Getting Ethereum Transaction Revert Reasons the Easy Way

Use the eth-revert-reason NPM package to easily derive the reason for an Ethereum transaction failure

Shane Fontaine
Authereum
3 min readApr 22, 2020

--

Failed Ethereum transactions sometimes include a reason for the transaction reversion. Retrieving these reasons is harder than it should be, especially given how useful these messages are. Inconsistencies between Geth and Parity, Infura and Alchemy, and even ethers.js and web3.js add to this complexity.

Authereum’s newly open-sourced eth-revert-reason NPM package handles all the work for you and gives you exactly what you want — a reason for the failed transaction.

Use this as an NPM package or as a simple CLI command by installing it today! The code below shows how easy this now is:

NPM

const txHash = '0xf212cc42d0eded75041225d71da6c3a8348bdb...'
await getRevertReason(txHash) // 'I accidentally killed it.'

CLI

> getRevertReason 0xf212cc42d0eded75041225d71da6c3a8348bdb...
I accidentally killed it.

Under the hood

The happy-path scenario for retrieving the revert reason is a simple eth_call with some parsing of the resulting string and a UTF-8 conversion. Libraries like ethers.js help with the formatting of the input, but even without a library it is relatively straight-forward.

The non-happy-path scenarios are where it gets more complicated.

Changing Error Messages

A little-known fact in the Ethereum ecosystem is that error messages for transactions may differ based on the context of the block they are called in. Take this Authereum transaction as an example:

Failed Authereum Transaction

You can see that it failed with the revert reason BA: Insufficient gas (ETH) for refund. However, if you run eth-revert-reason on this transaction hash, you will get the error “LKMTA: Auth key is invalid”. This is because the message you receive can change depending on the context of the block you are calling from. If you run eth-revert-reason and pass in that transaction hash, you will get the expected error!

const txHash = '0x6ea1798a2d0d21db18d6e45ca00f230160b05f172f...'
const network = 'mainnet'
let blockNumber = 9892242
await getRevertReason(txHash, network, blockNumber)
// 'BA: Insufficient gas (ETH) for refund'
blockNumber = 9919263
await getRevertReason(txHash, network, blockNumber)
// 'LKMTA: Auth key is invalid'

Running an Archive Node

Everyone’s favorite subject — the beloved archive node —plays a role in this conversation as well.

A non-archive node allows you to call a transaction from the context of a specific block. However, if the block was mined more than 128 blocks ago, then a non-archive node will throw, claiming that the node cannot access old blocks.

An archive node allows you to make a call from a block that is older than 128 blocks and can result in more accurate revert messages, as seen in the example above.

Figuring out what node you are using under-the-hood may be more difficult than you would hope, and it involves making RPC calls and inferring the node type based on the result. Hopefully this changes in the near future.

Kovan and Parity Traces

Another annoyance is the distinction between Kovan and the other networks, as Kovan is only accessible with the Parity client.

In order to retrieve the revert message on Kovan, your node must have Parity traces enabled, which is not a feature of Infura (at this time) and is not too common either.

Slightly modified string parsing must be done in this case as well.

Conclusion

Ethereum transaction revert reasons were once hard to retrieve but no longer are. Alchemy handles this well by offering Parity traces and archive nodes coupled with their package, but other providers like Infura either don’t provide this or layer on additional costs.

Please feel free to contribute to the project or ask any questions.

We hope this helps to advance and grow the entire Ethereum ecosystem!

If you want to share your thoughts or learn more, jump in our Telegram and let us know what’s on your mind. Follow us on Twitter for all of the latest news and updates from the Authereum team.

--

--