Skip to content

Commit 7f9d123

Browse files
committed
Support code delegation in instructions implementation
1 parent 133d2a7 commit 7f9d123

File tree

2 files changed

+92
-5
lines changed

2 files changed

+92
-5
lines changed

lib/evmone/instructions.hpp

+64-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include "baseline.hpp"
7+
#include "constants.hpp"
78
#include "eof.hpp"
89
#include "execution_state.hpp"
910
#include "instructions_traits.hpp"
@@ -128,6 +129,27 @@ inline bool check_memory(
128129
return check_memory(gas_left, memory, offset, static_cast<uint64_t>(size));
129130
}
130131

132+
constexpr bool is_code_delegated(bytes_view code) noexcept
133+
{
134+
return code.starts_with(DELEGATION_MAGIC);
135+
}
136+
137+
inline std::optional<evmc::address> get_delegate_address(
138+
const evmc::address& addr, const evmc::HostContext& host) noexcept
139+
{
140+
std::array<uint8_t, std::size(DELEGATION_MAGIC)> prefix;
141+
host.copy_code(addr, 0, prefix.data(), prefix.size());
142+
143+
if (!is_code_delegated(bytes_view{prefix.data(), prefix.size()}))
144+
return {};
145+
146+
assert(host.get_code_size(addr) == std::size(DELEGATION_MAGIC) + std::size(addr.bytes));
147+
148+
evmc::address delegate_address;
149+
host.copy_code(addr, prefix.size(), delegate_address.bytes, std::size(delegate_address.bytes));
150+
return delegate_address;
151+
}
152+
131153
namespace instr::core
132154
{
133155

@@ -518,21 +540,34 @@ inline void blobbasefee(StackTop stack, ExecutionState& state) noexcept
518540
inline Result extcodesize(StackTop stack, int64_t gas_left, ExecutionState& state) noexcept
519541
{
520542
auto& x = stack.top();
521-
const auto addr = intx::be::trunc<evmc::address>(x);
543+
auto addr = intx::be::trunc<evmc::address>(x);
522544

523545
if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD)
524546
{
525547
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
526548
return {EVMC_OUT_OF_GAS, gas_left};
527549
}
528550

551+
if (state.rev >= EVMC_PRAGUE)
552+
{
553+
if (const auto delegate_addr = get_delegate_address(addr, state.host))
554+
{
555+
addr = *delegate_addr;
556+
if (state.host.access_account(addr) == EVMC_ACCESS_COLD)
557+
{
558+
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
559+
return {EVMC_OUT_OF_GAS, gas_left};
560+
}
561+
}
562+
}
563+
529564
x = state.host.get_code_size(addr);
530565
return {EVMC_SUCCESS, gas_left};
531566
}
532567

