Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-7702 - devnet-6 version #1114

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/evmone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_library(evmone
baseline_instruction_table.cpp
baseline_instruction_table.hpp
constants.hpp
delegation.hpp
eof.cpp
eof.hpp
instructions.hpp
Expand Down
42 changes: 42 additions & 0 deletions lib/evmone/delegation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2025 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include <evmc/bytes.hpp>
#include <evmc/evmc.hpp>
#include <cassert>

namespace evmone
{
using evmc::bytes_view;

/// Prefix of code for delegated accounts
/// defined by [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702)
constexpr uint8_t DELEGATION_MAGIC_BYTES[] = {0xef, 0x01, 0x00};
constexpr bytes_view DELEGATION_MAGIC{DELEGATION_MAGIC_BYTES, std::size(DELEGATION_MAGIC_BYTES)};

/// Check if code contains EIP-7702 delegation designator
inline constexpr bool is_code_delegated(bytes_view code) noexcept
{
return code.starts_with(DELEGATION_MAGIC);
}

/// Get EIP-7702 delegate address from the code of addr, if it is delegated.
inline std::optional<evmc::address> get_delegate_address(
const evmc::address& addr, const evmc::HostInterface& host) noexcept
{
uint8_t prefix[std::size(DELEGATION_MAGIC)] = {};
host.copy_code(addr, 0, prefix, std::size(prefix));

if (!is_code_delegated(bytes_view{prefix, std::size(prefix)}))
return {};

evmc::address delegate_address;
assert(host.get_code_size(addr) ==
std::size(DELEGATION_MAGIC) + std::size(delegate_address.bytes));
host.copy_code(
addr, std::size(prefix), delegate_address.bytes, std::size(delegate_address.bytes));
return delegate_address;
}
} // namespace evmone
9 changes: 5 additions & 4 deletions lib/evmone/instructions_calls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2019 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include "delegation.hpp"
#include "eof.hpp"
#include "instructions.hpp"

Expand All @@ -28,19 +29,19 @@ inline std::variant<evmc::address, Result> get_target_address(
if (state.rev < EVMC_PRAGUE)
return addr;

const auto delegate_addr = state.host.get_delegate_address(addr);
if (delegate_addr == evmc::address{})
const auto delegate_addr = get_delegate_address(addr, state.host);
if (!delegate_addr)
return addr;

const auto delegate_account_access_cost =
(state.host.access_account(delegate_addr) == EVMC_ACCESS_COLD ?
(state.host.access_account(*delegate_addr) == EVMC_ACCESS_COLD ?
instr::cold_account_access_cost :
instr::warm_storage_read_cost);

if ((gas_left -= delegate_account_access_cost) < 0)
return Result{EVMC_OUT_OF_GAS, gas_left};

return delegate_addr;
return *delegate_addr;
}
} // namespace

Expand Down
26 changes: 1 addition & 25 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@

namespace evmone::state
{
namespace
{
/// The value returned by EXTCODEHASH of an address with EIP-7702 delegation designator.
/// See https://eips.ethereum.org/EIPS/eip-7702#delegation-designation
constexpr auto EIP7702_CODE_HASH_SENTINEL =
0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329_bytes32;
} // namespace

bool Host::account_exists(const address& addr) const noexcept
{
const auto* const acc = m_state.find(addr);
Expand Down Expand Up @@ -89,7 +81,7 @@ namespace
/// unconditionally, because EOF contracts dot no have EXTCODE* instructions.
bytes_view extcode(bytes_view code) noexcept
{
return (is_eof_container(code) || is_code_delegated(code)) ? code.substr(0, 2) : code;
return is_eof_container(code) ? code.substr(0, 2) : code;
}

/// Check if an existing account is the "create collision"
Expand Down Expand Up @@ -132,9 +124,6 @@ bytes32 Host::get_code_hash(const address& addr) const noexcept
if (is_eof_container(code))
return EOF_CODE_HASH_SENTINEL;

if (is_code_delegated(code))
return EIP7702_CODE_HASH_SENTINEL;

return acc->code_hash;
}

Expand Down Expand Up @@ -563,17 +552,4 @@ void Host::set_transient_storage(
m_state.journal_transient_storage_change(addr, key, slot);
slot = value;
}

address Host::get_delegate_address(const address& addr) const noexcept
{
const auto raw_code = m_state.get_code(addr);

if (!is_code_delegated(raw_code))
return {};

address delegate;
assert(raw_code.size() == std::size(DELEGATION_MAGIC) + sizeof(delegate));
std::copy_n(&raw_code[std::size(DELEGATION_MAGIC)], sizeof(delegate), delegate.bytes);
return delegate;
}
} // namespace evmone::state
2 changes: 0 additions & 2 deletions test/state/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ class Host : public evmc::Host
public:
evmc_access_status access_account(const address& addr) noexcept override;

address get_delegate_address(const address& addr) const noexcept override;

private:
evmc_access_status access_storage(const address& addr, const bytes32& key) noexcept override;

Expand Down
5 changes: 3 additions & 2 deletions test/state/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "host.hpp"
#include "state_view.hpp"
#include <evmone/constants.hpp>
#include <evmone/delegation.hpp>
#include <evmone/eof.hpp>
#include <algorithm>

Expand Down Expand Up @@ -604,9 +605,9 @@ TransactionReceipt transition(const StateView& state_view, const BlockInfo& bloc
auto message = build_message(tx, tx_props.execution_gas_limit, rev);
if (tx.to.has_value())
{
if (const auto delegate = host.get_delegate_address(*tx.to))
if (const auto delegate = get_delegate_address(*tx.to, host))
{
message.code_address = delegate;
message.code_address = *delegate;
message.flags |= EVMC_DELEGATED;
host.access_account(message.code_address);
}
Expand Down
11 changes: 0 additions & 11 deletions test/state/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,4 @@ TransactionReceipt transition(const StateView& state, const BlockInfo& block,
[[nodiscard]] std::variant<TransactionProperties, std::error_code> validate_transaction(
const StateView& state_view, const BlockInfo& block, const Transaction& tx, evmc_revision rev,
int64_t block_gas_left, int64_t blob_gas_left) noexcept;

/// Prefix of code for delegated accounts
/// defined by [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702)
constexpr uint8_t DELEGATION_MAGIC_BYTES[] = {0xef, 0x01, 0x00};
constexpr bytes_view DELEGATION_MAGIC{DELEGATION_MAGIC_BYTES, std::size(DELEGATION_MAGIC_BYTES)};

/// Check if code contains EIP-7702 delegation designator
constexpr bool is_code_delegated(bytes_view code) noexcept
{
return code.starts_with(DELEGATION_MAGIC);
}
} // namespace evmone::state
5 changes: 2 additions & 3 deletions test/unittests/state_transition_eip7702_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ TEST_F(state_transition, eip7702_extcodesize)

expect.post[callee].exists = true;
expect.post[delegate].exists = true;
expect.post[To].storage[0x01_bytes32] = 0x02_bytes32;
expect.post[To].storage[0x01_bytes32] = 0x17_bytes32;
}

TEST_F(state_transition, eip7702_extcodehash_delegation_to_empty)
Expand All @@ -87,8 +87,7 @@ TEST_F(state_transition, eip7702_extcodehash_delegation_to_empty)

expect.post[callee].exists = true;
expect.post[delegate].exists = false;
expect.post[To].storage[0x00_bytes32] =
0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329_bytes32;
expect.post[To].storage[0x00_bytes32] = keccak256(bytes{0xef, 0x01, 0x00} + hex(delegate));
expect.post[To].storage[0x01_bytes32] = 0x01_bytes32;
}

Expand Down