Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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