In this repository, we provide a model of the EVM in K.
bash <(curl https://kframework.org/install): install kup package manager.kup install kevm: install KEVM.kup list kevm: list available KEVM versions.kup update kevm: update to latest KEVM version.
NOTE: The first run will take longer to fetch all the libraries and compile sources. (30m to 1h)
These may be useful for learning KEVM and K (newest to oldest):
- K, KEVM and Foundry Integration overview
- Jello Paper, a nice presentation of this repository.
- 20 minute tour of the semantics at 2017 Devcon3.
- KEVM 1.0 technical report, especially sections 3 and 5.
- KEVM Paper at CSF'18/FLoC.
To get support for KEVM, please join our Discord Channel.
If you want to start proving with KEVM, refer to tests/specs/examples/README.md.
The following files constitute the KEVM semantics:
- network.md provides the status codes reported to an Ethereum client on execution exceptions.
- json-rpc.md is an implementation of JSON RPC in K.
- evm-types.md provides the (functional) data of EVM (256-bit words, wordstacks, etc...).
- serialization.md provides helpers for parsing and unparsing data (hex strings, recursive-length prefix, Merkle trees, etc.).
- evm.md is the main KEVM semantics, containing EVM’s configuration and transition rules.
- gas.md contains all information relevant to gas.
- schedule.md contains all information relevant to EVM schedules.
These additional files extend the semantics to make the repository more useful:
- buf.md defines the
#bufbyte-buffer abstraction for use during symbolic execution. - abi.md defines the Contract ABI Specification for use in proofs and easy contract/function specification.
- hashed-locations.md defines the
#hashedLocationabstraction used to specify Solidity-generated storage layouts. - edsl.md combines the previous three abstractions for ease-of-use.
These files are used for testing the semantics itself:
- state-utils.md provides functionality for EVM initialization, setup, and querying.
- driver.md is an execution harness for KEVM, providing a simple language for describing tests/programs.
There are two backends of K available: LLVM for concrete execution and Haskell for symbolic execution.
This repository generates the build-products for each backend in $XDG_CACHE_HOME/evm-semantics-<digest>.
Run install-build-deps to install the required OS-supplied dependencies.
There are some additional notes for specific systems:
Ubuntu:
- The script works for ≥ 22.04.
- On Ubuntu < 18.04, you'll need to skip
libsecp256k1-devand instead build it from source (via ourMakefile) usingmake libsecp256k1.
Arch:
- No issues known.
MacOS:
-
After installing the Command Line Tools, Homebrew, and getting the blockchain plugin, run:
-
NOTE: It is recommended to use the homebrew version of
flexand XCode. -
If you are building on an Apple Silicon machine, ensure that your
PATHis set up correctly before runningmake depsormake k-deps. You can do so usingdirenvby copyingmacos-envrcto.envrc, then runningdirenv allow. -
If the build on macOS still fails, you can also try adding the following lines to the top of your
MakefileunderUNAME_S:ifeq ($(UNAME_S), Darwin) SHELL := /usr/local/bin/bash PATH := $(pwd)/.build/usr/bin:$(PATH) endif
- Haskell Stack.
Note that the version of the
stacktool provided by your package manager might not be recent enough. Please follow installation instructions from the Haskell Stack website linked above.
To upgrade stack (if needed):
stack upgrade
export PATH=$HOME/.local/bin:$PATHYou need to install the K Framework on your system, see the instructions there. The fastest way is via the kup package manager, with which you can do to get the correct version of K:
kup install k.openssl --version v$(cat deps/k_release)You can also drop into a single development shell with the correct version of K on path by doing:
kup shell k.openssl --version v$(cat deps/k_release)Make sure Python (>=3.10) and uv are installed on your system.
You can check your setup by running make.
You also need to get the blockchain plugin submodule and install it.
git submodule update --init --recursive
uv --project kevm-pyk run -- kdist --verbose build evm-semantics.pluginTo change the default compiler:
CXX=clang++-15 uv --project kevm-pyk run -- kdist --verbose build evm-semantics.pluginOn Apple silicon:
APPLE_SILICON=true uv --project kevm-pyk run -- kdist --verbose build evm-semantics.pluginFinally, you can build the semantics.
uv --project kevm-pyk run -- kdist --verbose build -j6You can build specific targets using options evm-semantics.{llvm,kllvm,kllvm-runtime,haskell,haskell-standalone,plugin}, e.g.:
uv --project kevm-pyk run -- kdist build -j2 evm-semantics.llvm evm-semantics.haskellTargets can be cleaned with
uv --project kevm-pyk run -- kdist cleanFor more information, refer to kdist --help and the dist.py module.
To execute tests from the Ethereum Test Set, the submodule needs to be fetched first.
git submodule update --init --recursive -- tests/ethereum-testsThe tests are run using the supplied Makefile.
The following subsume all other tests:
make test: All of the quick tests.make test-all: All of the quick and slow tests.
These are the individual test-suites (all of these can be suffixed with -all to also run slow tests):
make test-vm: VMTests from the Ethereum Test Set.make test-bchain: Subset of BlockchainTests from the Ethereum Test Set.make test-proof: Proofs from the Verified Smart Contracts.make test-interactive: Tests of thekevmcommand.
All these targets call pytest under the hood. You can pass additional arguments to the call by appending them to variable PYTEST_ARGS. E.g. run
make test-vm PYTEST_ARGS+=-vv
to execute VMTests with increased verbosity, and
make test-vm PYTEST_ARGS+=-n0
to execute them on a single worker.
Files produced by test runs, e.g. kompiled definition and logs, can be found in /tmp/pytest-of-<user>/.
If built from the source, the kevm-pyk executable will be installed in a virtual environment handled by uv.
You can call kevm-pyk --help to get a quick summary of how to use the script.
Run the file tests/ethereum-tests/BlockchainTests/GeneralStateTests/VMTests/vmArithmeticTest/add0.json:
uv --project kevm-pyk run -- kevm-pyk run tests/ethereum-tests/BlockchainTests/GeneralStateTests/VMTests/vmArithmeticTest/add0.json --schedule DEFAULT --mode VMTESTSTo enable the debug symbols for the llvm backend, build using this command:
uv --project kevm-pyk run -- kdist build evm-semantics.llvm --arg enable-llvm-debug=trueTo debug a conformance test, add the --debugger flag to the command:
uv --project kevm-pyk run -- kevm-pyk run tests/ethereum-tests/BlockchainTests/GeneralStateTests/stExample/add11.json --target llvm --mode NORMAL --schedule CANCUN --chainid 1 --debuggerAlways have your build up-to-date.
- If using the kup package manager, run
kup install kevm --version .to install the local version. - If building from source:
makeneeds to be re-run if you touch any of thekevm-pykcode.uv --project kevm-pyk run -- kdist build <target> --forceneeds to be re-run if you touch any of this repos files.uv --project kevm-pyk run -- kdist cleanis a safe way to remove the target directory.
We now support building KEVM using nix flakes.
To set up nix flakes you will need to be on nix 2.4 or higher and follow the instructions here.
For example, if you are on a standard Linux distribution, such as Ubuntu, first install nix
and then enable flakes by editing either ~/.config/nix/nix.conf or /etc/nix/nix.conf and adding:
experimental-features = nix-command flakes
This is needed to expose the Nix 2.0 CLI and flakes support that are hidden behind feature-flags.
By default, Nix will build the project and its transitive dependencies from source, which can take up to an hour. We recommend setting up the binary cache to speed up the build process significantly.
To build KEVM, run:
nix build .#kevmThis will build all of KEVM and K and put a link to the resulting binaries in the result/ folder.
NOTE: Mac users, especially those running M1/M2 Macs may find nix segfaulting on occasion. If this happens, try running the nix command like this: GC_DONT_GC=1 nix build .
If you want to temporarily add the kevm binary to the current shell, run
nix shell .#kevmNix can also be used to quickly profile different versions of the Haskell backend. Simply run:
nix build github:runtimeverification/evm-semantics#profile \
--override-input k-framework/haskell-backend github:runtimeverification/haskell-backend/<HASH> \
-o prof-<HASH>replacing <HASH> with the commit you want to run profiling against.
If you want to profile against a working version of the Haskell backend repository, simply cd into the root of the repo and run:
nix build github:runtimeverification/evm-semantics#profile \
--override-input k-framework/haskell-backend $(pwd) \
-o prof-my-featureTo compare profiles, you can use:
nix run github:runtimeverification/evm-semantics#compare-profiles -- prof-my-feature prof-<HASH>This will produce a nice table with the times for both versions of the haskell-backend.
Note that #profile pre-pends the output of kore-exec --version to the profile run, which is then used as a tag by the #compare-profiles script.
Therefore, any profiled local checkout of the haskell-backend will report as dirty-ghc8107 in the resulting table.
This repository can build two pieces of documentation for you, the Jello Paper and the 2017 Devcon3 presentation.
For the presentations in the media directory, you'll need pdflatex, commonly provided with texlive-full, and pandoc.
sudo apt install texlive-full pandocTo build all the PDFs (presentations and reports) available in the media/ directory, use:
make media- EVM Yellowpaper: Original specification of EVM.
- LEM Semantics of EVM
- EVM Opcode Interactive Reference
- Solidity ABI Encoding
For more information about the K Framework, refer to these sources:
- The K Tutorial
- Semantics-Based Program Verifiers for All Languages
- Reachability Logic Resources
- Matching Logic Resources
- Logical Frameworks: Discussion of logical frameworks.