Пример #1
0
def log_XX(computation: ComputationAPI, topic_count: int) -> None:
    if topic_count < 0 or topic_count > 4:
        raise TypeError("Invalid log topic size.  Must be 0, 1, 2, 3, or 4")

    mem_start_position, size = computation.stack_pop_ints(2)

    if not topic_count:
        topics: Tuple[int, ...] = ()
    elif topic_count > 1:
        topics = computation.stack_pop_ints(topic_count)
    else:
        topics = (computation.stack_pop1_int(), )

    data_gas_cost = constants.GAS_LOGDATA * size
    topic_gas_cost = constants.GAS_LOGTOPIC * topic_count
    total_gas_cost = data_gas_cost + topic_gas_cost

    computation.consume_gas(
        total_gas_cost,
        reason="Log topic and data gas cost",
    )

    computation.extend_memory(mem_start_position, size)
    log_data = computation.memory_read_bytes(mem_start_position, size)

    computation.add_log_entry(
        account=computation.msg.storage_address,
        topics=topics,
        data=log_data,
    )
Пример #2
0
def return_op(computation: ComputationAPI) -> None:
    start_position, size = computation.stack_pop_ints(2)

    computation.extend_memory(start_position, size)

    computation.output = computation.memory_read_bytes(start_position, size)
    raise Halt('RETURN')