533568
inline Result extcodecopy(StackTop stack, int64_t gas_left, ExecutionState& state) noexcept
534569
{
535-
const auto addr = intx::be::trunc<evmc::address>(stack.pop());
570+
auto addr = intx::be::trunc<evmc::address>(stack.pop());
536571
const auto& mem_index = stack.pop();
537572
const auto& input_index = stack.pop();
538573
const auto& size = stack.pop();
@@ -550,6 +585,19 @@ inline Result extcodecopy(StackTop stack, int64_t gas_left, ExecutionState& stat
550585
return {EVMC_OUT_OF_GAS, gas_left};
551586
}
552587

588+
if (state.rev >= EVMC_PRAGUE)
589+
{
590+
if (const auto delegate_addr = get_delegate_address(addr, state.host))
591+
{
592+
addr = *delegate_addr;
593+
if (state.host.access_account(addr) == EVMC_ACCESS_COLD)
594+
{
595+
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
596+
return {EVMC_OUT_OF_GAS, gas_left};
597+
}
598+
}
599+
}
600+
553601
if (s > 0)
554602
{
555603
const auto src =
@@ -636,14 +684,27 @@ inline Result returndatacopy(StackTop stack, int64_t gas_left, ExecutionState& s
636684
inline Result extcodehash(StackTop stack, int64_t gas_left, ExecutionState& state) noexcept
637685
{
638686
auto& x = stack.top();
639-
const auto addr = intx::be::trunc<evmc::address>(x);
687+
auto addr = intx::be::trunc<evmc::address>(x);
640688

641689
if (state.rev >= EVMC_BERLIN && state.host.access_account(addr) == EVMC_ACCESS_COLD)
642690
{
643691
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
644692
return {EVMC_OUT_OF_GAS, gas_left};
645693
}
646694

695+
if (state.rev >= EVMC_PRAGUE)
696+
{
697+
if (const auto delegate_addr = get_delegate_address(addr, state.host))
698+
{
699+
addr = *delegate_addr;
700+
if (state.host.access_account(addr) == EVMC_ACCESS_COLD)
701+
{
702+
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
703+
return {EVMC_OUT_OF_GAS, gas_left};
704+
}
705+
}
706+
}
707+
647708
x = intx::be::load<uint256>(state.host.get_code_hash(addr));
648709
return {EVMC_SUCCESS, gas_left};
649710
}

lib/evmone/instructions_calls.cpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Result call_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noexce
5050
Op == OP_CALL || Op == OP_CALLCODE || Op == OP_DELEGATECALL || Op == OP_STATICCALL);
5151

5252
const auto gas = stack.pop();
53-
const auto dst = intx::be::trunc<evmc::address>(stack.pop());
53+
auto dst = intx::be::trunc<evmc::address>(stack.pop());
5454
const auto value = (Op == OP_STATICCALL || Op == OP_DELEGATECALL) ? 0 : stack.pop();
5555
const auto has_value = value != 0;
5656
const auto input_offset_u256 = stack.pop();
@@ -67,6 +67,19 @@ Result call_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noexce
6767
return {EVMC_OUT_OF_GAS, gas_left};
6868
}
6969

70+
if (state.rev >= EVMC_PRAGUE)
71+
{
72+
if (const auto delegate_addr = get_delegate_address(dst, state.host))
73+
{
74+
dst = *delegate_addr;
75+
if (state.host.access_account(dst) == EVMC_ACCESS_COLD)
76+
{
77+
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
78+
return {EVMC_OUT_OF_GAS, gas_left};
79+
}
80+
}
81+
}
82+
7083
if (!check_memory(gas_left, state.memory, input_offset_u256, input_size_u256))
7184
return {EVMC_OUT_OF_GAS, gas_left};
7285

@@ -170,14 +183,27 @@ Result extcall_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noe
170183
if (dst_u256 > ADDRESS_MAX)
171184
return {EVMC_ARGUMENT_OUT_OF_RANGE, gas_left};
172185

173-
const auto dst = intx::be::trunc<evmc::address>(dst_u256);
186+
auto dst = intx::be::trunc<evmc::address>(dst_u256);
174187

175188
if (state.host.access_account(dst) == EVMC_ACCESS_COLD)
176189
{
177190
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
178191
return {EVMC_OUT_OF_GAS, gas_left};
179192
}
180193

194+
if (state.rev >= EVMC_PRAGUE)
195+
{
196+
if (const auto delegate_addr = get_delegate_address(dst, state.host))
197+
{
198+
dst = *delegate_addr;
199+
if (state.host.access_account(dst) == EVMC_ACCESS_COLD)
200+
{
201+
if ((gas_left -= instr::additional_cold_account_access_cost) < 0)
202+
return {EVMC_OUT_OF_GAS, gas_left};
203+
}
204+
}
205+
}
206+
181207
if (!check_memory(gas_left, state.memory, input_offset_u256, input_size_u256))
182208
return {EVMC_OUT_OF_GAS, gas_left};
183209

0 commit comments

Comments
 (0)