question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support contract error reason strings

See original GitHub issue
  • py-evm Version: 0.2.0a18
  • OS: linux
  • Python Version (python --version): 3.6

What is wrong?

Currently in the case of revert opcodes evm.exceptions.Revert is raised. Since solidity 0.4.22, revert can pass reason string. See solidity doc.

references: https://github.com/ethereum/EIPs/issues/838 https://github.com/ethereum/solidity/pull/3364#discussion_r180455883

How can it be fixed

One obstacle is how py-evm does contract calls, by running a transaction in a temporary state with gas price set to zero. Normally calls don’t have a gas set, so gas estimation is triggered, but then fails, masking the (would be) revert return value. Somewhat unrelated to the core issue of returning the reason string.

solidity code:

pragma solidity ^0.4.22;

contract DoRevert {
    function do_revert(bool _revert) public returns (string message) {
        if (_revert) {
            revert("ribbert, ribbert");
        }   
        return "No ribbert";
    }   
}

web3 with eth-tester provider py-evm backend

contract.functions.do_revert(True).call()

exception:

../../../web3/contract.py:1110: in call
    **self.kwargs
../../../web3/contract.py:1364: in call_contract_function
    return_data = web3.eth.call(call_transaction, block_identifier=block_id)
../../../venv/lib/python3.6/site-packages/eth_utils/functional.py:22: in inner
    return callback(fn(*args, **kwargs))
../../../web3/eth.py:294: in call
    [transaction, block_identifier],
../../../web3/manager.py:107: in request_blocking
    response = self._make_request(method, params)
../../../web3/manager.py:90: in _make_request
    return request_func(method, params)
../../../web3/middleware/gas_price_strategy.py:18: in middleware
    return make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/middleware/attrdict.py:18: in middleware
    response = make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/middleware/normalize_errors.py:9: in middleware
    result = make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/providers/eth_tester/middleware.py:309: in middleware
    fill_default_gas,
cytoolz/functoolz.pyx:589: in cytoolz.functoolz.pipe
    ???
cytoolz/functoolz.pyx:565: in cytoolz.functoolz.c_pipe
    ???
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/providers/eth_tester/middleware.py:295: in fill_default
    guess_val = guess_func(web3, transaction)
../../../web3/providers/eth_tester/middleware.py:287: in guess_gas
    return web3.eth.estimateGas(transaction) * 2
../../../web3/eth.py:304: in estimateGas
    [transaction],
../../../web3/manager.py:107: in request_blocking
    response = self._make_request(method, params)
../../../web3/manager.py:90: in _make_request
    return request_func(method, params)
../../../web3/middleware/gas_price_strategy.py:18: in middleware
    return make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/middleware/attrdict.py:18: in middleware
    response = make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/middleware/normalize_errors.py:9: in middleware
    result = make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/providers/eth_tester/middleware.py:320: in middleware
    return make_request(method, [filled_transaction] + params[1:])
../../../web3/middleware/fixture.py:12: in middleware
    return make_request(method, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/middleware/formatting.py:48: in apply_formatters
    response = make_request(method, formatted_params)
../../../web3/providers/eth_tester/main.py:46: in make_request
    response = delegator(self.ethereum_tester, params)
cytoolz/functoolz.pyx:232: in cytoolz.functoolz.curry.__call__
    ???
../../../web3/providers/eth_tester/defaults.py:36: in call_eth_tester
    return getattr(eth_tester, fn_name)(*fn_args, **fn_kwargs)
../../../venv/lib/python3.6/site-packages/eth_tester/main.py:466: in estimate_gas
    raw_gas_estimate = self.backend.estimate_gas(raw_transaction)

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
pipermerriamcommented, Jul 19, 2018

I think you’ve got this in the correct location (eth-tester). Once you get the PR open I’ve got some minor feedback, but overall it looks like a solid approach.

1reaction
jacqueswwwcommented, Jul 17, 2018

@carver may I try and tackle this one now? As I am anyways working on adding reason string support to vyper (https://github.com/ethereum/vyper/issues/889) 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Support reason string in assert · Issue #1686 · ethereum/solidity
Depends on EIP 140 (REVERT) to be fully accepted. assert(thing, "Thing is invalid"); would basically translate to if (!thing) revert("Thing ...
Read more >
concatenated string reason message in require() not displaying
When use abi.encodePacked() method, you must to put into it only strings. In your smart contract code, you're passing into this method two...
Read more >
Openzeppelin-solidity requires do not have string "reason ...
I'm curious, why is it that require statements inside the OZ-solidity contracts don't have a string "reason" message?
Read more >
Web3 1.2.5: Revert reason strings - Solidity developer
contract.methods.myMethod(…).call(…) you will see a new message like. Error: Your request got reverted with the following reason string: ...
Read more >
Expressions and Control Structures - Solidity
Solidity also supports exception handling in the form of try / catch ... If there is an error during decoding of catch Error(string...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found