Hi, guys. I'm fuzzing the py-evm py-evm 0.8.0b1 with other EVM implementations and I found that when calling opcode 0xFF SELFDESTRUCT , the funtion apply_computation() at eth/vm/computation.py will raise an AttributeError as AttributeError: 'function' object has no attribute 'mnemonic'. The corresponding line of python codes is opcode_fn = computation.get_opcode_fn(opcode).
I will give an json file with relevant trace of opcodes, maybe this will be helpful.
And the simple solidity contract I executed is:
contract ForceEth {
constructor() payable {}
receive() external payable {}
function forceEth(address to) public {
selfdestruct(payable(to));
}
}
The parameter I used to call the contract is 0xb349cb320000000000000000000000004dead63c2002b5f7997626feaca7f7ed0ba6ccf0.
I'd like to know whether this is sort of bug. If you need further information, feel free to reach out.
Thanks for your time!
Code that produced the error
from eth import constants
from eth.db.atomic import AtomicDB
from eth import constants
from eth.chains.base import MiningChain
from eth_utils import (to_wei, decode_hex, to_canonical_address,)
from eth.vm.forks.shanghai import ShanghaiVM
from eth_typing import Address
from eth_keys import keys
from eth.tools.transaction import new_transaction
from cytoolz import assoc
import argparse
def parse_args():
"""
Parse input arguments
"""
parser = argparse.ArgumentParser(description='Test a transaction')
# contract runtime bytecode $ solc xxx.sol --bin-runtime
parser.add_argument('--data', dest='data', default='', type=str)
# function signature bytecode
parser.add_argument('--sig', dest='signature', default='', type=str)
args = parser.parse_args()
return args
def funded_address_initial_balance():
return to_wei(0xffff, 'ether')
def base_genesis_state(funded_address, funded_address_initial_balance):
return {
funded_address: {
'balance': funded_address_initial_balance,
'nonce': 0,
'code': b'',
'storage': {},
}
}
def funded_address_private_key():
return keys.PrivateKey(
decode_hex('0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8')
)
def genesis_state(base_genesis_state,simple_contract_address, bytecode):
# base_genesis_state is a dict, simple_contract_address is key, {b,n,c,s} is value :)
result = assoc(
base_genesis_state,
simple_contract_address,
{
'balance': 0,
'nonce': 0,
'code': decode_hex(bytecode), # contract bytecode
'storage': {},
},
)
return result
GENESIS_PARAMS = {
'coinbase': Address(0x000000000000000000000000000000000000abcd.to_bytes(20,'big')),
'transaction_root': constants.BLANK_ROOT_HASH,
'receipt_root': constants.BLANK_ROOT_HASH,
'difficulty': 0,
'gas_limit': 0xffffff,
'timestamp': 0,
'extra_data': constants.GENESIS_EXTRA_DATA,
'nonce': b'\x00' * 8
}
def main():
args = parse_args()
init_address = to_canonical_address("8888f1f195afa192cfee860698584c030f4c9db1")
base_state = base_genesis_state(init_address, funded_address_initial_balance())
simple_contract_address = to_canonical_address("0x692a70d2e424a56d2c6c27aa97d1a86395877b3a")
klass = MiningChain.configure(
__name__='MyTestChain',
vm_configuration=(
(constants.GENESIS_BLOCK_NUMBER,ShanghaiVM),
)
)
SENDER = to_canonical_address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")
SENDER_PRIVATE_KEY = funded_address_private_key()
GENESIS_STATE = genesis_state(base_state, simple_contract_address,args.data)
chain = klass.from_genesis(AtomicDB(), GENESIS_PARAMS, GENESIS_STATE)
call_txn = new_transaction(
vm = chain.get_vm(),
from_ = to_canonical_address("0x1c7cd2d37ffd63856a5bd56a9af1643f2bcf545f"),
to = simple_contract_address,
gas=0xffffff,
data=decode_hex(args.signature),
)
result_bytes = chain.get_transaction_result(call_txn, chain.get_canonical_head())
if __name__ == '__main__':
main()
Full error output
Traceback (most recent call last):
File "/home/alleysira/EVMFuzzer/benchmarkEVMs/py-evm/runBytecode.py", line 109, in <module>
main()
File "/home/alleysira/EVMFuzzer/benchmarkEVMs/py-evm/runBytecode.py", line 105, in main
result_bytes = chain.get_transaction_result(call_txn, chain.get_canonical_head())
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/chains/base.py", line 479, in get_transaction_result
computation = state.costless_execute_transaction(transaction)
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/state.py", line 283, in costless_execute_transaction
return self.apply_transaction(free_transaction)
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/forks/frontier/state.py", line 219, in apply_transaction
return executor(transaction)
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/state.py", line 330, in __call__
computation = self.build_computation(message, transaction)
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/forks/berlin/state.py", line 37, in build_computation
return super().build_computation(message, transaction)
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/forks/frontier/state.py", line 147, in build_computation
computation = self.vm_state.computation_class.apply_message(
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/forks/frontier/computation.py", line 87, in apply_message
computation = cls.apply_computation(
File "/home/alleysira/EVMFuzzer/env/lib/python3.8/site-packages/eth/vm/computation.py", line 354, in apply_computation
opcode_fn.mnemonic,
AttributeError: 'function' object has no attribute 'mnemonic'
Fill this section in if you know how this could or should be fixed
I noticed that you guys changed the way to get opcode_fn to the following commands, don't know whether this problem will still happen.
for opcode in computation.code:
try:
opcode_fn = opcode_lookup[opcode]
except KeyError:
opcode_fn = InvalidOpcode(opcode)
Hey @Alleysira, can you please start testing with the latest version of the library? This was only relevant when debug logging. It was indeed a "bug" but it has since been fixed.
What happened?
Hi, guys. I'm fuzzing the py-evm py-evm 0.8.0b1 with other EVM implementations and I found that when calling opcode
0xFF SELFDESTRUCT
, the funtionapply_computation()
ateth/vm/computation.py
will raise an AttributeError asAttributeError: 'function' object has no attribute 'mnemonic'
. The corresponding line of python codes isopcode_fn = computation.get_opcode_fn(opcode)
. I will give an json file with relevant trace of opcodes, maybe this will be helpful. And the simple solidity contract I executed is:The parameter I used to call the contract is
0xb349cb320000000000000000000000004dead63c2002b5f7997626feaca7f7ed0ba6ccf0
. I'd like to know whether this is sort of bug. If you need further information, feel free to reach out. Thanks for your time!Code that produced the error
Full error output
Fill this section in if you know how this could or should be fixed
I noticed that you guys changed the way to get opcode_fn to the following commands, don't know whether this problem will still happen.
py-evm Version
0.8.0b1
Python Version
Python 3.8.10
Operating System
linux
Output from pip-freeze