How do I debug “evm: execution reverted” errors?
One of the most common errors Ethereum smart contract developers face isevm: execution reverted
or one of its variations depending on the SDK being used.
Ethereum Virtual Machine (EVM) does not have access to system I/O, as a result there is no handy logging output for debugging purposes. When a transaction fails to execute or validate, there is no easy way to find out the internal states leading up to the failure.
To get the reason for the failure, EVM allows a past transaction to be "replayed" and for the internal states to be introspected at each step. You can use a number of tooling options to debug a failed transaction.
Remix Debugger UI
Remix is a browser based IDE for Solidity developers. Remix supports a debugger extension that can take a transaction hash and step through the low-level EVM opcodes executed during the transaction processing, and display all the internal states (memory stack, storage variables, etc.) in an easy-to-use UI.
Connecting Remix to Kaleido
Follow the instructions here to connect to a Kaleido node.
Install and activate Debugger
In the left navigation bar, click thePlugin Manager icon to install and activate the DEBUGGER module.
Once activated, the Debugger is visible in the left navigation bar.
Click the Debugger icon to go into the UI. Fill in the hash of the failed transaction and click Start debugging. While stepping through the instructions use the Memory section to monitor possible error messages generated byrequire
statements, or the Storage section to see if the storage variables have the expected values.
Truffle debug
If you have the truffle project that contains the source code of the deployed contract, you can use the built-in command line based debugger.
From the truffle project root,truffle debug {txhash}
to launch the truffle command line debugger.
Follow the instructions here to specify truffle configurations to connect to a Kaleido node.
DIY with custom code
You can also use theeth_call
JSON RPC request to get the details of the transactions failure from the EVM. You must specify the same input parameters that were used to submit the original transaction, but instead of callingeth_sendTransaction
, useeth_call
to simulate the transaction execution and return the results.
A code snippet is provided below:
constethers=require('ethers');constappCred=`${user}:${password}`;// Kaleido application credentialsconstconnectionURL='u0abcdefgh-u012345678-rpc.us0-aws.kaleido.io';// without protocol (https://)constprovider=newethers.providers.JsonRpcProvider(`https://${appCred}@${connectionURL}`);functionhex_to_ascii(str1){varhex=str1.toString();varstr='';for(varn=0;n<hex.length;n+=2){str+=String.fromCharCode(parseInt(hex.substr(n,2),16));}returnstr;}asyncfunctionreason(txhash){lettx=awaitprovider.getTransaction(txhash);if(!tx){console.log('tx not found');}else{letcode=awaitprovider.call(tx,tx.blockNumber);letreason=hex_to_ascii(code.substr(138));console.log('revert reason:',reason);}}console.log(awaitreason());
REST API Gateway
Kaleido's REST API Gateway has built-in support for returning the error string when transactions failed.