ethereum / py-evm

A Python implementation of the Ethereum Virtual Machine
https://py-evm.readthedocs.io/en/latest/
MIT License
2.26k stars 647 forks source link

Invalid opcode Exception with Solidity 0.5.7 but not with 0.5.3 #1748

Open relyt29 opened 5 years ago

relyt29 commented 5 years ago

What is wrong?

Here are two separate compiles of a contract from solidity. One was compiled with solc version 0.5.7+commit.6da8b019.Emscripten.clang and another with solc version 0.5.3+commit.10d17f24.Emscripten.clang - both were made with the compiler on remix.ethereum.org. One works just fine, the other has an opcode which causes an exception in pyevm.

First the solidity source:

pragma solidity^0.5.0;

contract Foo {

    string public bar;
    event barred(string _bar);

    constructor() public {
        bar = "hello world";
    }

    function setBar(string memory _bar) public {
        bar = _bar;
        emit barred(_bar);
    }

}

And now the python used to run it:

from eth_tester import EthereumTester, PyEVMBackend
from web3 import Web3, EthereumTesterProvider

class TestExample(unittest.TestCase):

    def setUp(self):
        self.tester_provider = EthereumTesterProvider()
        self.eth_tester = self.tester_provider.ethereum_tester
        self.w3 = Web3(self.tester_provider)
        self.test_accounts_tuple = self.eth_tester.get_accounts()
        self.deploy_address = str(self.test_accounts_tuple[0])
        self.w3.personal.unlockAccount(self.deploy_address, "")
        abi = """[{"anonymous":false,"inputs":[{"indexed":false,"name":"_bar","type":"string"}],"name":"barred","type":"event"},{"constant":false,"inputs":[{"name":"_bar","type":"string"}],"name":"setBar","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[],"name":"bar","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]"""
        bytecode53 = """608060405234801561001057600080fd5b506040805190810160405280600b81526020017f68656c6c6f20776f726c640000000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50610107565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b808211156101005760008160009055506001016100e8565b5090565b90565b6103bb806101166000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c01000000000000000000000000000000000000000000000000000000009004806397bc14aa14610058578063febb0f7e14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b61024c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac9291906102ea565b507f5f71ad82e16f082de5ff496b140e2fbc8621eeb37b36d59b185c3f1364bbd529816040518080602001828103825283818151815260200191508051906020019080838360005b8381101561020f5780820151818401526020810190506101f4565b50505050905090810190601f16801561023c5780820380516001836020036101000a031916815260200191505b509250505060405180910390a150565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102e25780601f106102b7576101008083540402835291602001916102e2565b820191906000526020600020905b8154815290600101906020018083116102c557829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032b57805160ff1916838001178555610359565b82800160010185558215610359579182015b8281111561035857825182559160200191906001019061033d565b5b509050610366919061036a565b5090565b61038c91905b80821115610388576000816000905550600101610370565b5090565b9056fea165627a7a72305820ae6ca683d45ee8a71bba45caee29e4815147cd308f772c853a20dfe08214dbb50029"""
        bytecode57 = """608060405234801561001057600080fd5b506040518060400160405280600b81526020017f68656c6c6f20776f726c640000000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50610107565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b808211156101005760008160009055506001016100e8565b5090565b90565b61039e806101166000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806397bc14aa1461003b578063febb0f7e146100f6575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610179565b005b6100fe61022f565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b806000908051906020019061018f9291906102cd565b507f5f71ad82e16f082de5ff496b140e2fbc8621eeb37b36d59b185c3f1364bbd529816040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f25780820151818401526020810190506101d7565b50505050905090810190601f16801561021f5780820380516001836020036101000a031916815260200191505b509250505060405180910390a150565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102c55780601f1061029a576101008083540402835291602001916102c5565b820191906000526020600020905b8154815290600101906020018083116102a857829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061030e57805160ff191683800117855561033c565b8280016001018555821561033c579182015b8281111561033b578251825591602001919060010190610320565b5b509050610349919061034d565b5090565b61036f91905b8082111561036b576000816000905550600101610353565b5090565b9056fea165627a7a723058204a4a74d2a8e0a915cddf35c1924895f205286cb72a49ff22971a4feb840750740029"""

        self.contract = self.w3.eth.contract(abi=abi, bytecode=bytecode57)
        tx_hash = self.contract.constructor().transact({'from': self.deploy_address, 'gas': 2000000})
        tx_receipt = self.w3.eth.waitForTransactionReceipt(tx_hash, 180)
        self.contract_address = tx_receipt.contractAddress
        self.contract_object = self.w3.eth.contract(abi=abi, address=self.contract_address)

    def test_hello_world(self):
        hw = self.contract_object.functions.bar().call()
        print(hw)

