eth-brownie / brownie

A Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine.
https://eth-brownie.readthedocs.io
MIT License
2.65k stars 552 forks source link

Solidity: Custom errors with "bytes32" cause TypeError #1749

Closed VseYugov closed 9 months ago

VseYugov commented 9 months ago

Environment information

What was wrong?

Reverting with custom error that contains bytes32 argument causes TypeError to be emitted:

File "brownie/_cli/run.py", line 51, in main
    return_value, frame = run(
  File "brownie/project/scripts.py", line 110, in run
    return_value = f_locals[method_name](*args, **kwargs)
  File "./scripts/deploy.py", line 6, in main
    tkn.transfer(accounts[1], 100, {'from': owner})
  File "brownie/network/contract.py", line 1781, in __call__
    return self.transact(*args, silent=silent)
  File "brownie/network/contract.py", line 1653, in transact
    return tx["from"].transfer(
  File "brownie/network/account.py", line 697, in transfer
    receipt._raise_if_reverted(exc)
  File "brownie/network/transaction.py", line 430, in _raise_if_reverted
    self._expand_trace()
  File "brownie/network/transaction.py", line 809, in _expand_trace
    self._get_trace()
  File "brownie/network/transaction.py", line 688, in _get_trace
    self._reverted_trace(trace)
  File "brownie/network/transaction.py", line 720, in _reverted_trace
    self._revert_msg = decode_typed_error(data.hex())
  File "brownie/exceptions.py", line 295, in decode_typed_error
    return f"{_errors[selector]['name']}: {', '.join(result)}"

This, in turn, causes tests in test suite to fail.

Example solidity code:


pragma solidity 0.8.19;
contract BroTest
{
  error SampleError(bytes32 err);
  bytes32 constant err = bytes32(uint256(0x01));
  constructor() 
  {
  }
  function error() external 
  {
    revert SampleError(err);
  }
}

Example python code:

from brownie import *

def main():
  con=BroTest.deploy({'from':accounts[0]}) 
  con.error()

Note: similar error happens for errors with integer arguments.

How can it be fixed?

The simplest fix would be to replace

f"{_errors[selector]['name']}: {', '.join(result)}"

with something like

f"{_errors[selector]['name']}: {', '.join([str(r) for r in result])}"