The hevm
project is an implementation of the Ethereum virtual machine (EVM) made specifically for unit testing and debugging smart contracts. It is developed by DappHub and integrates especially well with the dapp
tool suite. The hevm
command line program can run unit tests, interactively debug contracts while showing the Solidity source, or run arbitrary EVM code.
Note: the hevm
test runner and debugger currently assumes the use of the ds-test
framework for Solidity unit tests and the dapp
tool suite.
After running dapp build
, you can run your unit test suite with
$ hevm dapp-test
or you can enter the interactive debugger using
$ hevm interactive
hevm -- Ethereum evaluator
Usage: hevm [<options>] <command>
or: hevm <command> --help
Commands:
exec Execute a given program with specified env & calldata
dapp-test Run unit tests
interactive Browse and run unit tests interactively
flatten Concat all dependencies for a given source file
bc-test Run an Ethereum Blockchain/GeneralState test
vm-test Run an Ethereum VMTest
compliance Run Blockchain or VMTest compliance report
emacs Emacs console
version Show hevm version
Esc
: exit debuggera
: step to starte
: step to endn
: step forwards by one instructionp
: step backwards by one instructionN
: step to the next source positionC-n
: step to the next source position and don't enterCALL
orCREATE
m
: toggle memory viewh
: show key-binding help
These environment variables can be used to control block parameters
DAPP_TEST_ADDRESS
DAPP_TEST_CALLER
DAPP_TEST_ORIGIN
DAPP_TEST_GAS_CREATE
DAPP_TEST_GAS_CALL
DAPP_TEST_BALANCE_CREATE
DAPP_TEST_BALANCE_CALL
DAPP_TEST_COINBASE
DAPP_TEST_NUMBER
DAPP_TEST_TIMESTAMP
DAPP_TEST_GAS_LIMIT
DAPP_TEST_GAS_PRICE
DAPP_TEST_DIFFICULTY
hevm
is distributed as part of the Dapp tools suite.
If you don't want to compile anything, and you're on x86-64 Linux, you can download a static binary from the "Releases" tab on GitHub. If the static binary complains about a "terminfo" file, you have to set the TERMINFO
environment variable; on Ubuntu, you should do
$ export TERMINFO=/lib/terminfo
(Put that in your ~/.bashrc
for convenience.)
If you can't or won't use Nix, the easiest way especially if you don't have GHC (the Haskell compiler) installed already, is to use Stack, which can take care of installing GHC for you. These commands should work:
$ curl -sSL https://get.haskellstack.org/ | sh
$ git clone https://github.com/dapphub/dapptools.git
$ cd dapptools/src/hevm && stack setup && stack install
Also, hevm is in Hackage so you can execute stack install hevm
to get it up and running.
If you prefer to use your own installation of GHC and the basic Haskell package manager, Cabal, simply run:
$ git clone https://github.com/dapphub/dapptools.git
$ cd dapptools/src/hevm && cabal configure && cabal install
Note: If you are on macOS when building with Stack, you will first need to install the secp256k1 and libff libraries. These commands should be enough:
$ git clone https://github.com/bitcoin-core/secp256k1.git
$ cd secp256k1
$ ./autogen.sh
$ ./configure --enable-module-recovery # for generating secp256k1_recovery.h
$ make
$ sudo make install
$ cd .. && rm -rf secp256k1 # optional (cleanup)
$ git clone https://github.com/scipr-lab/libff --recursive
$ cd libff
$ export LDFLAGS=-L/usr/local/opt/openssl/lib
$ export CPPFLAGS=-I/usr/local/opt/openssl/include
$ export CXXFLAGS=-I/usr/local/opt/openssl/include
$ ARGS="-DWITH_PROCPS=OFF -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/openssl -DCURVE=ALT_BN128"
$ sed -i '' 's/STATIC/SHARED/' libff/CMakeLists.txt
$ sed -i '' 's/STATIC/SHARED/' depends/CMakeLists.txt
$ mkdir build
$ cd build
$ CXXFLAGS="-fPIC $CXXFLAGS" cmake $ARGS ..
$ make && sudo make install
Since Hevm is an EVM implementation mainly dedicated to testing and exploration, it features a set of cheat codes
which can manipulate the environment in which the execution is run.
These can be accessed by calling into a contract (typically called Hevm
) at address 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D
, which implements the following methods:
-
function warp(uint x) public
sets the TIMESTAMP tox
. -
function store(address c, bytes32 loc, bytes32 val) public
sets the slotloc
toval
of contractc
.
You can find us in the DappHub chat at https://dapphub.chat/, especially the #dev
channel.