9

I have a smart contract with required message and pretend to use the required/validation message in front end.

require(bytes(hashAlreadyRegistered[hash]).length  == 0, "Hash already registered");

I'm trying to get the reason of revert using web3.eth.call.

By my understanding reading the doc if i pass the object generated by sendTransaction it will work. I think it is what i'm trying to do but didn't work so far.

My codes

sendTransaction method:

await canManipuleContract.methods.setDocumentHash('#_' + request.body.hash)
    .send({
      from: fromAddress,
      gas: 400000,
      gasPrice: 21000000000
    })
    .then(function(txRaw) {
      console.log(txRaw)
      return response.json( txRaw.transactionHash );
    })
    .catch(function(error) {
      handleRevert(error);
      console.log("Error: \n" + error);
      return response.json( 'error' )
    })
  }

web3.eth.call method:

function handleRevert( transactionObject ) {
    web3.eth.call( transactionObject, function( err, result ) {
      if ( ! err ) {
        console.log( 'result ' + result )
      }
      console.log( 'err ' +  err)
      //return response.json( 'Error: Returned error: execution reverted' )
    })
  }

The return value of handleRevert is always err 0x. In geth console i clearly see the value err and errdata returning the correct messages.

If i pass the contract address instead transactionObject in web3.eth.call method it always return Error: Returned error: execution reverted, but never the required message it self.

Version:

Geth: 1.9.15-stable

web3.js: ^1.2.8

What am i missing here? Any others methods to get the message required of smart contract will help here.

4 Answers 4

7

Try this,

async function getRevertReason(txHash){

  const tx = await web3.eth.getTransaction(txHash)

  var result = await web3.eth.call(tx, tx.blockNumber)

  result = result.startsWith('0x') ? result : `0x${result}`

  if (result && result.substr(138)) {

    const reason = web3.utils.toAscii(result.substr(138))
    console.log('Revert reason:', reason)
    return reason

  } else {

    console.log('Cannot get reason - No return value')

  }

}
4
  • 1
    Oh yes, it works. But i'm not been able to get the txHash of the var error of catch block to pass into getRevertReason function. With e.g. console.log( "Error: \n" + errorTransaction ) it prints the entire object of reverted transaction. If i for example console.log( "Error: \n" + errorTransaction.transactionHash ) or any other property it throws undefined. any tip here? Jun 27, 2020 at 1:19
  • 1
    i already tried to transform the object error to json and then parse or split it, but didn't sucessed. Jun 27, 2020 at 1:27
  • 1
    also tried to change the send method to use callback but error callback always return null instead the reverted transaction. Jun 27, 2020 at 1:56
  • 1
    remove await or write code inside try, catch block Jun 29, 2020 at 9:33
7

Web3 supports revert strings now: https://web3js.readthedocs.io/en/v1.2.8/web3-eth.html#handlerevert.

You can activate it easily by setting web3.eth.handleRevert = true. Now when you use call or send functions, precisely one of the following:

  • web3.eth.call()
  • web3.eth.sendTransaction()
  • contract.methods.myMethod(…).send(…)
  • contract.methods.myMethod(…).call(…)

you will see a new message like

Error: Your request got reverted with the following reason string: This is the revert reason!
3
  • didn't work. I put web3.eth.handleRevert = true after beside the provider. e.g. const canManipuleContract = createContract(contractAddress), web3.eth.handleRevert = true; Jun 27, 2020 at 1:22
  • @RAFAELDASILVA It seems there is a Web3 bug for geth 1.9.5. It's already fixed: github.com/ethereum/web3.js/pull/3571 but you'll have to wait for the next Web3 version to be released. Jun 27, 2020 at 3:21
  • this unfortunately doesn't work. "invalid arrayify value'"
    – noooooooob
    Feb 22, 2021 at 6:05
1

There is a handleRevert property in web3 itself. For me, it only works when I set web3.handleRevert = true instead of the documented option, web3.eth.handleRevert = true. The error message comes back in the reason attribute of the Error object that is thrown by the send() call of a smart contract method.

0

Follow this. Basically different RPC's will have different error response data. So you'll have to check the response and then simply use parseError on contract's interface.

https://ethereum.stackexchange.com/a/142364/128523

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.