From b449afca876131f15fba43ff425392c9844be4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 20 May 2024 11:40:31 +0200 Subject: [PATCH] Fix EOF initcode handling before EOF is enabled The special rule of handling EOF initcode in CREATE/CREATE2 instructions should not be activated before EOF is activated. --- lib/evmone/instructions_calls.cpp | 9 ++-- .../state_transition_eof_create_test.cpp | 49 ++++++++++++++++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/lib/evmone/instructions_calls.cpp b/lib/evmone/instructions_calls.cpp index d550d8607a..b1e081572f 100644 --- a/lib/evmone/instructions_calls.cpp +++ b/lib/evmone/instructions_calls.cpp @@ -280,9 +280,12 @@ Result create_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noex msg.input_data = &state.memory[init_code_offset]; msg.input_size = init_code_size; - // EOF initcode is not allowed for legacy creation - if (is_eof_container({msg.input_data, msg.input_size})) - return {EVMC_SUCCESS, gas_left}; // "Light" failure. + if (state.rev >= EVMC_PRAGUE) + { + // EOF initcode is not allowed for legacy creation + if (is_eof_container({msg.input_data, msg.input_size})) + return {EVMC_SUCCESS, gas_left}; // "Light" failure. + } } msg.sender = state.msg->recipient; msg.depth = state.msg->depth + 1; diff --git a/test/unittests/state_transition_eof_create_test.cpp b/test/unittests/state_transition_eof_create_test.cpp index eaa726e167..7fe82cb384 100644 --- a/test/unittests/state_transition_eof_create_test.cpp +++ b/test/unittests/state_transition_eof_create_test.cpp @@ -31,7 +31,7 @@ TEST_F(state_transition, create_with_eof_initcode) tx.gas_limit = block.gas_limit; pre.get(tx.sender).balance = tx.gas_limit * tx.max_gas_price + tx.value + 1; - const bytecode init_container = eof_bytecode(ret(0, 1)); + const bytecode init_container = eof_bytecode(OP_INVALID); const auto factory_code = mstore(0, push(init_container)) + // init_container will be left-padded in memory to 32 bytes @@ -46,6 +46,28 @@ TEST_F(state_transition, create_with_eof_initcode) expect.post[*tx.to].storage[0x01_bytes32] = 0x01_bytes32; } +TEST_F(state_transition, create_with_eof_initcode_cancun) +{ + rev = EVMC_CANCUN; + block.gas_limit = 10'000'000; + tx.gas_limit = block.gas_limit; + pre.get(tx.sender).balance = tx.gas_limit * tx.max_gas_price + tx.value + 1; + + const bytecode init_container = eof_bytecode(OP_INVALID); + const auto factory_code = + mstore(0, push(init_container)) + + // init_container will be left-padded in memory to 32 bytes + sstore(0, create().input(32 - init_container.size(), init_container.size())) + sstore(1, 1); + + tx.to = To; + + pre.insert(*tx.to, {.nonce = 1, .code = factory_code}); + + expect.post[*tx.to].nonce = pre.get(*tx.to).nonce + 1; // fails by EF execution, nonce bumped. + expect.post[*tx.to].storage[0x00_bytes32] = 0x00_bytes32; + expect.post[*tx.to].storage[0x01_bytes32] = 0x01_bytes32; +} + TEST_F(state_transition, create2_with_eof_initcode) { rev = EVMC_PRAGUE; @@ -53,7 +75,7 @@ TEST_F(state_transition, create2_with_eof_initcode) tx.gas_limit = block.gas_limit; pre.get(tx.sender).balance = tx.gas_limit * tx.max_gas_price + tx.value + 1; - const bytecode init_container = eof_bytecode(ret(0, 1)); + const bytecode init_container = eof_bytecode(OP_INVALID); const auto factory_code = mstore(0, push(init_container)) + // init_container will be left-padded in memory to 32 bytes @@ -69,6 +91,29 @@ TEST_F(state_transition, create2_with_eof_initcode) expect.post[*tx.to].storage[0x01_bytes32] = 0x01_bytes32; } +TEST_F(state_transition, create2_with_eof_initcode_cancun) +{ + rev = EVMC_CANCUN; + block.gas_limit = 10'000'000; + tx.gas_limit = block.gas_limit; + pre.get(tx.sender).balance = tx.gas_limit * tx.max_gas_price + tx.value + 1; + + const bytecode init_container = eof_bytecode(OP_INVALID); + const auto factory_code = + mstore(0, push(init_container)) + + // init_container will be left-padded in memory to 32 bytes + sstore(0, create2().input(32 - init_container.size(), init_container.size()).salt(Salt)) + + sstore(1, 1); + + tx.to = To; + + pre.insert(*tx.to, {.nonce = 1, .code = factory_code}); + + expect.post[*tx.to].nonce = pre.get(*tx.to).nonce + 1; // fails by EF execution, nonce bumped. + expect.post[*tx.to].storage[0x00_bytes32] = 0x00_bytes32; + expect.post[*tx.to].storage[0x01_bytes32] = 0x01_bytes32; +} + TEST_F(state_transition, create_tx_deploying_eof) { rev = EVMC_PRAGUE;