diff --git a/circle.yml b/circle.yml index 189d0db2f0..48b47ab840 100644 --- a/circle.yml +++ b/circle.yml @@ -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)" diff --git a/lib/evmone/instructions_calls.cpp b/lib/evmone/instructions_calls.cpp index 480dc7eaa8..86fe7a8274 100644 --- a/lib/evmone/instructions_calls.cpp +++ b/lib/evmone/instructions_calls.cpp @@ -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 @@ -95,6 +96,21 @@ Result call_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noexce if (has_value && intx::be::load(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; diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index f7486fe996..7ee339ee72 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -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 diff --git a/test/unittests/evm_eof_calls_test.cpp b/test/unittests/evm_eof_calls_test.cpp new file mode 100644 index 0000000000..350c2a6e03 --- /dev/null +++ b/test/unittests/evm_eof_calls_test.cpp @@ -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); + } +}