This tool is used to track the values and addresses of slots (storage variables in Solidity) inside the Ethereum contract, as well as tracking logs (Solidity events).
- Partial symbolic execution provides the complete data on how a specific variable or slot address was calculated
- Suitable for learning about Solidity internals
- Written in Go
The easiest way to start using the tool is to use Docker
docker pull ioterw/tracevm
It is needed to copy the sample config from here, and save it as conf.json
Run TracEVM
cat conf.json | docker run --rm -i -p 4334:4334 -p 8545:8545 ioterw/tracevm
Project includes submodules, therefore it is needed to clone the project this way.
git clone https://github.com/ioterw/tracevm.git
cd tracevm
git submodule update --init
Also, make
, git
, go
and python3
should be preinstalled.
Additionally, Geth prerequisites are required to compile Geth.
It is possible to build TracEVM with such command.
./build.py geth
To open webview on address 127.0.0.1:4334 run the following command.
cd build
./run.py conf.json
TracEVM will be running!
It is expected to have Remix installed.
Choose External HTTP Provider
Connect by default address.
Let's imagine we have such contract.
Let's deploy the contract and see the output.
We see that:
- event type is final_slot, which means that this slot was written at the end of transaction (not reverted).
- further we see slot offsets (constant - initial slot, mapping - solidity keccak mapping magic, offset - offset from last value)
- short slot formula, which shows all cryptographic operations which were performed with slot
Also there is a full formula, which computes all needed data from initial initcode (or calldata).
{
"kv": {
// Possible values for engine:
// memory: data is stored in memory (root is ignored)
// leveldb: data is stored in leveldb (root is path for leveldb folders)
// riak: data is stored in riak (root is riak address)
// amnesia: data is not stored (root is ignored, past_unknown is switched to true)
"engine": "memory",
"root": ""
},
"logger": {
// _short postfix generally counts only cryptographic formulas (sha256, keccak etc.)
// as significant, other formulas are folded
"opcodes_short": ["e0", "e1"],
// outputs each occurence of TracEVM opcode
// (probably it is a good idea to try ["e0", "e1"], which are sload and sstore)
"opcodes": [],
"final_slots_short": true,
// outputs final slots which are set at the end of transaction
"final_slots": true,
"codes_short": false,
// outputs code of contracts which is set at the end of transaction
"codes": false,
"return_data_short": false,
// outputs return data at the end of transaction
"return_data": true,
"logs_short": false,
// outputs logs (events)
"logs": true,
// outputs solidity view of final slots (final_slots should be enabled)
"sol_view": true
},
// Possible values:
// path to output file
// if starts with "http://", starts http server on specified address
// if empty, outputs to terminal
"output": "http://127.0.0.1:4334",
// special mode, if enabled TracEVM thinks that there are some slots or code which
// existed before, therefore unknown, so it is marked as UNKNOWNSLOT or UNKNOWNCODE
"past_unknown": false
}
List of TracEVM opcodes can be found here
Other conf examples can be found here
Still the easiest way to start foundry is to use Docker
docker pull ioterw/tracevm-cast
Run cast
docker run --rm -it -p 4334:4334 ioterw/tracevm-cast run 0xf717d3585675a6453e7b433692d3d951d24a41c7c0a7d04d1ce114f2db3e036d --flashbots --debug
or
docker run --rm -it ioterw/tracevm-cast run 0xf717d3585675a6453e7b433692d3d951d24a41c7c0a7d04d1ce114f2db3e036d --flashbots
make
, git
, go
, python3
, rust
, gcc
(clang
on mac should be fine) should be preinstalled.
It is possible to build TracEVM for Foundry with such command.
./build.py foundry
To open webview for specific transaction on address 127.0.0.1:4334 run the following command.
cd build
./tracevm-cast run 0xf717d3585675a6453e7b433692d3d951d24a41c7c0a7d04d1ce114f2db3e036d --flashbots --debug
Please open an issue and supply solidity code that produced unexpected behaviour.