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

Reject DELEGATECALL EOF → legacy #588

Merged
merged 1 commit into from
Jun 19, 2023
Merged
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
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);
}
}