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) world_state = WorldState() account = world_state.create_account(balance=1000000, address=101) account.code = Disassembly("60a760006000f000") environment = Environment(account, None, calldata, None, None, None) og_state = GlobalState(world_state, environment, None, MachineState(gas_limit=8000000)) og_state.transaction_stack.append( (MessageCallTransaction(world_state=WorldState(), gas_limit=8000000), None)) 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) created_contract_address = last_state.mstate.stack[-1].value created_contract_account = last_state.world_state.accounts[ created_contract_address] return last_state, created_contract_account
def test_vmtest( test_name: str, pre_condition: dict, action: dict, post_condition: dict ) -> None: # Arrange accounts = {} for address, details in pre_condition.items(): account = Account(address) account.code = Disassembly(details["code"][2:]) account.balance = int(details["balance"], 16) account.nonce = int(details["nonce"], 16) accounts[address] = account laser_evm = LaserEVM(accounts) # Act laser_evm.time = datetime.now() # TODO: move this line below and check for VmExceptions when gas has been implemented if post_condition == {}: return execute_message_call( laser_evm, callee_address=action["address"], caller_address=action["caller"], origin_address=action["origin"], code=action["code"][2:], gas=action["gas"], data=binascii.a2b_hex(action["data"][2:]), gas_price=int(action["gasPrice"], 16), value=int(action["value"], 16), ) # Assert assert len(laser_evm.open_states) == 1 world_state = laser_evm.open_states[0] model = get_model(next(iter(laser_evm.nodes.values())).states[0].mstate.constraints) for address, details in post_condition.items(): account = world_state[address] assert account.nonce == int(details["nonce"], 16) assert account.code.bytecode == details["code"][2:] for index, value in details["storage"].items(): expected = int(value, 16) if type(account.storage[int(index, 16)]) != int: actual = model.eval(account.storage[int(index, 16)]) actual = 1 if actual == True else 0 if actual == False else actual else: actual = account.storage[int(index, 16)] assert actual == expected
def test_vmtest(test_name: str, pre_condition: dict, action: dict, post_condition: dict) -> None: # Arrange accounts = {} for address, details in pre_condition.items(): account = Account(address) account.code = Disassembly(details['code'][2:]) account.balance = int(details['balance'], 16) account.nonce = int(details['nonce'], 16) accounts[address] = account laser_evm = LaserEVM(accounts) # Act laser_evm.time = datetime.now() try: execute_message_call( laser_evm, callee_address=action['address'], caller_address=action['caller'], origin_address=action['origin'], code=action['code'][2:], gas=action['gas'], data=binascii.a2b_hex(action['data'][2:]), gas_price=int(action['gasPrice'], 16), value=int(action['value'], 16) ) except VmException as e: if post_condition == {}: return else: raise e # Assert if 'Suicide' not in test_name: assert len(laser_evm.open_states) == 1 else: assert len(laser_evm.open_states) == 0 return world_state = laser_evm.open_states[0] for address, details in post_condition.items(): account = world_state[address] assert account.nonce == int(details['nonce'], 16) assert account.code.bytecode == details['code'][2:] for index, value in details['storage'].items(): expected = int(value, 16) actual = get_concrete_int(account.storage[int(index, 16)]) assert actual == expected
def test_execute_contract_creation(mocked_setup: MagicMock): # Arrange laser_evm = LaserEVM({}) laser_evm.open_states = [WorldState(), WorldState()] laser_evm.exec = MagicMock() mocked_setup.side_effect = _is_contract_creation # Act execute_contract_creation(laser_evm, "606000") # Assert # mocked_setup.assert_called() assert mocked_setup.call_count >= 1 # laser_evm.exec.assert_called_once() assert laser_evm.exec.call_count == 1 assert len(laser_evm.open_states) == 0
def test_execute(mocker): active_account = Account("0x00") environment = Environment(active_account, None, None, None, None, None) state_1 = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) state_1.mstate.stack = [1, 2] mocker.patch.object(state_1, "get_current_instruction") state_1.get_current_instruction.return_value = {"opcode": "PUSH"} state_2 = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) state_2.mstate.stack = [1, 2, 3] mocker.patch.object(state_2, "get_current_instruction") state_2.get_current_instruction.return_value = {"opcode": "ADD"} node_1 = Node("Test contract") node_1.states = [state_1, state_2] state_3 = GlobalState(None, environment, None, MachineState(gas_limit=8000000)) state_3.mstate.stack = [1, 2] mocker.patch.object(state_3, "get_current_instruction") state_3.get_current_instruction.return_value = {"opcode": "ADD"} node_2 = Node("Test contract") node_2.states = [state_3] edge = Edge(node_1.uid, node_2.uid) statespace = LaserEVM(None) statespace.edges = [edge] statespace.nodes[node_1.uid] = node_1 statespace.nodes[node_2.uid] = node_2 # Act result = TaintRunner.execute(statespace, node_1, state_1, [True, True]) # Assert print(result) assert len(result.records) == 3 assert result.records[2].states == [] assert state_3 in result.records[1].states
def test_execute_message_call(mocked_setup: MagicMock): # Arrange laser_evm = LaserEVM({}) world_state = WorldState() world_state.accounts["address"] = Account("address") laser_evm.open_states = [world_state] laser_evm.exec = MagicMock() mocked_setup.side_effect = _is_message_call # Act execute_message_call(laser_evm, "address") # Assert # laser_evm.exec.assert_called_once() assert laser_evm.exec.call_count == 1 # mocked_setup.assert_called_once() assert mocked_setup.call_count == 1 assert len(laser_evm.open_states) == 0
def test_execute_message_call(mocked_setup: MagicMock): # Arrange laser_evm = LaserEVM({}) world_state = WorldState() world_state.put_account(Account("0x0")) laser_evm.open_states = [world_state] laser_evm.exec = MagicMock() mocked_setup.side_effect = _is_message_call # Act execute_message_call(laser_evm, symbol_factory.BitVecVal(0, 256)) # Assert # laser_evm.exec.assert_called_once() assert laser_evm.exec.call_count == 1 # mocked_setup.assert_called_once() assert mocked_setup.call_count == 1 assert len(laser_evm.open_states) == 0
def test_calldata_constraints_in_transaction(): # Arrange laser_evm = LaserEVM({}) world_state = WorldState() correct_constraints = [MagicMock(), MagicMock(), MagicMock()] transaction = MessageCallTransaction(world_state, Account("ca11ee"), Account("ca114")) transaction.call_data = MagicMock() transaction.call_data.constraints = correct_constraints # Act _setup_global_state_for_execution(laser_evm, transaction) # Assert state = laser_evm.work_list[0] for constraint in correct_constraints: assert constraint in state.environment.calldata.constraints
def test_vmtest( test_name: str, environment: dict, pre_condition: dict, action: dict, gas_used: int, post_condition: dict, ) -> None: # Arrange if test_name == "gasprice": return accounts = {} for address, details in pre_condition.items(): account = Account(address) account.code = Disassembly(details["code"][2:]) account.balance = int(details["balance"], 16) account.nonce = int(details["nonce"], 16) accounts[address] = account laser_evm = LaserEVM(accounts) # Act laser_evm.time = datetime.now() final_states = execute_message_call( laser_evm, callee_address=action["address"], caller_address=action["caller"], origin_address=binascii.a2b_hex(action["origin"][2:]), code=action["code"][2:], gas_limit=int(action["gas"], 16), data=binascii.a2b_hex(action["data"][2:]), gas_price=int(action["gasPrice"], 16), value=int(action["value"], 16), track_gas=True, ) # Assert if gas_used is not None and gas_used < int(environment["currentGasLimit"], 16): # avoid gas usage larger than block gas limit # this currently exceeds our estimations gas_min_max = [(s.mstate.min_gas_used, s.mstate.max_gas_used) for s in final_states] gas_ranges = [g[0] <= gas_used for g in gas_min_max] assert all(map(lambda g: g[0] <= g[1], gas_min_max)) assert any(gas_ranges) if any( (v in test_name for v in ["error", "oog"])) and post_condition == {}: # no more work to do if error happens or out of gas assert len(laser_evm.open_states) == 0 else: assert len(laser_evm.open_states) == 1 world_state = laser_evm.open_states[0] model = get_model( next(iter(laser_evm.nodes.values())).states[0].mstate.constraints, enforce_execution_time=False, ) for address, details in post_condition.items(): account = world_state[address] assert account.nonce == int(details["nonce"], 16) assert account.code.bytecode == details["code"][2:] for index, value in details["storage"].items(): expected = int(value, 16) actual = account.storage[int(index, 16)] if isinstance(actual, Expression): actual = actual.value actual = 1 if actual is True else 0 if actual is False else actual else: if type(actual) == bytes: actual = int(binascii.b2a_hex(actual), 16) elif type(actual) == str: actual = int(actual, 16) assert actual == expected
def test_vmtest( test_name: str, environment: dict, pre_condition: dict, action: dict, gas_used: int, post_condition: dict, ) -> None: # Arrange if test_name in ignored_test_names: return world_state = WorldState() for address, details in pre_condition.items(): account = Account(address, concrete_storage=True) account.code = Disassembly(details["code"][2:]) account.nonce = int(details["nonce"], 16) for key, value in details["storage"].items(): account.storage[int(key, 16)] = int(value, 16) world_state.put_account(account) account.set_balance(int(details["balance"], 16)) laser_evm = LaserEVM() laser_evm.open_states = [world_state] # Act laser_evm.time = datetime.now() final_states = execute_message_call( laser_evm, callee_address=symbol_factory.BitVecVal(int(action["address"], 16), 256), caller_address=symbol_factory.BitVecVal(int(action["caller"], 16), 256), origin_address=symbol_factory.BitVecVal(int(action["origin"], 16), 256), code=action["code"][2:], gas_limit=int(action["gas"], 16), data=binascii.a2b_hex(action["data"][2:]), gas_price=int(action["gasPrice"], 16), value=int(action["value"], 16), track_gas=True, ) # Assert if gas_used is not None and gas_used < int(environment["currentGasLimit"], 16): # avoid gas usage larger than block gas limit # this currently exceeds our estimations gas_min_max = [(s.mstate.min_gas_used, s.mstate.max_gas_used) for s in final_states] gas_ranges = [g[0] <= gas_used for g in gas_min_max] assert all(map(lambda g: g[0] <= g[1], gas_min_max)) assert any(gas_ranges) if post_condition == {}: # no more work to do if error happens or out of gas assert len(laser_evm.open_states) == 0 else: assert len(laser_evm.open_states) == 1 world_state = laser_evm.open_states[0] for address, details in post_condition.items(): account = world_state[symbol_factory.BitVecVal( int(address, 16), 256)] assert account.nonce == int(details["nonce"], 16) assert account.code.bytecode == details["code"][2:] for index, value in details["storage"].items(): expected = int(value, 16) actual = account.storage[int(index, 16)] if isinstance(actual, Expression): actual = actual.value actual = 1 if actual is True else 0 if actual is False else actual else: if type(actual) == bytes: actual = int(binascii.b2a_hex(actual), 16) elif type(actual) == str: actual = int(actual, 16) assert actual == expected