From d446dd48716d2d112b532f672f636af3f40cfaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 28 Dec 2022 11:31:45 +0100 Subject: [PATCH] test: Add EIP-3860 unit tests --- test/unittests/CMakeLists.txt | 1 + test/unittests/evm_eip3860_initcode_test.cpp | 88 ++++++++++++++++++++ test/utils/bytecode.hpp | 5 ++ 3 files changed, 94 insertions(+) create mode 100644 test/unittests/evm_eip3860_initcode_test.cpp diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index 33f6e44b84..e53d0f83e7 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -17,6 +17,7 @@ add_executable(evmone-unittests evm_eip2929_test.cpp evm_eip3198_basefee_test.cpp evm_eip3855_push0_test.cpp + evm_eip3860_initcode_test.cpp evm_eof_test.cpp evm_memory_test.cpp evm_state_test.cpp diff --git a/test/unittests/evm_eip3860_initcode_test.cpp b/test/unittests/evm_eip3860_initcode_test.cpp new file mode 100644 index 0000000000..0e229f8158 --- /dev/null +++ b/test/unittests/evm_eip3860_initcode_test.cpp @@ -0,0 +1,88 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2019-2020 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +/// This file contains EVM unit tests for EIP-3860 "Limit and meter initcode" +/// https://eips.ethereum.org/EIPS/eip-3860 + +#include "evm_fixture.hpp" + +using namespace evmc::literals; +using evmone::test::evm; + +inline constexpr size_t initcode_size_limit = 0xc000; + +TEST_P(evm, create_initcode_limit) +{ + host.call_result.create_address = 0x02_address; + const auto code = create().input(0, calldataload(0)) + ret_top(); + for (const auto r : {EVMC_PARIS, EVMC_SHANGHAI}) + { + rev = r; + for (const auto s : {initcode_size_limit, initcode_size_limit + 1}) + { + execute(code, evmc::uint256be{s}); + EXPECT_STATUS(EVMC_SUCCESS); + const unsigned expected_output = + rev >= EVMC_SHANGHAI && s > initcode_size_limit ? 0 : 2; + EXPECT_OUTPUT_INT(expected_output); + } + } +} + +TEST_P(evm, create2_initcode_limit) +{ + host.call_result.create_address = 0x02_address; + const auto code = create2().input(0, calldataload(0)) + ret_top(); + for (const auto r : {EVMC_PARIS, EVMC_SHANGHAI}) + { + rev = r; + for (const auto s : {initcode_size_limit, initcode_size_limit + 1}) + { + execute(code, evmc::uint256be{s}); + EXPECT_STATUS(EVMC_SUCCESS); + const unsigned expected_output = + rev >= EVMC_SHANGHAI && s > initcode_size_limit ? 0 : 2; + EXPECT_OUTPUT_INT(expected_output); + } + } +} + +TEST_P(evm, create_initcode_gas_cost) +{ + rev = EVMC_SHANGHAI; + const auto code = create().input(0, calldataload(0)); + execute(44300, code, evmc::uint256be{initcode_size_limit}); + EXPECT_GAS_USED(EVMC_SUCCESS, 44300); + execute(44299, code, evmc::uint256be{initcode_size_limit}); + EXPECT_STATUS(EVMC_OUT_OF_GAS); +} + +TEST_P(evm, create2_initcode_gas_cost) +{ + rev = EVMC_SHANGHAI; + const auto code = create2().input(0, calldataload(0)); + execute(53519, code, evmc::uint256be{initcode_size_limit}); + EXPECT_GAS_USED(EVMC_SUCCESS, 53519); + execute(53518, code, evmc::uint256be{initcode_size_limit}); + EXPECT_STATUS(EVMC_OUT_OF_GAS); +} + +TEST_P(evm, create2_stack_check) +{ + // Checks if CREATE2 properly handles values on EVM stack. + rev = EVMC_SHANGHAI; + host.call_result.create_address = 0xca_address; + const auto code = + push(0x84) + create2().input(0, calldataload(0)).salt(0x42) + sstore(0) + sstore(1); + + for (const auto& input : {0xC000_bytes32, 0xC001_bytes32}) + { + execute(code, input); + EXPECT_STATUS(EVMC_SUCCESS); + auto& storage = host.accounts[msg.recipient].storage; + EXPECT_EQ( + storage[0x00_bytes32].current, input == 0xC001_bytes32 ? 0x00_bytes32 : 0xca_bytes32); + EXPECT_EQ(storage[0x01_bytes32].current, 0x84_bytes32); + } +} diff --git a/test/utils/bytecode.hpp b/test/utils/bytecode.hpp index 5cd9b3e53e..bf5c657c8d 100644 --- a/test/utils/bytecode.hpp +++ b/test/utils/bytecode.hpp @@ -282,6 +282,11 @@ inline bytecode sstore(bytecode index, bytecode value) return value + index + OP_SSTORE; } +inline bytecode sstore(bytecode index) +{ + return index + OP_SSTORE; +} + inline bytecode sload(bytecode index) { return index + OP_SLOAD;