Hackathons are fantastic!
There’s nothing more enjoyable than gathering a group of friends, eating pizza, and hack on something you’ve always wanted to build but haven’t had time for.
When we learned that Consensys is organizing an internal hackathon, it didn’t take us long to find projects to hack on.
A couple of friends started hacking on “TURN”, a revolutionary token-based solution that could simplify our day-to-day operations. More on this in a future post.
Four of us gathered together to hack on a thing we always wanted to have: a tool to help us investigate internal smart contract state and security incidents.
And guess what? We won a prize too: 🏆 Winner - Category: Developer Enablement
The Smart Contract Inspector
We set out to solve the problem that block explorers do not provide access to all state variables. Currently, they can only query what is available via eth_calls
(public interfaces, public state variables).
private
only prevents other contracts from reading or modifying the information, but it will still be visible to the whole world outside of the blockchain.Our library provides a crucial feature that block explorers are missing — giving direct access to all state variables (public
, private
, internal
).
We solve that problem by resolving the variable to storage slot mappings using the compiler output generated by solc
. We then recursively decode the low-level slot data according to the mapped variable types.
💻 Demo
We released this tool as an open-source library on GitHub. Feel free to use it within your projects or get inspired. No real rocket science was involved in the creation of this library.
Libraries are cool 😎 but ready-to-use web apps are cooler 😄. So, here’s a proof-of-concept DEMO web app to show off the library’s capabilities.
Here’s how you can use the web app:
- Provide a mainnet contract address
- Hit
Load!
- this will fetch the contract source from etherscan.io - Wait for the
Contract Name
andContract Code
to be populated - Hit
Inspect!
How it works
The service attempts to compile the source code to retrieve the storageLayout mapping from the compiler output and then decodes the variables mapped to the slots.
Here is how this may look like:
- base types are resolved directly
- structs are resolved recursively
- dynamic array types are listed with all their entries
- mapping types cannot be resolved automatically as there is no way (other than inspecting all transactions) to know what mapping keys store values. We, therefore, return a function and let the user query specific keys of that mapping manually.
Here’s a nice example of a contract you may want to try out: 0x851bbf02ee2171d7ec1d45c35f33ee6e2985e2d9
⚠️ Limitations
There’re some limitations, though:
- The web app is a PoC and it is running on trial keys. :) It will break (especially if there are too many concurrent users). Be patient! It should auto-fix itself, as seen in nature.
solc
prior to version0.5.13
does not seem to produce thestorageLayout
output. It is, therefore, not supported.- The solidity version extraction regex that we use is very fragile and won’t work for source units that define more complex semantic solidity versions (
pragma solidity
)
If you want to improve this tool, start digging in the code. And if this tool is useful for you, please let us know.
References
- Smart Contract Inspector Web App
- Source Code on GitHub
- solc - storageLayout reference
- Solidity Data Representation Guide by ethdebug/ g. nicholas d’andrea - your excellent guide saved us a lot of time. You rock! ❤
Thinking about smart contract security? We can provide training, ongoing advice, and smart contract auditing. Contact us.