Пример #3
0
    def get_call_params(self, computation: ComputationAPI) -> CallParams:
        gas = computation.stack_pop1_int()
        to = force_bytes_to_address(computation.stack_pop1_bytes())

        (
            value,
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop_ints(5)

        return (
            gas,
            value,
            to,
            None,  # sender
            None,  # code_address
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            True,  # should_transfer_value,
            computation.msg.is_static,
        )
Пример #4
0
def returndatacopy(computation: ComputationAPI) -> None:
    (
        mem_start_position,
        returndata_start_position,
        size,
    ) = computation.stack_pop_ints(3)

    if returndata_start_position + size > len(computation.return_data):
        raise OutOfBoundsRead(
            "Return data length is not sufficient to satisfy request.  Asked "
            f"for data from index {returndata_start_position} "
            f"to {returndata_start_position + size}.  "
            f"Return data is {len(computation.return_data)} bytes in length.")

    computation.extend_memory(mem_start_position, size)

    word_count = ceil32(size) // 32
    copy_gas_cost = word_count * constants.GAS_COPY

    computation.consume_gas(copy_gas_cost, reason="RETURNDATACOPY fee")

    value = computation.return_data[
        returndata_start_position:returndata_start_position + size]

    computation.memory_write(mem_start_position, size, value)
Пример #5
0
def revert(computation: ComputationAPI) -> None:
    start_position, size = computation.stack_pop_ints(2)

    computation.extend_memory(start_position, size)

    computation.output = computation.memory_read_bytes(start_position, size)
    raise Revert(computation.output)
Пример #6
0
    def get_call_params(self, computation: ComputationAPI) -> CallParams:
        gas = computation.stack_pop1_int()
        code_address = force_bytes_to_address(computation.stack_pop1_bytes())

        (
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
        ) = computation.stack_pop_ints(4)

        to = computation.msg.storage_address
        sender = computation.msg.sender
        value = computation.msg.value

        return (
            gas,
            value,
            to,
            sender,
            code_address,
            memory_input_start_position,
            memory_input_size,
            memory_output_start_position,
            memory_output_size,
            False,  # should_transfer_value,
            computation.msg.is_static,
        )
Пример #7
0
def sstore(computation: ComputationAPI) -> None:
    slot, value = computation.stack_pop_ints(2)

    computation.state.set_storage(
        address=computation.msg.storage_address,
        slot=slot,
        value=value,
    )
Пример #8
0
def xor(computation: ComputationAPI) -> None:
    """
    Bitwise XOr
    """
    left, right = computation.stack_pop_ints(2)

    result = left ^ right

    computation.stack_push_int(result)
Пример #9
0
def or_op(computation: ComputationAPI) -> None:
    """
    Bitwise Or
    """
    left, right = computation.stack_pop_ints(2)

    result = left | right

    computation.stack_push_int(result)
Пример #10
0
def and_op(computation: ComputationAPI) -> None:
    """
    Bitwise And
    """
    left, right = computation.stack_pop_ints(2)

    result = left & right

    computation.stack_push_int(result)
Пример #11
0
def net_sstore(gas_schedule: NetSStoreGasSchedule,
               computation: ComputationAPI) -> None:
    slot, value = computation.stack_pop_ints(2)

    current_value = computation.state.get_storage(
        address=computation.msg.storage_address,
        slot=slot,
    )

    original_value = computation.state.get_storage(
        address=computation.msg.storage_address, slot=slot, from_journal=False)

    gas_refund = 0

    if current_value == value:
        gas_cost = gas_schedule.base
    else:
        if original_value == current_value:
            if original_value == 0:
                gas_cost = gas_schedule.create
            else:
                gas_cost = gas_schedule.update

                if value == 0:
                    gas_refund += gas_schedule.remove_refund
        else:
            gas_cost = gas_schedule.base

            if original_value != 0:
                if current_value == 0:
                    gas_refund -= gas_schedule.remove_refund
                if value == 0:
                    gas_refund += gas_schedule.remove_refund

            if original_value == value:
                if original_value == 0:
                    gas_refund += (gas_schedule.create - gas_schedule.base)
                else:
                    gas_refund += (gas_schedule.update - gas_schedule.base)

    computation.consume_gas(
        gas_cost,
        reason=
        (f"SSTORE: {encode_hex(computation.msg.storage_address)}"
         f"[{slot}] -> {value} (current: {current_value} / original: {original_value})"
         ))

    if gas_refund:
        computation.refund_gas(gas_refund)

    computation.state.set_storage(
        address=computation.msg.storage_address,
        slot=slot,
        value=value,
    )
Пример #12
0
def eq(computation: ComputationAPI) -> None:
    """
    Equality
    """
    left, right = computation.stack_pop_ints(2)

    if left == right:
        result = 1
    else:
        result = 0

    computation.stack_push_int(result)
Пример #13
0
def gt(computation: ComputationAPI) -> None:
    """
    Greater Comparison
    """
    left, right = computation.stack_pop_ints(2)

    if left > right:
        result = 1
    else:
        result = 0

    computation.stack_push_int(result)
Пример #14
0
def byte_op(computation: ComputationAPI) -> None:
    """
    Bitwise And
    """
    position, value = computation.stack_pop_ints(2)

    if position >= 32:
        result = 0
    else:
        result = (value // pow(256, 31 - position)) % 256

    computation.stack_push_int(result)
Пример #15
0
def sha3(computation: ComputationAPI) -> None:
    start_position, size = computation.stack_pop_ints(2)

    computation.extend_memory(start_position, size)

    sha3_bytes = computation.memory_read_bytes(start_position, size)
    word_count = ceil32(len(sha3_bytes)) // 32

    gas_cost = constants.GAS_SHA3WORD * word_count
    computation.consume_gas(gas_cost, reason="SHA3: word gas cost")

    result = keccak(sha3_bytes)

    computation.stack_push_bytes(result)
Пример #16
0
def sgt(computation: ComputationAPI) -> None:
    """
    Signed Greater Comparison
    """
    left, right = map(
        unsigned_to_signed,
        computation.stack_pop_ints(2),
    )

    if left > right:
        result = 1
    else:
        result = 0

    computation.stack_push_int(signed_to_unsigned(result))
Пример #17
0
def calldatacopy(computation: ComputationAPI) -> None:
    (
        mem_start_position,
        calldata_start_position,
        size,
    ) = computation.stack_pop_ints(3)

    computation.extend_memory(mem_start_position, size)

    word_count = ceil32(size) // 32
    copy_gas_cost = word_count * constants.GAS_COPY

    computation.consume_gas(copy_gas_cost, reason="CALLDATACOPY fee")

    value = computation.msg.data_as_bytes[
        calldata_start_position:calldata_start_position + size]
    padded_value = value.ljust(size, b'\x00')

    computation.memory_write(mem_start_position, size, padded_value)
Пример #18
0
def codecopy(computation: ComputationAPI) -> None:
    (
        mem_start_position,
        code_start_position,
        size,
    ) = computation.stack_pop_ints(3)

    computation.extend_memory(mem_start_position, size)

    word_count = ceil32(size) // 32
    copy_gas_cost = constants.GAS_COPY * word_count

    computation.consume_gas(
        copy_gas_cost,
        reason="CODECOPY: word gas cost",
    )

    with computation.code.seek(code_start_position):
        code_bytes = computation.code.read(size)

    padded_code_bytes = code_bytes.ljust(size, b'\x00')

    computation.memory_write(mem_start_position, size, padded_code_bytes)
Пример #19
0
def extcodecopy(computation: ComputationAPI) -> None:
    account = force_bytes_to_address(computation.stack_pop1_bytes())
    (
        mem_start_position,
        code_start_position,
        size,
    ) = computation.stack_pop_ints(3)

    computation.extend_memory(mem_start_position, size)

    word_count = ceil32(size) // 32
    copy_gas_cost = constants.GAS_COPY * word_count

    computation.consume_gas(
        copy_gas_cost,
        reason='EXTCODECOPY: word gas cost',
    )

    code = computation.state.get_code(account)

    code_bytes = code[code_start_position:code_start_position + size]
    padded_code_bytes = code_bytes.ljust(size, b'\x00')

    computation.memory_write(mem_start_position, size, padded_code_bytes)
Пример #20
0
    def get_stack_data(self, computation: ComputationAPI) -> CreateOpcodeStackData:
        endowment, memory_start, memory_length, salt = computation.stack_pop_ints(4)

        return CreateOpcodeStackData(endowment, memory_start, memory_length, salt)