6

When calling a contract function that I expect to fail by invoking revert, I receive the following JSON-RPC response:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001150726f64756374206e6f7420666f756e64000000000000000000000000000000"
}

I believe the result field is a description of the error. How do I convert it into a human-readable format?

0

3 Answers 3

7

The data you are receiving is an ABI encoded error string, returned from a reverting contract. From the Solidity documentation:

The revert function .. takes an optional string message containing details about the error that is passed back to the caller.

The provided string is abi-encoded as if it were a call to a function Error(string).

To decode the error message:

  • The first 4 bytes (08c379a0) are the function selector - they can be discarded.
  • The remaining hex string is decoded according to the ABI specification for strings.

Using the Python eth-abi library to decode your example:

>>> from hexbytes import HexBytes
>>> from eth_abi import decode_abi
>>> response = HexBytes('0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001150726f64756374206e6f7420666f756e64000000000000000000000000000000')
>>> decode_abi(['string'], response)
('Product not found',)
1

You can use a try catch block to call the contract function. If call fails then you can interact with revert message in catch block.

try {
    var inOwner = await simpleCI.methods.isOwner().call({
        from: accounts[1]
    });
} catch (err) {
    console.log(err);
}

and this is a sample err object:

{
    name: 'o',
    results: {
        '0x68187df294516d3942805b2a2f26a5dfa343db17100112deaef1b5b554c6c62c': {
            error: 'revert',
            program_counter: 400,
            return: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000094e6f74206f776e65720000000000000000000000000000000000000000000000',
            reason: 'Not owner'
        }
    },
    hashes: [
        '0x68187df294516d3942805b2a2f26a5dfa343db17100112deaef1b5b554c6c62c'
    ],
    message: 'VM Exception while processing transaction: revert Not owner'
}
1

This answer might come a little late but here's a little utility that you can use to decode any kind of error response from the RPC response without having to mess with the data in result. You can check out ethers-decode-error.

What you have looks like a normal revert error but this utility will help to handle normal reverts as well as any other kind of errors that could possibly be thrown. Here's an example using it to catch your error:

Install ethers-decode-error:

npm install --save ethers-decode-error ethers

Then in your code:

import { ErrorDecoder } from 'ethers-decode-error'

const errorDecoder = ErrorDecoder.create()

const WETH = new ethers.Contract('0xC02aa...756Cc2', abi, provider)
try {
  const tx = await WETH.transfer('0x0', amount)
  await tx.wait()
} catch (err) {
  const { reason } = await errorDecoder.decode(err)
  // Prints "ERC20: transfer to the zero address"
  console.log('Revert reason:', reason)
}

More examples can be found here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.