Cleaned up code. Add create test.

pending-opcodes
Eric N 5 years ago
parent a9755b8c67
commit bc0f677e87
  1. 49
      mythril/laser/ethereum/instructions.py
  2. 16
      mythril/laser/ethereum/svm.py
  3. 63
      tests/instructions/create_test.py

@ -940,13 +940,13 @@ class Instruction:
if isinstance(global_state.current_transaction, ContractCreationTransaction): if isinstance(global_state.current_transaction, ContractCreationTransaction):
# Hacky way to ensure constructor arguments work - Pick some reasonably large size. # Hacky way to ensure constructor arguments work - Pick some reasonably large size.
no_of_bytes = len(disassembly.bytecode) // 2 no_of_bytes = len(disassembly.bytecode) // 2
# if isinstance(calldata, ConcreteCalldata): if isinstance(calldata, ConcreteCalldata):
# no_of_bytes += calldata.size + 5000 no_of_bytes += calldata.size
# else: else:
no_of_bytes += 0x200 # space for 16 32-byte arguments no_of_bytes += 0x200 # space for 16 32-byte arguments
# global_state.mstate.constraints.append( global_state.mstate.constraints.append(
# global_state.environment.calldata.size == no_of_bytes global_state.environment.calldata.size == no_of_bytes
# ) )
else: else:
no_of_bytes = len(disassembly.bytecode) // 2 no_of_bytes = len(disassembly.bytecode) // 2
@ -1139,9 +1139,9 @@ class Instruction:
8, 8,
) )
return [global_state] return [global_state]
for i in range(concrete_size):
for i in range(code_copy_size + calldata_copy_size):
if i < code_copy_size: if i < code_copy_size:
# copy from code
global_state.mstate.memory[concrete_memory_offset + i] = int( global_state.mstate.memory[concrete_memory_offset + i] = int(
code[ code[
2 2
@ -1154,7 +1154,7 @@ class Instruction:
# copy from calldata # copy from calldata
global_state.mstate.memory[ global_state.mstate.memory[
concrete_memory_offset + i concrete_memory_offset + i
] = calldata[calldata_copy_offset + i] ] = calldata[calldata_copy_offset + i - code_copy_size]
else: else:
global_state.mstate.memory[ global_state.mstate.memory[
concrete_memory_offset + i concrete_memory_offset + i
@ -1726,11 +1726,9 @@ class Instruction:
# Not supported # Not supported
return [global_state] return [global_state]
@staticmethod
def _create_transaction_helper( def _create_transaction_helper(
global_state, call_value, mem_offset, mem_size, op_code, create2_salt=None self, global_state, call_value, mem_offset, mem_size, create2_salt=None
): ):
mstate = global_state.mstate mstate = global_state.mstate
environment = global_state.environment environment = global_state.environment
world_state = global_state.world_state world_state = global_state.world_state
@ -1782,7 +1780,7 @@ class Instruction:
call_value=call_value, call_value=call_value,
contract_address=contract_address, contract_address=contract_address,
) )
raise TransactionStartSignal(transaction, op_code, global_state) raise TransactionStartSignal(transaction, self.op_code, global_state)
@StateTransition(is_state_mutation_instruction=True) @StateTransition(is_state_mutation_instruction=True)
def create_(self, global_state: GlobalState) -> List[GlobalState]: def create_(self, global_state: GlobalState) -> List[GlobalState]:
@ -1795,13 +1793,20 @@ class Instruction:
call_value, mem_offset, mem_size = global_state.mstate.pop(3) call_value, mem_offset, mem_size = global_state.mstate.pop(3)
return self._create_transaction_helper( return self._create_transaction_helper(
global_state, call_value, mem_offset, mem_size, self.op_code global_state, call_value, mem_offset, mem_size
) )
@StateTransition() @StateTransition()
def create_post(self, global_state: GlobalState) -> List[GlobalState]: def create_post(self, global_state: GlobalState) -> List[GlobalState]:
addr, call_value, mem_offset, mem_size = global_state.mstate.pop(4) call_value, mem_offset, mem_size = global_state.mstate.pop(3)
global_state.mstate.stack.append(addr) call_data = get_call_data(global_state, mem_offset, mem_offset + mem_size)
if global_state.last_return_data:
global_state.mstate.stack.append(
symbol_factory.BitVecVal(int(global_state.last_return_data, 16), 256)
)
else:
global_state.mstate.stack.append(symbol_factory.BitVecVal(0, 256))
return [global_state] return [global_state]
@StateTransition(is_state_mutation_instruction=True) @StateTransition(is_state_mutation_instruction=True)
@ -1814,13 +1819,19 @@ class Instruction:
call_value, mem_offset, mem_size, salt = global_state.mstate.pop(4) call_value, mem_offset, mem_size, salt = global_state.mstate.pop(4)
return self._create_transaction_helper( return self._create_transaction_helper(
global_state, call_value, mem_offset, mem_size, self.op_code, salt global_state, call_value, mem_offset, mem_size, salt
) )
@StateTransition() @StateTransition()
def create2_post(self, global_state: GlobalState) -> List[GlobalState]: def create2_post(self, global_state: GlobalState) -> List[GlobalState]:
addr, call_value, mem_offset, mem_size, salt = global_state.mstate.pop(5) call_value, mem_offset, mem_size, salt = global_state.mstate.pop(4)
global_state.mstate.stack.append(addr) call_data = get_call_data(global_state, mem_offset, mem_offset + mem_size)
if global_state.last_return_data:
global_state.mstate.stack.append(
symbol_factory.BitVecVal(int(global_state.last_return_data), 256)
)
else:
global_state.mstate.stack.append(symbol_factory.BitVecVal(0, 256))
return [global_state] return [global_state]
@StateTransition() @StateTransition()

@ -380,13 +380,6 @@ class LaserEVM:
:param return_data: :param return_data:
:return: :return:
""" """
if isinstance(global_state.current_transaction, ContractCreationTransaction):
# is this the proper place to put CREATE handle?
return_global_state.mstate.stack.append(
global_state.environment.active_account.address
)
return_global_state.mstate.min_gas_used += global_state.mstate.min_gas_used
return_global_state.mstate.max_gas_used += global_state.mstate.max_gas_used
return_global_state.mstate.constraints += global_state.mstate.constraints return_global_state.mstate.constraints += global_state.mstate.constraints
# Resume execution of the transaction initializing instruction # Resume execution of the transaction initializing instruction
@ -401,6 +394,15 @@ class LaserEVM:
return_global_state.environment.active_account = global_state.accounts[ return_global_state.environment.active_account = global_state.accounts[
return_global_state.environment.active_account.address.value return_global_state.environment.active_account.address.value
] ]
if isinstance(
global_state.current_transaction, ContractCreationTransaction
):
return_global_state.mstate.min_gas_used += (
global_state.mstate.min_gas_used
)
return_global_state.mstate.max_gas_used += (
global_state.mstate.max_gas_used
)
# Execute the post instruction handler # Execute the post instruction handler
new_global_states = Instruction( new_global_states = Instruction(

@ -6,20 +6,33 @@ from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.instructions import Instruction from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction from mythril.laser.ethereum.transaction.transaction_models import MessageCallTransaction
from mythril.laser.ethereum.state.calldata import ConcreteCalldata
from mythril.laser.ethereum.svm import LaserEVM from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.smt import symbol_factory from mythril.laser.smt import symbol_factory
# contract A {
# uint256 public val = 10;
# }
contract_init_code = "6080604052600a600055348015601457600080fd5b506084806100236000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633c6bb43614602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a72315820d3cfe7a909450a953cbd7e47d8c17477f2609baa5208d043e965efec69d1ed9864736f6c634300050b0032"
contract_runtime_code = "6080604052348015600f57600080fd5b506004361060285760003560e01c80633c6bb43614602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea265627a7a72315820d3cfe7a909450a953cbd7e47d8c17477f2609baa5208d043e965efec69d1ed9864736f6c634300050b0032"
last_state = None
created_contract_account = None
def execute_create():
global last_state
global created_contract_account
if not last_state and not created_contract_account:
code_raw = []
for i in range(len(contract_init_code) // 2):
code_raw.append(int(contract_init_code[2 * i : 2 * (i + 1)], 16))
calldata = ConcreteCalldata(0, code_raw)
def test_create():
creating_contract_runtime_code = "608060405260043610601c5760003560e01c8063efc81a8c146021575b600080fd5b60276029565b005b60006040516035906056565b604051809103906000f0801580156050573d6000803e3d6000fd5b50905050565b605b806100638339019056fe6080604052348015600f57600080fd5b50603e80601d6000396000f3fe6080604052600080fdfea265627a7a72315820f4040cbd444dcd2f49f1daf46a116eb32396f1cc84a9e79e3836d4bfe84d6bca64736f6c634300050b0032a265627a7a72315820e2350a73a28ed02b4dac678f2b77a330dc512c3cce8ca53fa1c30869f443553d64736f6c634300050b0032"
created_contract_init_code = "6080604052348015600f57600080fd5b50603e80601d6000396000f3fe6080604052600080fdfea265627a7a72315820f4040cbd444dcd2f49f1daf46a116eb32396f1cc84a9e79e3836d4bfe84d6bca64736f6c634300050b0032"
created_contract_runtime_code = "6080604052600080fdfea265627a7a72315820f4040cbd444dcd2f49f1daf46a116eb32396f1cc84a9e79e3836d4bfe84d6bca64736f6c634300050b0032"
world_state = WorldState() world_state = WorldState()
account = world_state.create_account(balance=1000, address=101) account = world_state.create_account(balance=1000000, address=101)
account.code = Disassembly(creating_contract_runtime_code) account.code = Disassembly("60a760006000f000")
environment = Environment(account, None, None, None, None, None) environment = Environment(account, None, calldata, None, None, None)
og_state = GlobalState( og_state = GlobalState(
world_state, environment, None, MachineState(gas_limit=8000000) world_state, environment, None, MachineState(gas_limit=8000000)
) )
@ -27,9 +40,33 @@ def test_create():
(MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None) (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)
) )
laser_evm = LaserEVM() laser = LaserEVM()
states = [og_state]
last_state = og_state
for state in states:
new_states, op_code = laser.execute_state(state)
last_state = state
if op_code == "STOP":
break
states.extend(new_states)
new_states, op_code = laser_evm.execute_state(og_state) created_contract_address = last_state.mstate.stack[-1].value
# checks created_contract_account = last_state.world_state.accounts[
created_contract_address
]
# TODO: come up with sequence, then grab an address from stack and check that its code is created. return last_state, created_contract_account
def test_create_has_code():
last_state, created_contract_account = execute_create()
assert created_contract_account.code.bytecode == contract_runtime_code
def test_create_has_storage():
last_state, created_contract_account = execute_create()
storage = created_contract_account.storage
# From contract, val = 10.
assert storage[symbol_factory.BitVecVal(0, 256)] == symbol_factory.BitVecVal(
10, 256
)

Loading…
Cancel
Save