Skip to content

Commit

Permalink
Reject DELEGATECALL EOF → legacy (#588)
Browse files Browse the repository at this point in the history
The code targeted by DELEGATECALL from an EOF must also be an EOF.
This restriction has been added to EIP-3540 in
ethereum/EIPs#7131.
  • Loading branch information
axic authored Jun 19, 2023
1 parent 1f8823e commit 94a948f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 3 deletions.
6 changes: 3 additions & 3 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,9 @@ jobs:
export EVMONE_PRECOMPILES_STUB=~/project/test/state/precompiles_stub.json
bin/evmone-statetest ~/tests/GeneralStateTests ~/tests/LegacyTests/Constantinople/GeneralStateTests
- download_execution_tests:
repo: ipsilon/tests
rev: eof
commit: b25623d4d7df10e38498cace7adc7eb413c4b20d
repo: ethereum/tests
rev: develop
commit: 0ec53d024c2b1f5175e70aba8f750cd4d37d9999
legacy: false
- run:
name: "State tests (EOF)"
Expand Down
16 changes: 16 additions & 0 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 "eof.hpp"
#include "instructions.hpp"

namespace evmone::instr::core
Expand Down Expand Up @@ -95,6 +96,21 @@ Result call_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noexce
if (has_value && intx::be::load<uint256>(state.host.get_balance(state.msg->recipient)) < value)
return {EVMC_SUCCESS, gas_left}; // "Light" failure.

if constexpr (Op == OP_DELEGATECALL)
{
if (state.rev >= EVMC_CANCUN && is_eof_container(state.original_code))
{
// The code targeted by DELEGATECALL must also be an EOF.
// This restriction has been added to EIP-3540 in
// https://github.com/ethereum/EIPs/pull/7131
uint8_t target_code_prefix[2];
const auto s = state.host.copy_code(
msg.code_address, 0, target_code_prefix, std::size(target_code_prefix));
if (!is_eof_container({target_code_prefix, s}))
return {EVMC_SUCCESS, gas_left};
}
}

const auto result = state.host.call(msg);
state.return_data.assign(result.output_data, result.output_size);
stack.top() = result.status_code == EVMC_SUCCESS;
Expand Down
1 change: 1 addition & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ target_sources(
evm_eip3855_push0_test.cpp
evm_eip3860_initcode_test.cpp
evm_eof_test.cpp
evm_eof_calls_test.cpp
evm_eof_function_test.cpp
evm_eof_rjump_test.cpp
evm_memory_test.cpp
Expand Down
48 changes: 48 additions & 0 deletions test/unittests/evm_eof_calls_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include "evm_fixture.hpp"
#include "evmone/eof.hpp"

using evmone::test::evm;
using namespace evmc::literals;

TEST_P(evm, eof1_delegatecall_eof1)
{
rev = EVMC_CANCUN;
constexpr auto callee = 0xca11ee_address;
host.accounts[callee].code = eof1_bytecode(OP_STOP);
bytes call_output{0x01, 0x02, 0x03};
host.call_result.output_data = std::data(call_output);
host.call_result.output_size = std::size(call_output);
host.call_result.gas_left = 100;
host.call_result.status_code = EVMC_SUCCESS;

const auto code = eof1_bytecode(delegatecall(callee) + OP_RETURNDATASIZE + OP_PUSH0 + OP_PUSH0 +
OP_RETURNDATACOPY + ret(0, evmone::OP_RETURNDATASIZE),
6);

execute(code);
EXPECT_STATUS(EVMC_SUCCESS);
EXPECT_EQ(hex({result.output_data, result.output_size}), "010203");
}

TEST_P(evm, eof1_delegatecall_legacy)
{
rev = EVMC_CANCUN;
constexpr auto callee = 0xca11ee_address;
host.access_account(callee);

for (const auto& target_code : {""_hex, "EF"_hex, "EF01"_hex, "000000"_hex})
{
SCOPED_TRACE("target code: " + hex(target_code));
host.accounts[callee].code = target_code;

const auto code = eof1_bytecode(delegatecall(callee) + ret_top(), 6);

execute(code);
EXPECT_GAS_USED(EVMC_SUCCESS, 133); // Low gas usage because DELEGATECALL fails lightly.
EXPECT_OUTPUT_INT(0);
}
}

0 comments on commit 94a948f

Please sign in to comment.