if __name__ == "__main__":
    unittest.main()

And finally, the error that you get:

Traceback (most recent call last):
  File "/REDACTED/venv/lib/python3.7/site-packages/eth_tester/utils/formatting.py", line 85, in wrapper
    return to_wrap(*args, **kwargs)
  File "/REDACTED/venv/lib/python3.7/site-packages/eth_tester/backends/pyevm/main.py", line 511, in estimate_gas
    return self.chain.estimate_gas(spoofed_transaction)
  File "/REDACTED/venv/lib/python3.7/site-packages/eth/chains/base.py", line 615, in estimate_gas
    return self.gas_estimator(state, transaction)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/eth/estimators/gas.py", line 65, in binary_gas_search
    raise error
  File "/REDACTED/venv/lib/python3.7/site-packages/eth/vm/computation.py", line 560, in apply_computation
    opcode_fn(computation=computation)
  File "/REDACTED/venv/lib/python3.7/site-packages/eth/vm/logic/invalid.py", line 16, in __call__
    computation.code.pc - 1,
eth.exceptions.InvalidInstruction: Invalid opcode 0x1c @ 31

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "example.py", line 52, in test_hello_world
    hw = self.contract_object.functions.bar().call()
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/contract.py", line 1115, in call
    **self.kwargs
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/contract.py", line 1364, in call_contract_function
    return_data = web3.eth.call(call_transaction, block_identifier=block_id)
  File "/REDACTED/venv/lib/python3.7/site-packages/eth_utils/functional.py", line 46, in inner
    return callback(fn(*args, **kwargs))
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/eth.py", line 295, in call
    [transaction, block_identifier],
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/manager.py", line 110, in request_blocking
    response = self._make_request(method, params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/manager.py", line 93, in _make_request
    return request_func(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 50, in apply_formatters
    response = make_request(method, params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/gas_price_strategy.py", line 18, in middleware
    return make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/attrdict.py", line 18, in middleware
    response = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/normalize_errors.py", line 9, in middleware
    result = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/providers/eth_tester/middleware.py", line 313, in middleware
    fill_default_gas,
  File "cytoolz/functoolz.pyx", line 589, in cytoolz.functoolz.pipe
  File "cytoolz/functoolz.pyx", line 565, in cytoolz.functoolz.c_pipe
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/providers/eth_tester/middleware.py", line 299, in fill_default
    guess_val = guess_func(web3, transaction)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/providers/eth_tester/middleware.py", line 291, in guess_gas
    return web3.eth.estimateGas(transaction) * 2
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/eth.py", line 305, in estimateGas
    [transaction],
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/manager.py", line 110, in request_blocking
    response = self._make_request(method, params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/manager.py", line 93, in _make_request
    return request_func(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 50, in apply_formatters
    response = make_request(method, params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/gas_price_strategy.py", line 18, in middleware
    return make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/attrdict.py", line 18, in middleware
    response = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/normalize_errors.py", line 9, in middleware
    result = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/providers/eth_tester/middleware.py", line 324, in middleware
    return make_request(method, [filled_transaction] + params[1:])
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/fixture.py", line 12, in middleware
    return make_request(method, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/middleware/formatting.py", line 48, in apply_formatters
    response = make_request(method, formatted_params)
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/providers/eth_tester/main.py", line 46, in make_request
    response = delegator(self.ethereum_tester, params)
  File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__
  File "/REDACTED/venv/lib/python3.7/site-packages/web3/providers/eth_tester/defaults.py", line 36, in call_eth_tester
    return getattr(eth_tester, fn_name)(*fn_args, **fn_kwargs)
  File "/REDACTED/venv/lib/python3.7/site-packages/eth_tester/main.py", line 445, in estimate_gas
    raw_gas_estimate = self.backend.estimate_gas(raw_transaction)
  File "/REDACTED/venv/lib/python3.7/site-packages/eth_tester/utils/formatting.py", line 88, in wrapper
    raise old_to_new_exceptions[type(e)] from e
eth_tester.exceptions.TransactionFailed
pipermerriam commented 5 years ago

cc @njgheorghita I think this indicates that there is more to do in the eth-tester update.

https://github.com/ethereum/eth-tester/blob/5d1ba6d8828257ba8db30984b3ffdd35ccd91f6c/eth_tester/backends/pyevm/main.py#L163

Still hard pinned to the Byzantium VM.

njgheorghita commented 5 years ago

@pipermerriam Fix is here - was able to get the test passing in the above script by updating the default vm rules to Constantinople. Will merge / cut release if it looks 👍 - we'll also need to cut new web3 releases (v4 & v5) so the fix is available via pip install web3[tester]

carver commented 5 years ago

Thanks for writing this up @relyt29 ! It really helps get things moving.