This project is a library that is able to ingest EVM bytecode and discover an approximate storage layout for the contract described by that bytecode. It is not intended to be a full decompiler, but is instead a tool highly specialised for performing this discovery process.
See our announcement for more details or check the deepdive post on our blog.
This discovery process is performed, in broad strokes, as follows:
- Bytecode is ingested and disassembled into an instruction stream that is amenable to analysis. This is a sequence of Opcodes that is equivalent to the bytecode.
- The stream of instructions is executed symbolically on a specialised EVM implementation. This execution is both speculative and total, exploring all possible code paths that can influence the type attributed to a given storage location.
- For each value seen in the program during execution, the VM builds a symbolic value (a little tree structure) that represents the operations performed to that particular piece of "data".
- These execution trees are passed to a type inference process. This process starts by lifting, which turns low-level constructs into more-general high-level ones. The results of this are then fed to inference rules that output type inference judgements about the trees they analyse. Finally, these inferences are combined with a unifier to perform whole-program type inference.
- The resolved types associated with each storage slot are then turned into a storage layout that describes the type of each storage slot that was encountered.
For more information on the process with specific reference to concrete pieces of code, see the
documentation in lib.rs
. This also provides a basic usage example for the library,
though more complex ones can be found in the tests.
The primary means of extending this library to get better layouts is by extending the type inference engine. This is done by either writing new lifting passes or inference rules, and you can find more information on this process in the documentation on extending the library.
If you want to contribute code or documentation (non-code contributions are always welcome) to this project, please take a look at our contributing documentation. It provides an overview of how to get up and running, as well as what the contribution process looks like for the library. We are also available on our Telegram group if you have any questions.