Skip to content

Commit

Permalink
Refactor EIP-7702: delegation resolution in EVM instead of host function
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed Jan 31, 2025
1 parent 5fad30b commit a92a4ed
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 33 deletions.
2 changes: 1 addition & 1 deletion evmc
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
13 changes: 0 additions & 13 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,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

0 comments on commit a92a4ed

Please sign in to comment.