Skip to content

Instantly share code, notes, and snippets.

@gluk64
Last active August 27, 2023 12:53
Show Gist options
  • Star 39 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save gluk64/fdea559472d957f1138ed93bcbc6f78a to your computer and use it in GitHub Desktop.
Save gluk64/fdea559472d957f1138ed93bcbc6f78a to your computer and use it in GitHub Desktop.
// This is universal, works with Infura -- set provider accordingly
const ethers = require('ethers')
//const provider = ethers.getDefaultProvider('rinkeby')
const provider = new ethers.providers.JsonRpcProvider(process.env.WEB3_URL)
function hex_to_ascii(str1) {
var hex = str1.toString();
var str = '';
for (var n = 0; n < hex.length; n += 2) {
str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
}
return str;
}
async function reason() {
var args = process.argv.slice(2)
let hash = args[0]
console.log('tx hash:', hash)
console.log('provider:', process.env.WEB3_URL)
let tx = await provider.getTransaction(hash)
if (!tx) {
console.log('tx not found')
} else {
let code = await provider.call(tx, tx.blockNumber)
let reason = hex_to_ascii(code.substr(138))
console.log('revert reason:', reason)
}
}
reason()
#!/bin/bash
# This is for geth
# Fetching revert reason -- https://ethereum.stackexchange.com/questions/48383/how-to-receive-revert-reason-for-past-transactions
if [ -z "$1" ]
then
echo "Usage: revert-reason <TX_HASH>"
exit
fi
TX=$1
SCRIPT=" tx = eth.getTransaction( \"$TX\" ); tx.data = tx.input; eth.call(tx, tx.blockNumber)"
geth --exec "$SCRIPT" attach http://localhost:8545 | cut -d '"' -f 2 | cut -c139- | xxd -r -p
echo
@jjgonecrypto
Copy link

Awesome - just what I was looking for!

@jjgonecrypto
Copy link

Though you can use ethers.utils.toUtf8String('0x' + code.substr(138)); on L27 and not need hex_to_ascii at all

@amaurer
Copy link

amaurer commented May 30, 2019

Thanks for putting this together. I forked and made a few mods including the above recommendation.

@jjgonecrypto
Copy link

Nice. I bundled this up with some other features into https://github.com/justinjmoses/eth-reveal/

@msigwart
Copy link

msigwart commented Jul 16, 2019

Thanks, this is quite useful! I also forked and added a Go version of the script: https://gist.github.com/msigwart/d3e374a64c8718f8ac5ec04b5093597f

@shanefontaine
Copy link

I added an NPM package, eth-revert-reason that will return the reason in any case (any network, Geth or Parity).

@EvilJordan
Copy link

Please excuse the ignorance, but this does not work with ganache, correct?
provider.call() is not working for me after successfully retrieving the transaction, so maybe I'm doing something wrong?

@EvilJordan
Copy link

Apologies for the multiple questions.

I tested this on Rinkeby (https://rinkeby.etherscan.io/tx/0x512b05c7fadf8c30fc62fb9400bbeb47169174d908648ac531f5db9dd1aeaa96) and, as you can see, it failed (on purpose by me setting the gas too low).

When this transaction was first called, and failed, my try/catch block output as part of the return in my console logs:

reason: 'transaction failed',
code: 'CALL_EXCEPTION',

However, when reason runs, no code is returned for the provider.call(), which I believe is somehow equivalent to provider.getTransaction(). Likewise, if I run provider.getTransactionReceipt(hash), the output contains no mention of a failure (unless one looks at status: 0):

{
  to: '0xaa4041ca5d6d14e566DCE4A70d3b9ad585F0Da64',
  from: '0xA0b5B95617a5c6Bf0116d47C2a4c93164aaE3328',
  contractAddress: null,
  transactionIndex: 3,
  gasUsed: BigNumber { _hex: '0x01823e', _isBigNumber: true },
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  blockHash: '0x07c16e6922a64606c31bb742621eb1a93a57724c7cda771522315ef1d3bcc580',
  transactionHash: '0x512b05c7fadf8c30fc62fb9400bbeb47169174d908648ac531f5db9dd1aeaa96',
  logs: [],
  blockNumber: 6825108,
  confirmations: 64,
  cumulativeGasUsed: BigNumber { _hex: '0x034d77', _isBigNumber: true },
  status: 0,
  byzantium: true
}

Am I misunderstanding something here about how this is supposed to work?

@Elyx0
Copy link

Elyx0 commented May 29, 2021

  const a = await provider.getTransaction('0xdc6506137b443a6ad6734b0047a6d00d31748110589b379d72461bc57e510e94');
  try {
    let code = await provider.call(a, a.blockNumber)
  } catch (err) {
    const code = err.data.replace('Reverted ','');
    console.log({err});
    let reason = ethers.utils.toUtf8String('0x' + code.substr(138));
    console.log('revert reason:', reason);
  }

I had to catch one more level for it to work "ethers": "5.0.3",

@agatsoh
Copy link

agatsoh commented Jul 12, 2021

The bash script gives an error

-bash: ./revert-reason.sh: line 9: syntax error near unexpected token `fi'
-bash: ./revert-reason.sh: line 9: `fi'

@ludekvodicka
Copy link

Should this snippet work also with latest 5.4 ethers.js please?

I'm trying it together with typescript and there is type issue between getTransaction() returning TransactionResponse and call() method requesting TransactionRequest.

When I tried to re-type it then I'm still receiving only:

code:'CALL_EXCEPTION'
data:'0x'
reason:'missing revert data in call exception'

@axell9641
Copy link

Though you can use ethers.utils.toUtf8String('0x' + code.substr(138)); on L27 and not need hex_to_ascii at all

Wow it works!! But is this really all I need?

@leeleoo
Copy link

leeleoo commented Dec 5, 2022

Should this snippet work also with latest 5.4 ethers.js please?

I'm trying it together with typescript and there is type issue between getTransaction() returning TransactionResponse and call() method requesting TransactionRequest.

When I tried to re-type it then I'm still receiving only:

code:'CALL_EXCEPTION'
data:'0x'
reason:'missing revert data in call exception'

same with me

@gigamesh
Copy link

This works for me:

     const tx = await provider.getTransaction(txHash)
      const response = await provider.call(
        {
          to: tx.to,
          from: tx.from,
          nonce: tx.nonce,
          gasLimit: tx.gasLimit,
          gasPrice: tx.gasPrice,
          data: tx.data,
          value: tx.value,
          chainId: tx.chainId,
          type: tx.type ?? undefined,
          accessList: tx.accessList,
        },
        tx.blockNumber,
      )

     // This should be your error code
      const firstFourBytes = response.slice(0, 10)

@tonynguyen136
Copy link

Hope this will help you guys!

image

image

@gHashTag
Copy link

Hope this will help you guys!

image

image

Was it difficult to paste the code? Why did you send a screenshot? 🤦🏼‍♂️

@gHashTag
Copy link

gHashTag commented Aug 27, 2023

  const tx = await provider.getTransaction(txHash)
  const response = await provider.call(
    {
      to: tx.to,
      from: tx.from,
      nonce: tx.nonce,
      gasLimit: tx.gasLimit,
      gasPrice: tx.gasPrice,
      data: tx.data,
      value: tx.value,
      chainId: tx.chainId,
      type: tx.type ?? undefined,
      accessList: tx.accessList,
    },
    tx.blockNumber,
  )
  const reason = ethers.utils.toUtf8String('0x' + response.substring(138))
  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment