Esempio n. 1
0
def test_concrete_calldata_uninitialized_index(starting_calldata):
    # Arrange
    calldata = ConcreteCalldata(0, starting_calldata)

    # Act
    value = calldata[100]
    value2 = calldata.get_word_at(200)

    # Assert
    assert value == 0
    assert value2 == 0
Esempio n. 2
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
Esempio n. 3
0
def test_concrete_calldata_calldatasize():
    # Arrange
    calldata = ConcreteCalldata(0, [1, 4, 7, 3, 7, 2, 9])
    solver = Solver()

    # Act
    solver.check()
    model = solver.model()
    result = model.eval(calldata.calldatasize)

    # Assert
    assert result == 7
Esempio n. 4
0
def get_call_data(
    global_state: GlobalState,
    memory_start: Union[int, BitVec],
    memory_size: Union[int, BitVec],
):
    """Gets call_data from the global_state.

    :param global_state: state to look in
    :param memory_start: Start index
    :param memory_size: Size
    :return: Tuple containing: call_data array from memory or empty array if symbolic, type found
    """
    state = global_state.mstate
    transaction_id = "{}_internalcall".format(global_state.current_transaction.id)

    memory_start = cast(
        BitVec,
        (
            symbol_factory.BitVecVal(memory_start, 256)
            if isinstance(memory_start, int)
            else memory_start
        ),
    )
    memory_size = cast(
        BitVec,
        (
            symbol_factory.BitVecVal(memory_size, 256)
            if isinstance(memory_size, int)
            else memory_size
        ),
    )

    uses_entire_calldata = simplify(
        memory_size == global_state.environment.calldata.calldatasize
    )

    if is_true(uses_entire_calldata):
        return global_state.environment.calldata

    try:
        calldata_from_mem = state.memory[
            util.get_concrete_int(memory_start) : util.get_concrete_int(
                memory_start + memory_size
            )
        ]
        return ConcreteCalldata(transaction_id, calldata_from_mem)
    except TypeError:
        log.debug(
            "Unsupported symbolic memory offset %s size %s", memory_start, memory_size
        )
        return SymbolicCalldata(transaction_id)
Esempio n. 5
0
def test_concrete_calldata_constrain_index():
    # Arrange
    calldata = ConcreteCalldata(0, [1, 4, 7, 3, 7, 2, 9])
    solver = Solver()

    # Act
    value = calldata[2]
    constraint = value == 3

    solver.add([constraint])
    result = solver.check()

    # Assert
    assert str(result) == "unsat"
Esempio n. 6
0
def execute_message_call(
    laser_evm,
    callee_address,
    caller_address,
    origin_address,
    code,
    data,
    gas_limit,
    gas_price,
    value,
    track_gas=False,
) -> Union[None, List[GlobalState]]:
    """Execute a message call transaction from all open states.

    :param laser_evm:
    :param callee_address:
    :param caller_address:
    :param origin_address:
    :param code:
    :param data:
    :param gas_limit:
    :param gas_price:
    :param value:
    :param track_gas:
    :return:
    """
    # TODO: Resolve circular import between .transaction and ..svm to import LaserEVM here
    open_states = laser_evm.open_states[:]
    del laser_evm.open_states[:]

    for open_world_state in open_states:
        next_transaction_id = get_next_transaction_id()
        transaction = MessageCallTransaction(
            world_state=open_world_state,
            identifier=next_transaction_id,
            gas_price=gas_price,
            gas_limit=gas_limit,
            origin=origin_address,
            code=Disassembly(code),
            caller=caller_address,
            callee_account=open_world_state[callee_address],
            call_data=ConcreteCalldata(next_transaction_id, data),
            call_value=value,
        )

        _setup_global_state_for_execution(laser_evm, transaction)

    return laser_evm.exec(track_gas=track_gas)
Esempio n. 7
0
    def __init__(
        self,
        world_state: WorldState,
        callee_account: Account = None,
        caller: ExprRef = None,
        call_data=None,
        identifier: Optional[str] = None,
        gas_price=None,
        gas_limit=None,
        origin=None,
        code=None,
        call_value=None,
        init_call_data=True,
        static=False,
    ) -> None:
        assert isinstance(world_state, WorldState)
        self.world_state = world_state
        self.id = identifier or get_next_transaction_id()

        self.gas_price = (gas_price if gas_price is not None else
                          symbol_factory.BitVecSym(
                              "gasprice{}".format(identifier), 256))
        self.gas_limit = gas_limit

        self.origin = (origin
                       if origin is not None else symbol_factory.BitVecSym(
                           "origin{}".format(identifier), 256))
        self.code = code

        self.caller = caller
        self.callee_account = callee_account
        if call_data is None and init_call_data:
            self.call_data = SymbolicCalldata(self.id)  # type: BaseCalldata
        else:
            self.call_data = (call_data if isinstance(call_data, BaseCalldata)
                              else ConcreteCalldata(self.id, []))

        self.call_value = (call_value if call_value is not None else
                           symbol_factory.BitVecSym(
                               "callvalue{}".format(identifier), 256))
        self.static = static
        self.return_data = None  # type: str
Esempio n. 8
0
    def __init__(
        self,
        world_state: WorldState,
        callee_account: Account = None,
        caller: ExprRef = None,
        call_data=None,
        identifier=None,
        gas_price=None,
        gas_limit=None,
        origin=None,
        code=None,
        call_data_type=None,
        call_value=None,
        init_call_data=True,
    ):
        assert isinstance(world_state, WorldState)
        self.world_state = world_state
        self.id = identifier or get_next_transaction_id()

        self.gas_price = (gas_price if gas_price is not None else BitVec(
            "gasprice{}".format(identifier), 256))
        self.gas_limit = gas_limit

        self.origin = (origin if origin is not None else BitVec(
            "origin{}".format(identifier), 256))
        self.code = code

        self.caller = caller
        self.callee_account = callee_account
        if call_data is None and init_call_data:
            self.call_data = ConcreteCalldata(self.id, call_data)
        else:
            self.call_data = call_data if isinstance(call_data,
                                                     BaseCalldata) else None
        self.call_data_type = (call_data_type
                               if call_data_type is not None else BitVec(
                                   "call_data_type{}".format(identifier), 256))
        self.call_value = (call_value if call_value is not None else BitVec(
            "callvalue{}".format(identifier), 256))

        self.return_data = None
Esempio n. 9
0
def get_call_data(
    global_state: GlobalState,
    memory_start: Union[int, ExprRef],
    memory_size: Union[int, ExprRef],
):
    """
    Gets call_data from the global_state
    :param global_state: state to look in
    :param memory_start: Start index
    :param memory_size: Size
    :return: Tuple containing: call_data array from memory or empty array if symbolic, type found
    """
    state = global_state.mstate
    transaction_id = "{}_internalcall".format(
        global_state.current_transaction.id)
    try:
        # TODO: This only allows for either fully concrete or fully symbolic calldata.
        # Improve management of memory and callata to support a mix between both types.
        calldata_from_mem = state.memory[util.get_concrete_int(
            memory_start):util.get_concrete_int(memory_start + memory_size)]
        i = 0
        starting_calldata = []
        while i < len(calldata_from_mem):
            elem = calldata_from_mem[i]
            if isinstance(elem, int):
                starting_calldata.append(elem)
                i += 1
            else:  # BitVec
                for j in range(0, elem.size(), 8):
                    starting_calldata.append(Extract(j + 7, j, elem))
                    i += 1

        call_data = ConcreteCalldata(transaction_id, starting_calldata)
        call_data_type = CalldataType.CONCRETE
        logging.debug("Calldata: " + str(call_data))
    except TypeError:
        logging.debug("Unsupported symbolic calldata offset")
        call_data_type = CalldataType.SYMBOLIC
        call_data = SymbolicCalldata("{}_internalcall".format(transaction_id))

    return call_data, call_data_type