From d218d7dbbfda4f7cca5d9f293dcace12232a41e6 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 24 Jul 2026 02:15:38 +0000 Subject: [PATCH 1/6] fix(runtime): preserve SSTORE gas threshold across SPP Treat SSTORE as a gas-sensitive boundary when shifting static block costs. EIP-2200 checks gas left before the storage update, so precharging a successor can change success into out-of-gas even when total path cost is unchanged. Add a cache-level regression and an interpreter-versus-multipass replay of mainnet block 21800020 transaction 260 using audited bytecode and calldata fixtures. --- src/evm/evm_cache.cpp | 4 + src/tests/evm_cache_tests.cpp | 16 ++++ src/tests/evm_differential_tests.cpp | 80 ++++++++++++++++--- .../block21800020_tx260/calldata.hex | 1 + .../block21800020_tx260/runtime.hex | 1 + 5 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 tests/evm_regression_data/block21800020_tx260/calldata.hex create mode 100644 tests/evm_regression_data/block21800020_tx260/runtime.hex diff --git a/src/evm/evm_cache.cpp b/src/evm/evm_cache.cpp index 0966960be..c4c1fcc56 100644 --- a/src/evm/evm_cache.cpp +++ b/src/evm/evm_cache.cpp @@ -103,6 +103,10 @@ static bool isControlFlowTerminator(uint8_t OpcodeU8) { static bool isGasSensitiveTerminator(uint8_t OpcodeU8) { switch (static_cast(OpcodeU8)) { case evmc_opcode::OP_GAS: + // EIP-2200 makes SSTORE fail when gas left is at or below the call stipend. + // Moving successor cost before SSTORE can therefore change success to OOG + // even when the total path cost is preserved. + case evmc_opcode::OP_SSTORE: case evmc_opcode::OP_CREATE: case evmc_opcode::OP_CREATE2: case evmc_opcode::OP_CALL: diff --git a/src/tests/evm_cache_tests.cpp b/src/tests/evm_cache_tests.cpp index 7d9e2fadc..c9facc674 100644 --- a/src/tests/evm_cache_tests.cpp +++ b/src/tests/evm_cache_tests.cpp @@ -25,8 +25,10 @@ constexpr uint8_t OP_ADD = static_cast(evmc_opcode::OP_ADD); constexpr uint8_t OP_CALLDATALOAD = static_cast(evmc_opcode::OP_CALLDATALOAD); constexpr uint8_t OP_POP = static_cast(evmc_opcode::OP_POP); +constexpr uint8_t OP_SSTORE = static_cast(evmc_opcode::OP_SSTORE); constexpr uint8_t OP_JUMP = static_cast(evmc_opcode::OP_JUMP); constexpr uint8_t OP_JUMPDEST = static_cast(evmc_opcode::OP_JUMPDEST); +constexpr uint8_t OP_PUSH0 = static_cast(evmc_opcode::OP_PUSH0); constexpr uint8_t OP_PUSH1 = static_cast(evmc_opcode::OP_PUSH1); EVMBytecodeCache buildSPPCache(const std::vector &Code) { @@ -86,6 +88,20 @@ TEST(EVMCacheImplicitDynPred, InterpreterOnly_LeavesSPPArrayEmpty) { EXPECT_TRUE(Cache.GasChunkCostSPP.empty()); } +TEST(EVMCacheSPP, DoesNotShiftSuccessorCostBeforeSstore) { + const std::vector Code = { + OP_PUSH0, OP_PUSH0, OP_SSTORE, // block [0, 3) + OP_PUSH0, OP_POP, // block [3, 5) + OP_JUMPDEST, OP_STOP, + }; + const EVMBytecodeCache Cache = buildSPPCache(Code); + + ASSERT_EQ(Cache.GasChunkCostSPP.size(), Code.size()); + ASSERT_GT(Cache.GasChunkCost[3], 0u); + EXPECT_EQ(Cache.GasChunkCostSPP[0], Cache.GasChunkCost[0]); + EXPECT_EQ(Cache.GasChunkCostSPP[3], Cache.GasChunkCost[3]); +} + // Two dynamic JUMPs => ImplicitDynamicPredCount == 2 on each JUMPDEST. // effectivePredCount must block any lemma614 shift INTO either JUMPDEST. TEST(EVMCacheImplicitDynPred, MultipleDynJumps_BothTargetsCounted) { diff --git a/src/tests/evm_differential_tests.cpp b/src/tests/evm_differential_tests.cpp index 9286de23e..4149f512e 100644 --- a/src/tests/evm_differential_tests.cpp +++ b/src/tests/evm_differential_tests.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2025 the DTVM authors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include @@ -78,7 +79,9 @@ EVMExecutionResult runEvmBytecode( const std::string &Label, const std::vector &Bytecode, common::RunMode Mode, const std::vector &CallData = {}, uint32_t MessageFlags = 0u, bool EnableGasMetering = false, - uint64_t GasLimit = 0xFFFF'FFFF'FFFF - zen::evm::BASIC_EXECUTION_COST) { + uint64_t GasLimit = 0xFFFF'FFFF'FFFF - zen::evm::BASIC_EXECUTION_COST, + evmc_revision Revision = evmc_revision::EVMC_OSAKA, + bool SeedBlock21800020Tx260State = false) { EVMExecutionResult Empty; RuntimeConfig Config; @@ -87,7 +90,24 @@ EVMExecutionResult runEvmBytecode( Config.EnableEvmGasMetering = EnableGasMetering; auto MockedHost = std::make_unique(); - MockedHost->tx_context.tx_origin = zen::evm::DEFAULT_DEPLOYER_ADDRESS; + auto Sender = zen::evm::DEFAULT_DEPLOYER_ADDRESS; + evmc::address Recipient{}; + if (SeedBlock21800020Tx260State) { + Sender = evmc::literals::operator""_address( + "99aaecd05f9b699d1f07bee4eef40d64a2a5cb3d"); + Recipient = evmc::literals::operator""_address( + "5742195a81349f1306361d71a050c4cddc5814fe"); + + evmc::bytes32 Slot33{}; + Slot33.bytes[31] = 0x33; + evmc::bytes32 SenderValue{}; + std::copy(Sender.bytes, Sender.bytes + sizeof(Sender.bytes), + SenderValue.bytes + 12); + evmc::MockedAccount ContractAccount; + ContractAccount.storage[Slot33] = evmc::StorageValue{SenderValue}; + MockedHost->accounts[Recipient] = std::move(ContractAccount); + } + MockedHost->tx_context.tx_origin = Sender; auto RT = Runtime::newEVMRuntime(Config, MockedHost.get()); if (!RT) { ADD_FAILURE() << "runtime create failed: " << Label; @@ -114,20 +134,20 @@ EVMExecutionResult runEvmBytecode( return Empty; } EVMInstance *Inst = *InstRet; - Inst->setRevision(evmc_revision::EVMC_OSAKA); + Inst->setRevision(Revision); evmc_message Msg = { .kind = EVMC_CALL, .flags = MessageFlags, .depth = 0, .gas = static_cast(GasLimit), - .recipient = {}, - .sender = zen::evm::DEFAULT_DEPLOYER_ADDRESS, + .recipient = Recipient, + .sender = Sender, .input_data = CallData.empty() ? nullptr : CallData.data(), .input_size = CallData.size(), .value = {}, .create2_salt = {}, - .code_address = {}, + .code_address = Recipient, .code = reinterpret_cast(Mod->Code), .code_size = Mod->CodeSize, }; @@ -147,9 +167,12 @@ EVMExecutionResult runEvmBytecode( return Exec; } -EVMExecutionResult -runEvmBytecodeFile(const std::string &FilePath, common::RunMode Mode, - const std::vector &CallData = {}) { +EVMExecutionResult runEvmBytecodeFile( + const std::string &FilePath, common::RunMode Mode, + const std::vector &CallData = {}, bool EnableGasMetering = false, + uint64_t GasLimit = 0xFFFF'FFFF'FFFF - zen::evm::BASIC_EXECUTION_COST, + evmc_revision Revision = evmc_revision::EVMC_OSAKA, + bool SeedBlock21800020Tx260State = false) { EVMExecutionResult Empty; std::ifstream Fin(FilePath); @@ -166,8 +189,9 @@ runEvmBytecodeFile(const std::string &FilePath, common::RunMode Mode, ADD_FAILURE() << "Failed to convert hex to bytecode: " << FilePath; return Empty; } - - return runEvmBytecode(FilePath, *BytecodeBuf, Mode, CallData); + return runEvmBytecode(FilePath, *BytecodeBuf, Mode, CallData, 0u, + EnableGasMetering, GasLimit, Revision, + SeedBlock21800020Tx260State); } // Run `Bytecode` through interpreter and multipass, assert the interpreter @@ -665,6 +689,40 @@ TEST(EVMRangeDifferential, "0000000000000000000000000000000000000000000000005555555555555555"); } +TEST(EVMRangeDifferential, Block21800020Tx260MatchesInterpreter) { + const auto FixtureDir = + getEvmAsmDirPath().parent_path() / + std::filesystem::path("evm_regression_data/block21800020_tx260"); + const auto BytecodePath = (FixtureDir / "runtime.hex").string(); + const auto CallDataPath = (FixtureDir / "calldata.hex").string(); + + std::ifstream CallDataFile(CallDataPath); + ASSERT_TRUE(CallDataFile.is_open()); + std::string CallDataHex; + CallDataFile >> CallDataHex; + auto CallData = zen::utils::fromHex(CallDataHex); + ASSERT_TRUE(CallData); + + const auto Interp = + runEvmBytecodeFile(BytecodePath, common::RunMode::InterpMode, *CallData, + true, 31'922, evmc_revision::EVMC_CANCUN, true); + const auto Multi = runEvmBytecodeFile( + BytecodePath, common::RunMode::MultipassMode, *CallData, true, 31'922, + evmc_revision::EVMC_CANCUN, true); +#ifdef ZEN_ENABLE_JIT + EXPECT_TRUE(Multi.JITCompiled); +#endif + EXPECT_EQ(Interp.Status, EVMC_SUCCESS); + EXPECT_EQ(Interp.GasLeft, 1'122); + EXPECT_EQ(Interp.LogCount, 3u); + EXPECT_TRUE(Interp.OutputHex.empty()); + EXPECT_EQ(Multi.Status, Interp.Status); + EXPECT_EQ(Multi.GasLeft, Interp.GasLeft); + EXPECT_EQ(Multi.OutputHex, Interp.OutputHex); + EXPECT_EQ(Multi.LogCount, Interp.LogCount); + EXPECT_EQ(Multi.LogsSignature, Interp.LogsSignature); +} + // Sweep SHL/SHR/SAR with shift amounts that land inside the limb-crossing // region 2..255. The 11-value operand matrix, when fed as a shift amount, only // realizes {0, 1, >=2^64}; it never produces an amount in 2..255, so the diff --git a/tests/evm_regression_data/block21800020_tx260/calldata.hex b/tests/evm_regression_data/block21800020_tx260/calldata.hex new file mode 100644 index 000000000..8ba650f67 --- /dev/null +++ b/tests/evm_regression_data/block21800020_tx260/calldata.hex @@ -0,0 +1 @@ +0x9d8ecd8500000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/tests/evm_regression_data/block21800020_tx260/runtime.hex b/tests/evm_regression_data/block21800020_tx260/runtime.hex new file mode 100644 index 000000000..e29d008e8 --- /dev/null +++ b/tests/evm_regression_data/block21800020_tx260/runtime.hex @@ -0,0 +1 @@ +0x608060405234801561001057600080fd5b50600436106101505760003560e01c80638d3638f4116100cd578063d5438eae11610081578063f2fde38b11610066578063f2fde38b14610347578063f7e83aee1461035a578063fbc69aab1461037d57600080fd5b8063d5438eae14610300578063de523cf31461032757600080fd5b806393c44847116100b257806393c44847146102915780639d8ecd85146102da578063c4d66de8146102ed57600080fd5b80638d3638f4146102375780638da5cb5b1461027357600080fd5b8063440df4f4116101245780636465e69f116101095780636465e69f146101f5578063715018a61461020f5780637f5a7c7b1461021757600080fd5b8063440df4f4146101cd5780634c0a2ffc146101e257600080fd5b8062d84fd8146101555780630e72cc061461016a57806315ce45a21461017d5780633dfd3873146101ba575b600080fd5b6101686101633660046115a6565b610390565b005b6101686101783660046115e3565b6103a4565b61019061018b366004611649565b6104f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101686101c83660046115e3565b61050a565b6101d561064b565b6040516101b1919061168b565b6101686101f03660046116cf565b61065c565b6101fd600181565b60405160ff90911681526020016101b1565b610168610672565b6068546101909073ffffffffffffffffffffffffffffffffffffffff1681565b61025e7f000000000000000000000000000000000000000000000000000000000000000181565b60405163ffffffff90911681526020016101b1565b60335473ffffffffffffffffffffffffffffffffffffffff16610190565b6102cd6040518060400160405280600681526020017f352e31312e32000000000000000000000000000000000000000000000000000081525081565b6040516101b1919061172a565b6101686102e83660046117c0565b610686565b6101686102fb3660046115e3565b610903565b6101907f000000000000000000000000c005dc82818d67af737725bd4bf75435d065d23981565b6069546101909073ffffffffffffffffffffffffffffffffffffffff1681565b6101686103553660046115e3565b610a97565b61036d610368366004611843565b610b4b565b60405190151581526020016101b1565b61019061038b3660046115a6565b610be1565b610398610caa565b6103a181610d2b565b50565b8073ffffffffffffffffffffffffffffffffffffffff81163b1515806103de575073ffffffffffffffffffffffffffffffffffffffff8116155b61046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e670000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610477610caa565b606980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fc47cbcc588c67679e52261c45cc315e56562f8d0ccaba16facb9093ff9498799906020015b60405180910390a15050565b600061050161038b8484610d80565b90505b92915050565b8073ffffffffffffffffffffffffffffffffffffffff81163b151580610544575073ffffffffffffffffffffffffffffffffffffffff8116155b6105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e67000000000000000000000000000000000000000000000000006064820152608401610466565b6105d8610caa565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527f4eab7b127c764308788622363ad3e9532de3dfba7845bd4f84c125a22544255a906020016104e6565b60606106576065610da3565b905090565b610664610caa565b61066e8282610e3e565b5050565b61067a610caa565b6106846000610ee4565b565b600054610100900460ff16158080156106a65750600054600160ff909116105b806106c05750303b1580156106c0575060005460ff166001145b61074c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610466565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107aa57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6107b2610f5b565b83821461081b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6c656e677468206d69736d6174636800000000000000000000000000000000006044820152606401610466565b8360005b8181101561088d5761087d87878381811061083c5761083c6118af565b905060200201602081019061085191906115a6565b868684818110610863576108636118af565b905060200201602081019061087891906115e3565b610e3e565b6108868161190d565b905061081f565b5061089787610ee4565b5080156108fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b600054610100900460ff16158080156109235750600054600160ff909116105b8061093d5750303b15801561093d575060005460ff166001145b6109c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610466565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a2757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a2f610f5b565b610a3882610ee4565b801561066e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016104e6565b610a9f610caa565b73ffffffffffffffffffffffffffffffffffffffff8116610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610466565b6103a181610ee4565b6000610b5783836104f2565b73ffffffffffffffffffffffffffffffffffffffff1663f7e83aee868686866040518563ffffffff1660e01b8152600401610b95949392919061198e565b6020604051808303816000875af1158015610bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd891906119c0565b95945050505050565b60008080610bf9606563ffffffff80871690610ffa16565b915091508115610c1457610c0c81611013565b949350505050565b7f000000000000000000000000c005dc82818d67af737725bd4bf75435d065d23973ffffffffffffffffffffffffffffffffffffffff16636e5f516e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0c91906119e2565b5050919050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b610d3f606563ffffffff808416906110bc16565b610d48826110c8565b9061066e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610466919061172a565b6000610d906009600584866119ff565b610d9991611a29565b60e01c9392505050565b60606000610db0836110ff565b90508067ffffffffffffffff811115610dcb57610dcb611a71565b604051908082528060200260200182016040528015610df4578160200160208202803683370190505b50915060005b81811015610ca357610e0c848261110a565b60001c838281518110610e2157610e216118af565b602090810291909101015280610e368161190d565b915050610dfa565b73ffffffffffffffffffffffffffffffffffffffff81163b610ebc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f49534d206d757374206265206120636f6e7472616374000000000000000000006044820152606401610466565b61066e606563ffffffff841673ffffffffffffffffffffffffffffffffffffffff8416611116565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610ff2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610466565b610684611127565b60008061100784846111c7565b915091505b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff8211156110b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5479706543617374733a2062797465733332546f41646472657373206f76657260448201527f666c6f77000000000000000000000000000000000000000000000000000000006064820152608401610466565b5090565b60006105018383611201565b60606110d98263ffffffff1661121e565b6040516020016110e99190611aa0565b6040516020818303038152906040529050919050565b6000610504826112dc565b600061050183836112e6565b611121838383611310565b50505050565b600054610100900460ff166111be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610466565b61068433610ee4565b60008181526002830160205260408120548190806111f6576111e9858561132d565b92506000915061100c9050565b60019250905061100c565b600081815260028301602052604081208190556105018383611339565b6060600061122b83611345565b600101905060008167ffffffffffffffff81111561124b5761124b611a71565b6040519080825280601f01601f191660200182016040528015611275576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461127f57509392505050565b6000610504825490565b60008260000182815481106112fd576112fd6118af565b9060005260206000200154905092915050565b60008281526002840160205260408120829055610c0c8484611427565b60006105018383611433565b6000610501838361144b565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061138e577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106113ba576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113d857662386f26fc10000830492506010015b6305f5e10083106113f0576305f5e100830492506008015b612710831061140457612710830492506004015b60648310611416576064830492506002015b600a83106105045760010192915050565b6000610501838361153e565b60008181526001830160205260408120541515610501565b6000818152600183016020526040812054801561153457600061146f600183611ae5565b855490915060009061148390600190611ae5565b90508181146114e85760008660000182815481106114a3576114a36118af565b90600052602060002001549050808760000184815481106114c6576114c66118af565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806114f9576114f9611af8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610504565b6000915050610504565b600081815260018301602052604081205461158557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610504565b506000610504565b803563ffffffff811681146115a157600080fd5b919050565b6000602082840312156115b857600080fd5b6105018261158d565b73ffffffffffffffffffffffffffffffffffffffff811681146103a157600080fd5b6000602082840312156115f557600080fd5b8135611600816115c1565b9392505050565b60008083601f84011261161957600080fd5b50813567ffffffffffffffff81111561163157600080fd5b60208301915083602082850101111561100c57600080fd5b6000806020838503121561165c57600080fd5b823567ffffffffffffffff81111561167357600080fd5b61167f85828601611607565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b818110156116c3578351835292840192918401916001016116a7565b50909695505050505050565b600080604083850312156116e257600080fd5b6116eb8361158d565b915060208301356116fb816115c1565b809150509250929050565b60005b83811015611721578181015183820152602001611709565b50506000910152565b6020815260008251806020840152611749816040850160208701611706565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008083601f84011261178d57600080fd5b50813567ffffffffffffffff8111156117a557600080fd5b6020830191508360208260051b850101111561100c57600080fd5b6000806000806000606086880312156117d857600080fd5b85356117e3816115c1565b9450602086013567ffffffffffffffff8082111561180057600080fd5b61180c89838a0161177b565b9096509450604088013591508082111561182557600080fd5b506118328882890161177b565b969995985093965092949392505050565b6000806000806040858703121561185957600080fd5b843567ffffffffffffffff8082111561187157600080fd5b61187d88838901611607565b9096509450602087013591508082111561189657600080fd5b506118a387828801611607565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361193e5761193e6118de565b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006119a2604083018688611945565b82810360208401526119b5818587611945565b979650505050505050565b6000602082840312156119d257600080fd5b8151801515811461160057600080fd5b6000602082840312156119f457600080fd5b8151611600816115c1565b60008085851115611a0f57600080fd5b83861115611a1c57600080fd5b5050820193919092039150565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015611a695780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e6f2049534d20666f756e6420666f72206f726967696e3a2000000000000000815260008251611ad8816019850160208701611706565b9190910160190192915050565b81810381811115610504576105046118de565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220b228bdbbde9b718bad3c2a3328cd105fcdd195acfeca535172d620046167ee6364736f6c63430008130033 From df91ce19042faeb969935ad961404c3fb12b29f0 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 24 Jul 2026 03:43:46 +0000 Subject: [PATCH 2/6] fix(runtime): preserve gas across unresolved dynamic jumps Track omitted dynamic successors so SPP cannot charge untaken blocks on a taken path. Bind focused execution revisions and pin storage, log, and gas regression oracles. --- docs/modules/evm/cache-build.md | 121 ++++++++++++++++++++------- src/evm/evm_cache.cpp | 72 ++++++++-------- src/tests/evm_cache_tests.cpp | 16 ++++ src/tests/evm_differential_tests.cpp | 101 +++++++++++++++++++++- 4 files changed, 245 insertions(+), 65 deletions(-) diff --git a/docs/modules/evm/cache-build.md b/docs/modules/evm/cache-build.md index 23408c797..f0d1b77ec 100644 --- a/docs/modules/evm/cache-build.md +++ b/docs/modules/evm/cache-build.md @@ -40,17 +40,17 @@ straight-line fallback only. |---:|---|---| | 0 | `buildJumpDestMapAndPushCache` | Single bytecode walk: mark valid JUMPDESTs (skipping PUSH-data regions); decode PUSHn immediates into `PushValueMap` | | 1 | `buildGasBlocks` | Single bytecode walk: emit one `GasBlock` per basic block, record `JumpDestBlocks` inline, compute per-block straight-line gas | -| 2 | `buildCFGEdges` | Single sweep: emit Succs/Preds edges into `EdgeTables`; stamp `ImplicitDynamicPredCount` on JUMPDEST blocks reachable by unresolved dynamic JUMP | +| 2 | `buildCFGEdges` | Single sweep: emit resolved and fallthrough Succs/Preds edges into `EdgeTables`; for unresolved dynamic JUMP/JUMPI, mark the source with `HasUnresolvedDynamicSuccessor` and stamp possible JUMPDEST targets with `ImplicitDynamicPredCount` | | 3 | `splitCriticalEdges` | Insert empty synthetic blocks on `multi-succ → multi-pred` edges; appends new entries onto `Blocks` and `EdgeTables` | | 4 | `buildAdjacencyCSR` | Flatten `EdgeTables.Succs` and `.Preds` into two read-only `CSRGraph`s after the graph is frozen | | 5 | `computeReachable` | DFS from block 0 over `SuccsCSR`; produce `Reachable` bitset | | 6 | `computeDomInfo` | Cooper-Harvey-Kennedy fixpoint over `PredsCSR` for `IDom`, then Tarjan DFS over the dominator tree for `Enter`/`Exit` Euler tour stamps; produce `RPO` from the forward DFS | | 7 | `findBackEdgesUsingDominators` | Iterate edges; emit back-edges where successor `dominates(succ, curr)` | | 8 | `computeReverseTopo` | Return `reverse(DomInfo::RPO)` | -| 9 | `buildLoopsUsingDominance` | From dominator-based back-edges, gather natural-loop body sets; returns `true` if every node's back-edge target dominates it (reducible) | -| 10 | `computeInCycle` | **Conditional**: when `UseLinearSPP=true` (reducible result from 9), set `InCycle = union(Loops[].NodeMask)`; when `UseLinearSPP=false`, fall back to Tarjan SCC over `SuccsCSR` for `InCycle` | +| 9 | `buildLoopsUsingDominance` | Gather natural-loop bodies from dominance back-edges whose source is reachable; return `false` if a detected body violates header dominance or detected loops overlap without nesting. A `true` result validates only the detected loop set, not general CFG reducibility | +| 10 | `computeInCycle` | **Conditional**: when `UseLinearSPP=true`, set `InCycle = union(Loops[].NodeMask)`; when `UseLinearSPP=false`, run a two-pass Kosaraju-style SCC traversal over `SuccsCSR` and `PredsCSR`. The traversal therefore runs only for a rejected detected-loop set | | 11 | `meteringInit` | Copy per-block `Cost` into the `Metering` working array used by lemma614 | -| 12 | `lemma614Schedule` | SPP gas-shifting in reverse-topo order: for each block, try to shift its gas charge onto its successors via `lemma614Update`, gated on `effectivePredCount` and `InCycle` | +| 12 | `lemma614Schedule` | SPP gas-shifting in reverse-topo order: for each block, try to shift its gas charge onto its successors via `lemma614Update`, gated on `HasUnresolvedDynamicSuccessor == 0`, `effectivePredCount`, and `InCycle` | | 13 | `writeback` | Project per-block `Metering` back onto `GasChunkEnd` / `GasChunkCost` / `GasChunkCostSPP` | `EVM_PROFILE_BEGIN() / EVM_PROFILE_END()` chrono pairs @@ -72,7 +72,8 @@ Per-block scalars used by every downstream pass. | 16 | `ImplicitDynamicPredCount` | `uint32_t` | Count of dynamic-JUMP blocks that could land on this JUMPDEST (carried separately to avoid `D×J` materialised over-approximation edges) | | 20 | `LastOpcode` | `uint8_t` | Terminator opcode | | 21 | `PrevOpcode` | `uint8_t` | Opcode before terminator | -| 22 | _pad[2]_ | — | Alignment to 8-byte `Cost` | +| 22 | `HasUnresolvedDynamicSuccessor` | `uint8_t` | Nonzero when an unresolved dynamic JUMP/JUMPI has runtime targets omitted from this source's explicit successor list | +| 23 | _pad[1]_ | — | Alignment to 8-byte `Cost` | | 24 | `Cost` | `uint64_t` | Straight-line gas cost of the block | The 32-byte stride is load-bearing for the cache-density gains; the @@ -94,6 +95,13 @@ edge insertion is provided by the `addEdge` helper (linear scan over the per-block vectors). Consumed by `buildAdjacencyCSR` and not read directly by any downstream pass. +Edges for unresolved dynamic jumps are deliberately absent from both +tables and the resulting CSR graphs. `ImplicitDynamicPredCount` +represents those omitted incoming edges on each possible JUMPDEST, +while `HasUnresolvedDynamicSuccessor` marks the source whose runtime +successor set is incomplete. For an unresolved JUMPI, its fallthrough +edge remains explicit; only its taken-target edges are omitted. + ### `CSRGraph` — read-only flat adjacency ```cpp @@ -138,42 +146,93 @@ DFS instead of running their own. ## Invariants -### Reducible-CFG fast-path soundness +### Loop-set selection and per-update soundness + +`UseLinearSPP=true` means that the dominance-based natural loops found +by `buildLoopsUsingDominance` passed its body-dominance and nesting +checks. It does not prove that the CFG is reducible. A multi-entry SCC +with no dominance back-edge produces no `LoopInfo` and can therefore +return `true` with that SCC absent from `InCycle`. The two-pass SCC +traversal runs only when the detected loop set fails validation. -The R2 reviewers established the soundness story explicitly. When -`UseLinearSPP=true` (i.e. `buildLoopsUsingDominance` reported reducible), -`computeInCycle` is a **performance optimisation**, not the safety -mechanism. The actual safety invariant lives in `lemma614Update`'s -multi-predecessor guard: +Soundness does not require complete SCC classification. For updates +that can occur on a runtime path, it follows from these local +conditions: ```cpp +if (Node.HasUnresolvedDynamicSuccessor != 0) { + return false; +} + if (effectivePredCount(Succ, Blocks, PredsCSR) != 1) { - // refuse shift + MinSucc = 0; + continue; } ``` `effectivePredCount` folds `ImplicitDynamicPredCount` into the -structural pred count, so any JUMPDEST that could be reached by an -unresolved dynamic JUMP sees count > 1 and the lemma refuses to shift -gas across that edge. Every node inside any SCC of size ≥ 2 has at -least one in-cycle predecessor on top of any out-of-cycle entry, so -its `effectivePredCount` is ≥ 2 and the shift is refused even on -irreducible CFGs the fast-path filter misses. - -**Future-contributor warning**: do **not** remove the multi-pred guard -on the assumption that `InCycle` covers it. On an irreducible 2-entry -cycle `A ↔ B` where neither node dominates the other, the dominator-based -back-edge set is empty, `buildLoopsUsingDominance` returns `true` with -`Loops` empty, and `InCycle = union(empty) = all-zeros`. Without the -multi-pred guard, lemma614 would mis-charge such a CFG; with the guard, -correctness is preserved. - -### Irreducible-CFG fallback +structural pred count. A possible dynamic target with an explicit +incoming edge therefore has count greater than one, so the lemma +cannot move its cost onto only that explicit predecessor. A target +with only implicit incoming edges is not present in any source's +`SuccsCSR` slice and cannot be selected for a shift. + +Independently, no block with `HasUnresolvedDynamicSuccessor != 0` may +act as a lemma614 shift source. Moving explicit-successor cost onto +such a source would increase the charge on every runtime exit while +compensating only successors represented in `SuccsCSR`; an omitted +taken target would receive no compensating reduction. The guard makes +the represented successor list complete for every accepted source. + +A runtime-reachable source of a recorded dominance back-edge belongs +to the corresponding natural-loop mask and is skipped before +`lemma614Update`. The `BackEdges` branch therefore omits no executable +edge for a reachable source that is actually updated. In particular, +an updated reachable source in an unrecognized SCC has no recorded +outgoing back-edge, so the branch is a no-op. If `AllowedMask` excludes +any other represented successor, the first scan sets `MinSucc` to zero +and rejects the whole update. + +For a successful update on a reachable source, every represented +runtime successor is therefore included, and the source passes the +gas-sensitive boundary check. Each successor has one effective +predecessor, is not the program entry, has no implicit dynamic +predecessor, and passes the gas-chunk boundary check. The update +subtracts the same common cost from every such successor that it adds +to the source. Every source execution selects one compensated +successor, and every execution of that successor arrives from the +source, so the costs balance on complete paths even when an SCC was +not added to `InCycle`. + +`RPO` and the schedule can still contain unreachable blocks, while +`buildLoopsUsingDominance` skips an unreachable back-edge source. +`lemma614Update` may therefore update such a source and skip one of its +recorded back-edges. This does not affect runtime gas because no +executable path reaches the source. The local path-balance claim above +is intentionally limited to runtime-reachable sources. + +**Future-contributor warning**: `InCycle`, the dynamic-edge guards, +`effectivePredCount`, and the schedule masks enforce different parts of +this invariant. None can be removed on the assumption that +`UseLinearSPP=true` proves reducibility. + +### Conditional two-pass SCC fallback When `buildLoopsUsingDominance` returns `false`, `UseLinearSPP=false` -and the Tarjan SCC pass runs over `SuccsCSR` to fill `InCycle`. The -`effectivePredCount` guard remains active in this path too, so Tarjan -SCC is defence-in-depth, not the only safety net. +and a two-pass Kosaraju-style traversal runs over `SuccsCSR` and +`PredsCSR` to fill `InCycle`. A `true` result does not trigger the +fallback and may leave an SCC without dominance back-edges unmarked. +Both paths retain the same local source, successor, and schedule checks +described above. + +### Regression scope + +The permanent cache and execution regressions added for the dynamic-jump +fix directly cover the `HasUnresolvedDynamicSuccessor` behavior. They do +not execute an unrecognized SCC or a synthetic critical edge through the +complete SPP pipeline. Changes to loop discovery, back-edge filtering, or +synthetic-block writeback require dedicated regression coverage for those +paths. ### Block-vector reserve diff --git a/src/evm/evm_cache.cpp b/src/evm/evm_cache.cpp index c4c1fcc56..6ca5d7a55 100644 --- a/src/evm/evm_cache.cpp +++ b/src/evm/evm_cache.cpp @@ -105,7 +105,9 @@ static bool isGasSensitiveTerminator(uint8_t OpcodeU8) { case evmc_opcode::OP_GAS: // EIP-2200 makes SSTORE fail when gas left is at or below the call stipend. // Moving successor cost before SSTORE can therefore change success to OOG - // even when the total path cost is preserved. + // even when the total path cost is preserved. Applying this barrier before + // Istanbul is an intentional conservative safety policy: it can only reduce + // SPP shifting on revisions without the sentry. case evmc_opcode::OP_SSTORE: case evmc_opcode::OP_CREATE: case evmc_opcode::OP_CREATE2: @@ -232,7 +234,8 @@ buildJumpDestMapAndPushCache(const zen::common::Byte *Code, size_t CodeSize, // 16 ImplicitDynamicPredCount uint32 // 20 LastOpcode uint8 // 21 PrevOpcode uint8 -// 22 pad[2] (2 alignment bytes before Cost) +// 22 HasUnresolvedDynamicSuccessor uint8 +// 23 pad[1] (1 alignment byte before Cost) // 24 Cost uint64 // 32 sizeof struct GasBlock { @@ -247,6 +250,8 @@ struct GasBlock { uint32_t ImplicitDynamicPredCount = 0; uint8_t LastOpcode = 0; uint8_t PrevOpcode = 0; + // Runtime can branch to a successor omitted from the explicit CFG. + uint8_t HasUnresolvedDynamicSuccessor = 0; uint64_t Cost = 0; }; static_assert(sizeof(GasBlock) == 32, @@ -506,12 +511,11 @@ static bool resolveConstantJumpTarget(const std::vector &JumpDestMap, // single-target edges. For each unresolved dynamic jump we DO NOT add the // D*|JUMPDEST| explicit over-approximation edges (which previously made the // pass quadratic-to-cubic in pathological contracts). Instead we record on -// every JUMPDEST how many dynamic-jump blocks could land there at runtime -// via `ImplicitDynamicPredCount`, and `effectivePredCount` folds that count -// into its multi-predecessor check. SPP decisions are identical: a JUMPDEST -// that is a potential dynamic-jump target sees `effectivePredCount > 1` and -// `lemma614Update` refuses to shift gas across that edge, exactly as it -// would have done against an explicit over-approximated `Preds` set. +// every JUMPDEST how many dynamic-jump blocks could land there at runtime via +// `ImplicitDynamicPredCount`, and mark each dynamic-jump source with +// `HasUnresolvedDynamicSuccessor`. The former prevents shifts into an implicit +// target; the latter prevents shifts out of a source whose omitted successors +// cannot be compensated. static void buildCFGEdges(std::vector &Blocks, EdgeTables &Edges, const std::vector &BlockAtPc, @@ -527,7 +531,7 @@ buildCFGEdges(std::vector &Blocks, EdgeTables &Edges, // halves the call count and the bytecode rescan it performs. uint32_t DynamicJumpCount = 0; for (size_t BlockId = 0; BlockId < Blocks.size(); ++BlockId) { - const auto &Block = Blocks[BlockId]; + auto &Block = Blocks[BlockId]; const bool IsTerminator = isControlFlowTerminator(Block.LastOpcode); // Add fallthrough edge for non-terminating opcodes (CALL/CREATE/GAS, @@ -550,6 +554,7 @@ buildCFGEdges(std::vector &Blocks, EdgeTables &Edges, // Keep the constant-decode fallback for cases the shared abstract // stack pass intentionally leaves unresolved. } else { + Block.HasUnresolvedDynamicSuccessor = 1; ++DynamicJumpCount; continue; } @@ -1203,9 +1208,9 @@ static bool buildLoopsUsingDominance( // // Blocks with `ImplicitDynamicPredCount > 0` (every JUMPDEST in a contract // that has at least one dynamic jump) carry the over-approximated dynamic -// predecessors as a count instead of explicit edges; folding them in here -// keeps `lemma614Update`'s "shift only into single-pred successors" check -// equivalent to the explicit over-approximation. +// predecessors as a count instead of explicit edges. Folding them in here +// conservatively prevents a shift into any represented successor that could +// also be reached by an omitted dynamic edge. static size_t effectivePredCount(uint32_t NodeId, const std::vector &Blocks, const CSRGraph &PredsCSR) { @@ -1224,7 +1229,8 @@ static bool lemma614Update(uint32_t NodeId, const std::vector &Blocks, const std::vector *AllowedMask, std::vector &Metering) { const auto &Node = Blocks[NodeId]; - if (isGasSensitiveTerminator(Node.LastOpcode)) { + if (isGasSensitiveTerminator(Node.LastOpcode) || + Node.HasUnresolvedDynamicSuccessor != 0) { return false; } @@ -1512,7 +1518,9 @@ static bool buildGasChunksSPP( } // Always build CFG — no early exit for dynamic jumps. - // Unresolved jumps get over-approximated edges to all JUMPDESTs. + // Unresolved dynamic targets remain implicit: possible target blocks carry + // ImplicitDynamicPredCount, and their source blocks carry + // HasUnresolvedDynamicSuccessor. // JumpDestBlocks is now produced inline by buildGasBlocks (one push per // block whose first opcode is OP_JUMPDEST), eliminating the prior bytecode @@ -1520,11 +1528,9 @@ static bool buildGasChunksSPP( // every JUMPDEST byte under EVM semantics starts a new gas block. // Static jumps get precise single-target edges. For unresolved dynamic - // jumps, the CFG over-approximation is encoded as - // ImplicitDynamicPredCount on each JUMPDEST (folded into - // effectivePredCount). Narrowing to partial call-site resolution would - // under-approximate the CFG and let SPP shift gas along non-existent - // edges, producing unsafe metering. + // jumps, ImplicitDynamicPredCount protects possible targets while + // HasUnresolvedDynamicSuccessor prevents source-side shifts that could not + // compensate omitted targets. EdgeTables Edges; Edges.resize(Blocks.size()); @@ -1608,21 +1614,21 @@ static bool buildGasChunksSPP( SuccsCSR, PredsCSR, Dom, Reachable, Loops, LoopOf, ExitLoops, ExitFlags); EVM_PROFILE_END(buildLoopsUsingDominance); - // InCycle is a performance fast-path filter for lemma614Update, NOT the - // soundness mechanism. On reducible CFGs (UseLinearSPP=true) the union of - // natural-loop NodeMasks coincides with the in-cycle set Tarjan SCC would - // produce, so we skip the standalone Tarjan pass. On irreducible CFGs - // (UseLinearSPP=false) buildLoopsUsingDominance can miss multi-entry - // cycles (e.g. an irreducible 2-entry cycle A<->B with no dominator-based - // back-edge), so the Tarjan SCC backstop fills InCycle for those nodes. + // UseLinearSPP means only that the detected dominance-based natural loops + // passed the body-dominance and nesting checks. It is not a general + // reducibility proof: an SCC without a dominance back-edge produces no + // LoopInfo and can still return true. The two-pass SCC fallback runs only + // when the validator returns false; otherwise InCycle is the union of the + // detected loop masks. // - // Soundness on irreducible CFGs ultimately rests on lemma614Update's - // effectivePredCount(Succ) != 1 multi-pred guard at line 1224: every SCC - // node has at least one in-cycle predecessor on top of any out-of-cycle - // entry, so its effectivePredCount is >= 2 and the shift is refused even - // when InCycle is empty. See docs/modules/evm/cache-build.md §Invariants - // -- do NOT remove the multi-pred guard on the assumption that InCycle - // covers it. + // Runtime soundness is local to each successful update on a reachable source. + // Sources with omitted dynamic successors are rejected. A reachable source + // of a recorded dominance back-edge is in its natural-loop mask and is + // skipped by the schedule, so BackEdges omits no executable edge from a + // reachable source that is updated. If AllowedMask excludes another + // successor, lemma614Update cancels the whole update. Unreachable blocks can + // still be scheduled, but their shifted costs occur on no executable path. + // See docs/modules/evm/cache-build.md §Invariants. EVM_PROFILE_BEGIN(computeInCycle); std::vector InCycle; if (UseLinearSPP) { diff --git a/src/tests/evm_cache_tests.cpp b/src/tests/evm_cache_tests.cpp index c9facc674..8bff9974c 100644 --- a/src/tests/evm_cache_tests.cpp +++ b/src/tests/evm_cache_tests.cpp @@ -27,6 +27,7 @@ constexpr uint8_t OP_CALLDATALOAD = constexpr uint8_t OP_POP = static_cast(evmc_opcode::OP_POP); constexpr uint8_t OP_SSTORE = static_cast(evmc_opcode::OP_SSTORE); constexpr uint8_t OP_JUMP = static_cast(evmc_opcode::OP_JUMP); +constexpr uint8_t OP_JUMPI = static_cast(evmc_opcode::OP_JUMPI); constexpr uint8_t OP_JUMPDEST = static_cast(evmc_opcode::OP_JUMPDEST); constexpr uint8_t OP_PUSH0 = static_cast(evmc_opcode::OP_PUSH0); constexpr uint8_t OP_PUSH1 = static_cast(evmc_opcode::OP_PUSH1); @@ -102,6 +103,21 @@ TEST(EVMCacheSPP, DoesNotShiftSuccessorCostBeforeSstore) { EXPECT_EQ(Cache.GasChunkCostSPP[3], Cache.GasChunkCost[3]); } +TEST(EVMCacheSPP, DoesNotShiftFallthroughBeforeUnresolvedJumpi) { + const std::vector Code = { + OP_PUSH1, 0x00, OP_CALLDATALOAD, OP_PUSH1, 0x20, OP_CALLDATALOAD, + OP_JUMPI, // unresolved target + OP_PUSH0, OP_POP, // explicit fallthrough + OP_JUMPDEST, OP_STOP, // implicit dynamic target + }; + const EVMBytecodeCache Cache = buildSPPCache(Code); + + ASSERT_EQ(Cache.GasChunkCostSPP.size(), Code.size()); + ASSERT_EQ(Cache.GasChunkCost[7], 4u); + EXPECT_EQ(Cache.GasChunkCostSPP[0], Cache.GasChunkCost[0]); + EXPECT_EQ(Cache.GasChunkCostSPP[7], Cache.GasChunkCost[7]); +} + // Two dynamic JUMPs => ImplicitDynamicPredCount == 2 on each JUMPDEST. // effectivePredCount must block any lemma614 shift INTO either JUMPDEST. TEST(EVMCacheImplicitDynPred, MultipleDynJumps_BothTargetsCounted) { diff --git a/src/tests/evm_differential_tests.cpp b/src/tests/evm_differential_tests.cpp index 4149f512e..086ce0b4d 100644 --- a/src/tests/evm_differential_tests.cpp +++ b/src/tests/evm_differential_tests.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "compiler/evm_frontend/evm_analyzer.h" @@ -66,6 +67,7 @@ struct EVMExecutionResult { int64_t GasLeft = 0; std::string OutputHex; std::string LogsSignature; + std::unordered_map RecipientStorage; size_t LogCount = 0; bool JITCompiled = false; }; @@ -115,7 +117,8 @@ EVMExecutionResult runEvmBytecode( } MockedHost->setRuntime(RT.get()); - auto ModRet = RT->loadEVMModule(Label, Bytecode.data(), Bytecode.size()); + auto ModRet = + RT->loadEVMModule(Label, Bytecode.data(), Bytecode.size(), Revision); if (!ModRet) { ADD_FAILURE() << "module load failed: " << Label; return Empty; @@ -164,6 +167,10 @@ EVMExecutionResult runEvmBytecode( zen::utils::toHex(RawResult.output_data, RawResult.output_size); Exec.LogCount = MockedHost->recorded_logs.size(); Exec.LogsSignature = logsSignature(MockedHost->recorded_logs); + const auto RecipientIt = MockedHost->accounts.find(Recipient); + if (RecipientIt != MockedHost->accounts.end()) { + Exec.RecipientStorage = RecipientIt->second.storage; + } return Exec; } @@ -716,11 +723,103 @@ TEST(EVMRangeDifferential, Block21800020Tx260MatchesInterpreter) { EXPECT_EQ(Interp.GasLeft, 1'122); EXPECT_EQ(Interp.LogCount, 3u); EXPECT_TRUE(Interp.OutputHex.empty()); + constexpr char ExpectedLogsSignature[] = + "3|5742195a81349f1306361d71a050c4cddc5814fe:" + "8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0," + "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," + "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," + ":|5742195a81349f1306361d71a050c4cddc5814fe:" + "8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0," + "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," + "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," + ":|5742195a81349f1306361d71a050c4cddc5814fe:" + "7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498," + ":0000000000000000000000000000000000000000000000000000000000000001|"; + EXPECT_EQ(Interp.LogsSignature, ExpectedLogsSignature); + + auto ExpectStorageOracle = [](const EVMExecutionResult &Result) { + const evmc::bytes32 Slot0{}; + evmc::bytes32 Slot33{}; + Slot33.bytes[31] = 0x33; + + ASSERT_EQ(Result.RecipientStorage.size(), 2u); + const auto Slot0It = Result.RecipientStorage.find(Slot0); + ASSERT_NE(Slot0It, Result.RecipientStorage.end()); + EXPECT_EQ( + zen::utils::toHex(Slot0It->second.current.bytes, + sizeof(Slot0It->second.current.bytes)), + "0000000000000000000000000000000000000000000000000000000000000001"); + + const auto Slot33It = Result.RecipientStorage.find(Slot33); + ASSERT_NE(Slot33It, Result.RecipientStorage.end()); + EXPECT_EQ( + zen::utils::toHex(Slot33It->second.current.bytes, + sizeof(Slot33It->second.current.bytes)), + "00000000000000000000000099AAECD05F9B699D1F07BEE4EEF40D64A2A5CB3D"); + }; + ExpectStorageOracle(Interp); EXPECT_EQ(Multi.Status, Interp.Status); EXPECT_EQ(Multi.GasLeft, Interp.GasLeft); EXPECT_EQ(Multi.OutputHex, Interp.OutputHex); EXPECT_EQ(Multi.LogCount, Interp.LogCount); EXPECT_EQ(Multi.LogsSignature, Interp.LogsSignature); + EXPECT_EQ(Multi.LogsSignature, ExpectedLogsSignature); + ExpectStorageOracle(Multi); +} + +TEST(EVMRangeDifferential, UnresolvedJumpiTakenTargetPreservesGas) { + const std::vector Bytecode = { + 0x60, 0x00, 0x35, // PC0 condition = calldata[0] + 0x60, 0x20, 0x35, // PC3 destination = calldata[32] + 0x57, // PC6 dynamic JUMPI + 0x5f, 0x50, // PC7 untaken-only fallthrough cost + 0x5b, 0x5a, // PC9 dynamic target; observe GAS + 0x5f, 0x52, // PC11 MSTORE(0, gas) + 0x60, 0x20, 0x5f, 0xf3, + }; + std::vector TakenCallData(64, 0); + TakenCallData[31] = 1; + TakenCallData[63] = 9; + + const auto TakenInterp = + runEvmBytecode("unresolved_jumpi_taken_target_interp", Bytecode, + common::RunMode::InterpMode, TakenCallData, 0u, true, + 0x2210, evmc_revision::EVMC_CANCUN); + const auto TakenMulti = + runEvmBytecode("unresolved_jumpi_taken_target_multipass", Bytecode, + common::RunMode::MultipassMode, TakenCallData, 0u, true, + 0x2210, evmc_revision::EVMC_CANCUN); +#ifdef ZEN_ENABLE_JIT + EXPECT_TRUE(TakenMulti.JITCompiled); +#endif + constexpr char ExpectedTakenGasOutput[] = + "00000000000000000000000000000000000000000000000000000000000021F7"; + EXPECT_EQ(TakenInterp.Status, EVMC_SUCCESS); + EXPECT_EQ(TakenInterp.OutputHex, ExpectedTakenGasOutput); + EXPECT_EQ(TakenMulti.Status, TakenInterp.Status); + EXPECT_EQ(TakenMulti.GasLeft, TakenInterp.GasLeft); + EXPECT_EQ(TakenMulti.OutputHex, ExpectedTakenGasOutput); + + std::vector FallthroughCallData = TakenCallData; + FallthroughCallData[31] = 0; + const auto FallthroughInterp = + runEvmBytecode("unresolved_jumpi_fallthrough_interp", Bytecode, + common::RunMode::InterpMode, FallthroughCallData, 0u, true, + 0x2210, evmc_revision::EVMC_CANCUN); + const auto FallthroughMulti = + runEvmBytecode("unresolved_jumpi_fallthrough_multipass", Bytecode, + common::RunMode::MultipassMode, FallthroughCallData, 0u, + true, 0x2210, evmc_revision::EVMC_CANCUN); +#ifdef ZEN_ENABLE_JIT + EXPECT_TRUE(FallthroughMulti.JITCompiled); +#endif + constexpr char ExpectedFallthroughGasOutput[] = + "00000000000000000000000000000000000000000000000000000000000021F3"; + EXPECT_EQ(FallthroughInterp.Status, EVMC_SUCCESS); + EXPECT_EQ(FallthroughInterp.OutputHex, ExpectedFallthroughGasOutput); + EXPECT_EQ(FallthroughMulti.Status, FallthroughInterp.Status); + EXPECT_EQ(FallthroughMulti.GasLeft, FallthroughInterp.GasLeft); + EXPECT_EQ(FallthroughMulti.OutputHex, ExpectedFallthroughGasOutput); } // Sweep SHL/SHR/SAR with shift amounts that land inside the limb-crossing From 20fd9a780fb82e77f1cafb6f7000ab4a80927709 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 28 Jul 2026 07:42:26 +0000 Subject: [PATCH 3/6] test(runtime): make SPP regression self-contained Move the mainnet bytecode into a test-only header and document the SPP gas boundaries. --- .../README.md | 84 +++++++ src/evm/evm_cache.md | 59 +++-- src/tests/evm_differential_tests.cpp | 32 ++- src/tests/evm_spp_gas_regression_data.h | 225 ++++++++++++++++++ .../block21800020_tx260/calldata.hex | 1 - .../block21800020_tx260/runtime.hex | 1 - 6 files changed, 361 insertions(+), 41 deletions(-) create mode 100644 docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md create mode 100644 src/tests/evm_spp_gas_regression_data.h delete mode 100644 tests/evm_regression_data/block21800020_tx260/calldata.hex delete mode 100644 tests/evm_regression_data/block21800020_tx260/runtime.hex diff --git a/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md b/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md new file mode 100644 index 000000000..4c20b8742 --- /dev/null +++ b/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md @@ -0,0 +1,84 @@ +# Change: Preserve gas semantics at EVM SPP boundaries + +- **Status**: Implemented +- **Date**: 2026-07-28 +- **Tier**: Light +- **PR**: #579 + +This fix closes two unsafe SPP boundary classes with 0% `GasBlock` size growth. +Retain both the unresolved-source and implicit-target guards to preserve gas +semantics. + +## Overview + +The Structured Precharging Pass (SPP) must not rely only on total path cost at +these two boundaries: + +- `SSTORE`, whose EIP-2200 sentry depends on the gas remaining at the + instruction; +- unresolved dynamic `JUMP` and `JUMPI` sources, whose runtime successor set + is incomplete in the explicit cache-build CFG. + +The implementation treats `SSTORE` as a gas-sensitive boundary and rejects +source-side shifts from blocks with omitted dynamic successors. The existing +implicit-predecessor check continues to reject shifts into possible dynamic +targets. + +## Motivation + +SPP may move a successor block's gas charge into its predecessor. This +transformation is valid only when intermediate gas cannot affect execution and +every runtime successor receives the corresponding compensation. + +Precharging later work before `SSTORE` can change a successful execution into +an out-of-gas failure at the EIP-2200 call-stipend threshold. At an unresolved +dynamic `JUMPI`, moving the explicit fallthrough cost onto the source also +charges the taken path even though its omitted target receives no compensating +reduction. + +## Impact + +- `src/evm/evm_cache.cpp` adds the two scheduling guards. +- `GasBlock` stores the omitted-successor flag in existing padding and remains + 32 bytes. +- `src/evm/evm_cache.md` and `docs/modules/evm/cache-build.md` record the + source, successor, and CFG invariants used by SPP scheduling. +- Cache-level and interpreter-versus-multipass regressions cover both failure + modes without introducing a new runtime component. +- No API, ABI, configuration, or persisted-data format changes are introduced. +- The guards can reduce SPP scheduling opportunities around `SSTORE` and + unresolved dynamic jumps. Applying the `SSTORE` boundary before Istanbul is + intentionally conservative. No performance claim is made. + +## Verification + +The production implementation at commit +`79540851a852d5eb2fbc1f847c2fc6f95acd7aff` was validated by: + +- tracked-source formatting and a clean Release all-target build, with no + warning diagnostics from changed files; +- focused cache regressions: 2/2; +- focused interpreter-versus-multipass regressions: 2/2; +- CTest: 12/12 targets; +- interpreter unit, Cancun state, and EVM assembly suites: 215/215, 2723/2723, + and 209/209; +- multipass unit, Cancun state, and EVM assembly suites: 223/223, 2723/2723, + and 209/209. + +A sealed multipass replay of blocks 21,800,000--21,800,031 covered 32/32 +blocks, 4,993 transactions, and 594,578,894 gas. Its semantic summary matched +the frozen reference, and its exported post-state was byte-identical. The +replay used Git tree `97dd4837b1803f72e3b3c4fc742fec691b09d115` and +`libdtvmapi.so.0.1.0` SHA-256 +`5135b4a4424a92c4e66cce6c86df01e688998468341e3dd0292bbb1f7ff2d73a`. +This evidence covers the production implementation in +`src/evm/evm_cache.cpp` blob +`6ca5d7a55812920d4d0e1de8b258c176c3d3c252`; it does not claim that a later +documentation or test-only head was itself replayed. + +## Checklist + +- [x] Implementation complete +- [x] Tests added/updated +- [x] Module specs in `docs/modules/` updated +- [x] Build and tests pass diff --git a/src/evm/evm_cache.md b/src/evm/evm_cache.md index c6a8bb644..93019cbf5 100644 --- a/src/evm/evm_cache.md +++ b/src/evm/evm_cache.md @@ -2,6 +2,11 @@ This document describes the bytecode cache built by `buildBytecodeCache()` in `src/evm/evm_cache.cpp` and used by `BaseInterpreter::interpret()` in `src/evm/interpreter.cpp` as well as the EVM JIT compiler in `src/compiler/evm_compiler.cpp`. +The current SPP design fixes two unsafe gas-shifting boundary classes with 0% +`GasBlock` size growth; the structure remains 32 bytes. Retain both the +unresolved-source guard and the implicit-target predecessor guard because +removing either can make gas placement unsound. + ## Layout - `JumpDestMap[pc]` (`uint8_t`): `1` if `Code[pc]` is `OP_JUMPDEST` and this byte is an opcode byte (not inside PUSH data). @@ -32,6 +37,7 @@ We still partition the bytecode into straight-line "gas blocks": - `INVALID` - `JUMP`, `JUMPI` - `GAS` + - `SSTORE` - `CREATE`, `CREATE2` - `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL` @@ -51,9 +57,12 @@ every execution path. We build a CFG of gas blocks and compute a *shifted* metering function `m` using a linear-time SPP pass: -- Edges: fallthrough edges (including `JUMPI` fallthrough) and constant-jump - edges (validated by `JumpDestMap`). Dynamic jumps are conservatively - over-approximated to all `JUMPDEST` blocks. +- Edges: fallthrough edges, including `JUMPI` fallthrough, are explicit. + Resolved jump-target edges are also explicit after validation by + `JumpDestMap`. Target edges for an unresolved dynamic `JUMP` or `JUMPI` are + omitted. The source is marked with `HasUnresolvedDynamicSuccessor`, and each + possible `JUMPDEST` target carries the corresponding + `ImplicitDynamicPredCount`. - Critical edges are split before SPP to preserve the local update rules. - Dominators are computed by the Cooper-Harvey-Kennedy (CHK) algorithm (`computeDomInfo` in `evm_cache.cpp`): iterate `IDom[b] = NCA(p, IDom[b])` @@ -82,14 +91,14 @@ emits a CSV row per named phase to stderr: EVM_CACHE_PROFILE,, -Named phases: `buildGasBlocks`, `collectJumpDests`, `buildCFGEdges`, -`splitCriticalEdges`, `computeReachable`, `computeDomInfo`, `findBackEdges`, -`computeReverseTopo`, `computeInCycle`, `buildLoopsUsingDominance`, -`meteringInit`, `lemma614Schedule`, `writeback`. When `OFF` (default), the -macros expand to `((void)0)` and the release build is bytecode-identical to -the un-instrumented variant — used to drive `tools/bench_evm_cache.sh` and -`tools/analyze_evm_cache_bench.py` for paired-ratio cluster-bootstrap BCa -analysis (see `tests/corpus/evm-cache/`). +Named phases: `buildJumpDestMap`, `buildGasBlocks`, `buildCFGEdges`, +`splitCriticalEdges`, `buildCSR`, `computeReachable`, `computeDomInfo`, +`findBackEdges`, `computeReverseTopo`, `buildLoopsUsingDominance`, +`computeInCycle`, `meteringInit`, `lemma614Schedule`, `writeback`. When `OFF` +(default), the macros expand to `((void)0)` and the release build is +bytecode-identical to the un-instrumented variant — used to drive +`tools/bench_evm_cache.sh` and `tools/analyze_evm_cache_bench.py` for +paired-ratio cluster-bootstrap BCa analysis (see `tests/corpus/evm-cache/`). This moves common costs earlier, reducing the number of non-zero charge points. The resulting shifted value `m(s)` is stored in `GasChunkCostSPP[s]` at each @@ -99,8 +108,11 @@ modules that will be JIT-compiled (gated by `EnableSPP` in `buildBytecodeCache`); for interpreter-only modules `GasChunkCostSPP` is left empty and the CFG / metering work is skipped. -If the CFG is not suitable for linear SPP (e.g., dominance-based loop analysis -fails), we still run SPP updates once per node in reverse topological order +`UseLinearSPP=true` means only that the detected dominance-based natural loops +passed their body-dominance and nesting checks; it is not a general CFG +reducibility proof. In this path, `InCycle` is the union of the detected loop +masks. If those checks fail, a two-pass Kosaraju-style SCC traversal computes +`InCycle`, and SPP updates only non-cycle nodes in reverse topological order without loop fast-forward. ## Design Goal @@ -135,12 +147,15 @@ zero bytes on the right, matching the EVM encoding. interpreter's fast path enters a chunk only when `gas_left >= GasChunkCost[s]` and base-cost out-of-gas cannot occur inside a block. The multipass JIT reads the shifted value `m(s)` from `GasChunkCostSPP[s]`. Lemma 6.14 updates move -cost along CFG edges while preserving total base cost on every path. -Over-approximating dynamic jumps to all `JUMPDEST`s keeps the optimization -safe — narrowing those edges with partial call-site resolution would -under-approximate the CFG and let the SPP pass shift gas along edges that -don't exist at runtime, producing unsafe metering. Splitting critical edges -ensures that cost is only moved along edges where the local update is valid. -When loop analysis fails, the reverse-topological updates still preserve -correctness without fast-forward. Dynamic/extra gas is charged inside opcode -handlers as before (memory expansion, cold access, keccak word cost, etc). +cost along represented CFG edges while preserving total base cost on accepted +paths. An unresolved dynamic source has +`HasUnresolvedDynamicSuccessor != 0`, so it cannot receive shifted successor +cost when runtime targets are absent from the explicit CFG. +`effectivePredCount` includes `ImplicitDynamicPredCount`, so a possible dynamic +target cannot receive a shift from only one represented predecessor. `SSTORE` +is also a gas-sensitive boundary because the EIP-2200 sentry depends on the gas +remaining at that instruction. Splitting critical edges and the loop schedule +retain the local update preconditions; the SCC fallback skips cycle nodes and +applies per-node updates without fast-forward. Dynamic and extra gas remain +charged inside opcode handlers as before (memory expansion, cold access, +keccak word cost, and related charges). diff --git a/src/tests/evm_differential_tests.cpp b/src/tests/evm_differential_tests.cpp index 086ce0b4d..2df1bef02 100644 --- a/src/tests/evm_differential_tests.cpp +++ b/src/tests/evm_differential_tests.cpp @@ -13,6 +13,7 @@ #include "compiler/evm_frontend/evm_analyzer.h" #include "evm/evm.h" +#include "evm_spp_gas_regression_data.h" #include "evm_test_host.hpp" #include "runtime/evm_module.h" #include "utils/evm.h" @@ -697,25 +698,22 @@ TEST(EVMRangeDifferential, } TEST(EVMRangeDifferential, Block21800020Tx260MatchesInterpreter) { - const auto FixtureDir = - getEvmAsmDirPath().parent_path() / - std::filesystem::path("evm_regression_data/block21800020_tx260"); - const auto BytecodePath = (FixtureDir / "runtime.hex").string(); - const auto CallDataPath = (FixtureDir / "calldata.hex").string(); - - std::ifstream CallDataFile(CallDataPath); - ASSERT_TRUE(CallDataFile.is_open()); - std::string CallDataHex; - CallDataFile >> CallDataHex; - auto CallData = zen::utils::fromHex(CallDataHex); + const auto Bytecode = + zen::utils::fromHex(zen::evm::test_data::Block21800020Tx260RuntimeHex); + const auto CallData = + zen::utils::fromHex(zen::evm::test_data::Block21800020Tx260CalldataHex); + ASSERT_TRUE(Bytecode); ASSERT_TRUE(CallData); + ASSERT_EQ(Bytecode->size(), 7'005u); + ASSERT_EQ(CallData->size(), 164u); - const auto Interp = - runEvmBytecodeFile(BytecodePath, common::RunMode::InterpMode, *CallData, - true, 31'922, evmc_revision::EVMC_CANCUN, true); - const auto Multi = runEvmBytecodeFile( - BytecodePath, common::RunMode::MultipassMode, *CallData, true, 31'922, - evmc_revision::EVMC_CANCUN, true); + const auto Interp = runEvmBytecode( + "block21800020_tx260_interp", *Bytecode, common::RunMode::InterpMode, + *CallData, 0u, true, 31'922, evmc_revision::EVMC_CANCUN, true); + const auto Multi = + runEvmBytecode("block21800020_tx260_multipass", *Bytecode, + common::RunMode::MultipassMode, *CallData, 0u, true, + 31'922, evmc_revision::EVMC_CANCUN, true); #ifdef ZEN_ENABLE_JIT EXPECT_TRUE(Multi.JITCompiled); #endif diff --git a/src/tests/evm_spp_gas_regression_data.h b/src/tests/evm_spp_gas_regression_data.h new file mode 100644 index 000000000..02d588444 --- /dev/null +++ b/src/tests/evm_spp_gas_regression_data.h @@ -0,0 +1,225 @@ +// Copyright (C) 2025 the DTVM authors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H +#define ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H + +#include + +namespace zen::evm::test_data { + +// Captured from mainnet block 21800020, transaction 260. +// Decoded runtime SHA-256: +// cb4ee5cc0b651a5974d6ee0d6e389ff56cbb793ad279c27ba522335c15b0c1f5 +inline constexpr std::string_view Block21800020Tx260RuntimeHex = + "0x608060405234801561001057600080fd5b50600436106101505760003560e01c80638d" + "3638f4116100cd578063d5438eae11610081578063f2fde38b11610066578063f2fde38b" + "14610347578063f7e83aee1461035a578063fbc69aab1461037d57600080fd5b8063d543" + "8eae14610300578063de523cf31461032757600080fd5b806393c44847116100b2578063" + "93c44847146102915780639d8ecd85146102da578063c4d66de8146102ed57600080fd5b" + "80638d3638f4146102375780638da5cb5b1461027357600080fd5b8063440df4f4116101" + "245780636465e69f116101095780636465e69f146101f5578063715018a61461020f5780" + "637f5a7c7b1461021757600080fd5b8063440df4f4146101cd5780634c0a2ffc146101e2" + "57600080fd5b8062d84fd8146101555780630e72cc061461016a57806315ce45a2146101" + "7d5780633dfd3873146101ba575b600080fd5b6101686101633660046115a6565b610390" + "565b005b6101686101783660046115e3565b6103a4565b61019061018b36600461164956" + "5b6104f2565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260" + "20015b60405180910390f35b6101686101c83660046115e3565b61050a565b6101d56106" + "4b565b6040516101b1919061168b565b6101686101f03660046116cf565b61065c565b61" + "01fd600181565b60405160ff90911681526020016101b1565b610168610672565b606854" + "6101909073ffffffffffffffffffffffffffffffffffffffff1681565b61025e7f000000" + "000000000000000000000000000000000000000000000000000000000181565b60405163" + "ffffffff90911681526020016101b1565b60335473ffffffffffffffffffffffffffffff" + "ffffffffff16610190565b6102cd6040518060400160405280600681526020017f352e31" + "312e32000000000000000000000000000000000000000000000000000081525081565b60" + "40516101b1919061172a565b6101686102e83660046117c0565b610686565b6101686102" + "fb3660046115e3565b610903565b6101907f000000000000000000000000c005dc82818d" + "67af737725bd4bf75435d065d23981565b6069546101909073ffffffffffffffffffffff" + "ffffffffffffffffff1681565b6101686103553660046115e3565b610a97565b61036d61" + "0368366004611843565b610b4b565b60405190151581526020016101b1565b6101906103" + "8b3660046115a6565b610be1565b610398610caa565b6103a181610d2b565b50565b8073" + "ffffffffffffffffffffffffffffffffffffffff81163b1515806103de575073ffffffff" + "ffffffffffffffffffffffffffffffff8116155b61046f576040517f08c379a000000000" + "000000000000000000000000000000000000000000000000815260206004820152602760" + "248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e7472616374" + "2060448201527f73657474696e6700000000000000000000000000000000000000000000" + "00000060648201526084015b60405180910390fd5b610477610caa565b606980547fffff" + "ffffffffffffffffffff00000000000000000000000000000000000000001673ffffffff" + "ffffffffffffffffffffffffffffffff84169081179091556040519081527fc47cbcc588" + "c67679e52261c45cc315e56562f8d0ccaba16facb9093ff9498799906020015b60405180" + "910390a15050565b600061050161038b8484610d80565b90505b92915050565b8073ffff" + "ffffffffffffffffffffffffffffffffffff81163b151580610544575073ffffffffffff" + "ffffffffffffffffffffffffffff8116155b6105d0576040517f08c379a0000000000000" + "000000000000000000000000000000000000000000008152602060048201526027602482" + "01527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060" + "448201527f73657474696e67000000000000000000000000000000000000000000000000" + "006064820152608401610466565b6105d8610caa565b606880547fffffffffffffffffff" + "ffffff00000000000000000000000000000000000000001673ffffffffffffffffffffff" + "ffffffffffffffffff84169081179091556040519081527f4eab7b127c76430878862236" + "3ad3e9532de3dfba7845bd4f84c125a22544255a906020016104e6565b60606106576065" + "610da3565b905090565b610664610caa565b61066e8282610e3e565b5050565b61067a61" + "0caa565b6106846000610ee4565b565b600054610100900460ff16158080156106a65750" + "600054600160ff909116105b806106c05750303b1580156106c0575060005460ff166001" + "145b61074c576040517f08c379a000000000000000000000000000000000000000000000" + "000000000000815260206004820152602e60248201527f496e697469616c697a61626c65" + "3a20636f6e747261637420697320616c72656160448201527f647920696e697469616c69" + "7a65640000000000000000000000000000000000006064820152608401610466565b6000" + "80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016" + "600117905580156107aa57600080547fffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffff00ff166101001790555b6107b2610f5b565b83821461081b5760" + "40517f08c379a00000000000000000000000000000000000000000000000000000000081" + "5260206004820152600f60248201527f6c656e677468206d69736d617463680000000000" + "0000000000000000000000006044820152606401610466565b8360005b8181101561088d" + "5761087d87878381811061083c5761083c6118af565b9050602002016020810190610851" + "91906115a6565b868684818110610863576108636118af565b9050602002016020810190" + "61087891906115e3565b610e3e565b6108868161190d565b905061081f565b5061089787" + "610ee4565b5080156108fb57600080547fffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f13" + "3852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050" + "505050565b600054610100900460ff16158080156109235750600054600160ff90911610" + "5b8061093d5750303b15801561093d575060005460ff166001145b6109c9576040517f08" + "c379a0000000000000000000000000000000000000000000000000000000008152602060" + "04820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420" + "697320616c72656160448201527f647920696e697469616c697a65640000000000000000" + "000000000000000000006064820152608401610466565b600080547fffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a2757" + "600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" + "ff166101001790555b610a2f610f5b565b610a3882610ee4565b801561066e5760008054" + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055" + "604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38" + "47402498906020016104e6565b610a9f610caa565b73ffffffffffffffffffffffffffff" + "ffffffffffff8116610b42576040517f08c379a000000000000000000000000000000000" + "000000000000000000000000815260206004820152602660248201527f4f776e61626c65" + "3a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573" + "730000000000000000000000000000000000000000000000000000606482015260840161" + "0466565b6103a181610ee4565b6000610b5783836104f2565b73ffffffffffffffffffff" + "ffffffffffffffffffff1663f7e83aee868686866040518563ffffffff1660e01b815260" + "0401610b95949392919061198e565b6020604051808303816000875af1158015610bb457" + "3d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190" + "610bd891906119c0565b95945050505050565b60008080610bf9606563ffffffff808716" + "90610ffa16565b915091508115610c1457610c0c81611013565b949350505050565b7f00" + "0000000000000000000000c005dc82818d67af737725bd4bf75435d065d23973ffffffff" + "ffffffffffffffffffffffffffffffff16636e5f516e6040518163ffffffff1660e01b81" + "52600401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050" + "506040513d601f19601f82011682018060405250810190610c0c91906119e2565b505091" + "9050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106845760" + "40517f08c379a00000000000000000000000000000000000000000000000000000000081" + "5260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e" + "6f7420746865206f776e65726044820152606401610466565b610d3f606563ffffffff80" + "8416906110bc16565b610d48826110c8565b9061066e576040517f08c379a00000000000" + "00000000000000000000000000000000000000000000008152600401610466919061172a" + "565b6000610d906009600584866119ff565b610d9991611a29565b60e01c939250505056" + "5b60606000610db0836110ff565b90508067ffffffffffffffff811115610dcb57610dcb" + "611a71565b604051908082528060200260200182016040528015610df457816020016020" + "8202803683370190505b50915060005b81811015610ca357610e0c848261110a565b6000" + "1c838281518110610e2157610e216118af565b602090810291909101015280610e368161" + "190d565b915050610dfa565b73ffffffffffffffffffffffffffffffffffffffff81163b" + "610ebc576040517f08c379a0000000000000000000000000000000000000000000000000" + "00000000815260206004820152601660248201527f49534d206d75737420626520612063" + "6f6e7472616374000000000000000000006044820152606401610466565b61066e606563" + "ffffffff841673ffffffffffffffffffffffffffffffffffffffff8416611116565b6033" + "805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffff" + "ffffff000000000000000000000000000000000000000083168117909355604051911691" + "9082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0" + "90600090a35050565b600054610100900460ff16610ff2576040517f08c379a000000000" + "000000000000000000000000000000000000000000000000815260206004820152602b60" + "248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420" + "6960448201527f6e697469616c697a696e67000000000000000000000000000000000000" + "0000006064820152608401610466565b610684611127565b60008061100784846111c756" + "5b915091505b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff" + "8211156110b8576040517f08c379a0000000000000000000000000000000000000000000" + "000000000000008152602060048201526024808201527f5479706543617374733a206279" + "7465733332546f41646472657373206f76657260448201527f666c6f7700000000000000" + "0000000000000000000000000000000000000000006064820152608401610466565b5090" + "565b60006105018383611201565b60606110d98263ffffffff1661121e565b6040516020" + "016110e99190611aa0565b6040516020818303038152906040529050919050565b600061" + "0504826112dc565b600061050183836112e6565b611121838383611310565b5050505056" + "5b600054610100900460ff166111be576040517f08c379a0000000000000000000000000" + "00000000000000000000000000000000815260206004820152602b60248201527f496e69" + "7469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e" + "697469616c697a696e670000000000000000000000000000000000000000006064820152" + "608401610466565b61068433610ee4565b60008181526002830160205260408120548190" + "806111f6576111e9858561132d565b92506000915061100c9050565b6001925090506110" + "0c565b600081815260028301602052604081208190556105018383611339565b60606000" + "61122b83611345565b600101905060008167ffffffffffffffff81111561124b5761124b" + "611a71565b6040519080825280601f01601f191660200182016040528015611275576020" + "820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffff017f30313233343536373839616263646566" + "00000000000000000000000000000000600a86061a8153600a850494508461127f575093" + "92505050565b6000610504825490565b60008260000182815481106112fd576112fd6118" + "af565b9060005260206000200154905092915050565b6000828152600284016020526040" + "8120829055610c0c8484611427565b60006105018383611433565b600061050183836114" + "4b565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310" + "61138e577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083049250" + "6040015b6d04ee2d6d415b85acef810000000083106113ba576d04ee2d6d415b85acef81" + "00000000830492506020015b662386f26fc1000083106113d857662386f26fc100008304" + "92506010015b6305f5e10083106113f0576305f5e100830492506008015b612710831061" + "140457612710830492506004015b60648310611416576064830492506002015b600a8310" + "6105045760010192915050565b6000610501838361153e565b6000818152600183016020" + "5260408120541515610501565b6000818152600183016020526040812054801561153457" + "600061146f600183611ae5565b855490915060009061148390600190611ae5565b905081" + "81146114e85760008660000182815481106114a3576114a36118af565b90600052602060" + "002001549050808760000184815481106114c6576114c66118af565b6000918252602080" + "832090910192909255918252600188019052604090208390555b85548690806114f95761" + "14f9611af8565b6001900381819060005260206000200160009055905585600101600086" + "81526020019081526020016000206000905560019350505050610504565b600091505061" + "0504565b6000818152600183016020526040812054611585575081546001818101845560" + "008481526020808220909301849055845484825282860190935260409020919091556105" + "04565b506000610504565b803563ffffffff811681146115a157600080fd5b919050565b" + "6000602082840312156115b857600080fd5b6105018261158d565b73ffffffffffffffff" + "ffffffffffffffffffffffff811681146103a157600080fd5b6000602082840312156115" + "f557600080fd5b8135611600816115c1565b9392505050565b60008083601f8401126116" + "1957600080fd5b50813567ffffffffffffffff81111561163157600080fd5b6020830191" + "5083602082850101111561100c57600080fd5b6000806020838503121561165c57600080" + "fd5b823567ffffffffffffffff81111561167357600080fd5b61167f8582860161160756" + "5b90969095509350505050565b6020808252825182820181905260009190848201906040" + "850190845b818110156116c3578351835292840192918401916001016116a7565b509096" + "95505050505050565b600080604083850312156116e257600080fd5b6116eb8361158d56" + "5b915060208301356116fb816115c1565b809150509250929050565b60005b8381101561" + "1721578181015183820152602001611709565b50506000910152565b6020815260008251" + "806020840152611749816040850160208701611706565b601f017fffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056" + "5b60008083601f84011261178d57600080fd5b50813567ffffffffffffffff8111156117" + "a557600080fd5b6020830191508360208260051b850101111561100c57600080fd5b6000" + "806000806000606086880312156117d857600080fd5b85356117e3816115c1565b945060" + "2086013567ffffffffffffffff8082111561180057600080fd5b61180c89838a0161177b" + "565b9096509450604088013591508082111561182557600080fd5b506118328882890161" + "177b565b969995985093965092949392505050565b600080600080604085870312156118" + "5957600080fd5b843567ffffffffffffffff8082111561187157600080fd5b61187d8883" + "8901611607565b9096509450602087013591508082111561189657600080fd5b506118a3" + "87828801611607565b95989497509550505050565b7f4e487b7100000000000000000000" + "000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b" + "710000000000000000000000000000000000000000000000000000000060005260116004" + "5260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffff820361193e5761193e6118de565b5060010190565b818352818160208501" + "3750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006119" + "a2604083018688611945565b82810360208401526119b5818587611945565b9796505050" + "50505050565b6000602082840312156119d257600080fd5b815180151581146116005760" + "0080fd5b6000602082840312156119f457600080fd5b8151611600816115c1565b600080" + "85851115611a0f57600080fd5b83861115611a1c57600080fd5b50508201939190920391" + "50565b7fffffffff00000000000000000000000000000000000000000000000000000000" + "8135818116916004851015611a695780818660040360031b1b83161692505b5050929150" + "50565b7f4e487b7100000000000000000000000000000000000000000000000000000000" + "600052604160045260246000fd5b7f4e6f2049534d20666f756e6420666f72206f726967" + "696e3a2000000000000000815260008251611ad8816019850160208701611706565b9190" + "910160190192915050565b81810381811115610504576105046118de565b7f4e487b7100" + "000000000000000000000000000000000000000000000000000000600052603160045260" + "246000fdfea2646970667358221220b228bdbbde9b718bad3c2a3328cd105fcdd195acfe" + "ca535172d620046167ee6364736f6c63430008130033"; + +// Decoded calldata SHA-256: +// 6f191b9d7f68717789f8a76435fc7a91c255e7b8a9c39e1f5fbe91ded93b220b +inline constexpr std::string_view Block21800020Tx260CalldataHex = + "0x9d8ecd8500000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb" + "3d0000000000000000000000000000000000000000000000000000000000000060000000" + "000000000000000000000000000000000000000000000000000000008000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000"; + +static_assert(Block21800020Tx260RuntimeHex.size() == 14'012); +static_assert(Block21800020Tx260CalldataHex.size() == 330); + +} // namespace zen::evm::test_data + +#endif // ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H diff --git a/tests/evm_regression_data/block21800020_tx260/calldata.hex b/tests/evm_regression_data/block21800020_tx260/calldata.hex deleted file mode 100644 index 8ba650f67..000000000 --- a/tests/evm_regression_data/block21800020_tx260/calldata.hex +++ /dev/null @@ -1 +0,0 @@ -0x9d8ecd8500000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/tests/evm_regression_data/block21800020_tx260/runtime.hex b/tests/evm_regression_data/block21800020_tx260/runtime.hex deleted file mode 100644 index e29d008e8..000000000 --- a/tests/evm_regression_data/block21800020_tx260/runtime.hex +++ /dev/null @@ -1 +0,0 @@ -0x608060405234801561001057600080fd5b50600436106101505760003560e01c80638d3638f4116100cd578063d5438eae11610081578063f2fde38b11610066578063f2fde38b14610347578063f7e83aee1461035a578063fbc69aab1461037d57600080fd5b8063d5438eae14610300578063de523cf31461032757600080fd5b806393c44847116100b257806393c44847146102915780639d8ecd85146102da578063c4d66de8146102ed57600080fd5b80638d3638f4146102375780638da5cb5b1461027357600080fd5b8063440df4f4116101245780636465e69f116101095780636465e69f146101f5578063715018a61461020f5780637f5a7c7b1461021757600080fd5b8063440df4f4146101cd5780634c0a2ffc146101e257600080fd5b8062d84fd8146101555780630e72cc061461016a57806315ce45a21461017d5780633dfd3873146101ba575b600080fd5b6101686101633660046115a6565b610390565b005b6101686101783660046115e3565b6103a4565b61019061018b366004611649565b6104f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101686101c83660046115e3565b61050a565b6101d561064b565b6040516101b1919061168b565b6101686101f03660046116cf565b61065c565b6101fd600181565b60405160ff90911681526020016101b1565b610168610672565b6068546101909073ffffffffffffffffffffffffffffffffffffffff1681565b61025e7f000000000000000000000000000000000000000000000000000000000000000181565b60405163ffffffff90911681526020016101b1565b60335473ffffffffffffffffffffffffffffffffffffffff16610190565b6102cd6040518060400160405280600681526020017f352e31312e32000000000000000000000000000000000000000000000000000081525081565b6040516101b1919061172a565b6101686102e83660046117c0565b610686565b6101686102fb3660046115e3565b610903565b6101907f000000000000000000000000c005dc82818d67af737725bd4bf75435d065d23981565b6069546101909073ffffffffffffffffffffffffffffffffffffffff1681565b6101686103553660046115e3565b610a97565b61036d610368366004611843565b610b4b565b60405190151581526020016101b1565b61019061038b3660046115a6565b610be1565b610398610caa565b6103a181610d2b565b50565b8073ffffffffffffffffffffffffffffffffffffffff81163b1515806103de575073ffffffffffffffffffffffffffffffffffffffff8116155b61046f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e670000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610477610caa565b606980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fc47cbcc588c67679e52261c45cc315e56562f8d0ccaba16facb9093ff9498799906020015b60405180910390a15050565b600061050161038b8484610d80565b90505b92915050565b8073ffffffffffffffffffffffffffffffffffffffff81163b151580610544575073ffffffffffffffffffffffffffffffffffffffff8116155b6105d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060448201527f73657474696e67000000000000000000000000000000000000000000000000006064820152608401610466565b6105d8610caa565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527f4eab7b127c764308788622363ad3e9532de3dfba7845bd4f84c125a22544255a906020016104e6565b60606106576065610da3565b905090565b610664610caa565b61066e8282610e3e565b5050565b61067a610caa565b6106846000610ee4565b565b600054610100900460ff16158080156106a65750600054600160ff909116105b806106c05750303b1580156106c0575060005460ff166001145b61074c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610466565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107aa57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6107b2610f5b565b83821461081b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6c656e677468206d69736d6174636800000000000000000000000000000000006044820152606401610466565b8360005b8181101561088d5761087d87878381811061083c5761083c6118af565b905060200201602081019061085191906115a6565b868684818110610863576108636118af565b905060200201602081019061087891906115e3565b610e3e565b6108868161190d565b905061081f565b5061089787610ee4565b5080156108fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b600054610100900460ff16158080156109235750600054600160ff909116105b8061093d5750303b15801561093d575060005460ff166001145b6109c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610466565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a2757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a2f610f5b565b610a3882610ee4565b801561066e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016104e6565b610a9f610caa565b73ffffffffffffffffffffffffffffffffffffffff8116610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610466565b6103a181610ee4565b6000610b5783836104f2565b73ffffffffffffffffffffffffffffffffffffffff1663f7e83aee868686866040518563ffffffff1660e01b8152600401610b95949392919061198e565b6020604051808303816000875af1158015610bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd891906119c0565b95945050505050565b60008080610bf9606563ffffffff80871690610ffa16565b915091508115610c1457610c0c81611013565b949350505050565b7f000000000000000000000000c005dc82818d67af737725bd4bf75435d065d23973ffffffffffffffffffffffffffffffffffffffff16636e5f516e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0c91906119e2565b5050919050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610466565b610d3f606563ffffffff808416906110bc16565b610d48826110c8565b9061066e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610466919061172a565b6000610d906009600584866119ff565b610d9991611a29565b60e01c9392505050565b60606000610db0836110ff565b90508067ffffffffffffffff811115610dcb57610dcb611a71565b604051908082528060200260200182016040528015610df4578160200160208202803683370190505b50915060005b81811015610ca357610e0c848261110a565b60001c838281518110610e2157610e216118af565b602090810291909101015280610e368161190d565b915050610dfa565b73ffffffffffffffffffffffffffffffffffffffff81163b610ebc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f49534d206d757374206265206120636f6e7472616374000000000000000000006044820152606401610466565b61066e606563ffffffff841673ffffffffffffffffffffffffffffffffffffffff8416611116565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610ff2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610466565b610684611127565b60008061100784846111c7565b915091505b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff8211156110b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5479706543617374733a2062797465733332546f41646472657373206f76657260448201527f666c6f77000000000000000000000000000000000000000000000000000000006064820152608401610466565b5090565b60006105018383611201565b60606110d98263ffffffff1661121e565b6040516020016110e99190611aa0565b6040516020818303038152906040529050919050565b6000610504826112dc565b600061050183836112e6565b611121838383611310565b50505050565b600054610100900460ff166111be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610466565b61068433610ee4565b60008181526002830160205260408120548190806111f6576111e9858561132d565b92506000915061100c9050565b60019250905061100c565b600081815260028301602052604081208190556105018383611339565b6060600061122b83611345565b600101905060008167ffffffffffffffff81111561124b5761124b611a71565b6040519080825280601f01601f191660200182016040528015611275576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461127f57509392505050565b6000610504825490565b60008260000182815481106112fd576112fd6118af565b9060005260206000200154905092915050565b60008281526002840160205260408120829055610c0c8484611427565b60006105018383611433565b6000610501838361144b565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061138e577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106113ba576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106113d857662386f26fc10000830492506010015b6305f5e10083106113f0576305f5e100830492506008015b612710831061140457612710830492506004015b60648310611416576064830492506002015b600a83106105045760010192915050565b6000610501838361153e565b60008181526001830160205260408120541515610501565b6000818152600183016020526040812054801561153457600061146f600183611ae5565b855490915060009061148390600190611ae5565b90508181146114e85760008660000182815481106114a3576114a36118af565b90600052602060002001549050808760000184815481106114c6576114c66118af565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806114f9576114f9611af8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610504565b6000915050610504565b600081815260018301602052604081205461158557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610504565b506000610504565b803563ffffffff811681146115a157600080fd5b919050565b6000602082840312156115b857600080fd5b6105018261158d565b73ffffffffffffffffffffffffffffffffffffffff811681146103a157600080fd5b6000602082840312156115f557600080fd5b8135611600816115c1565b9392505050565b60008083601f84011261161957600080fd5b50813567ffffffffffffffff81111561163157600080fd5b60208301915083602082850101111561100c57600080fd5b6000806020838503121561165c57600080fd5b823567ffffffffffffffff81111561167357600080fd5b61167f85828601611607565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b818110156116c3578351835292840192918401916001016116a7565b50909695505050505050565b600080604083850312156116e257600080fd5b6116eb8361158d565b915060208301356116fb816115c1565b809150509250929050565b60005b83811015611721578181015183820152602001611709565b50506000910152565b6020815260008251806020840152611749816040850160208701611706565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008083601f84011261178d57600080fd5b50813567ffffffffffffffff8111156117a557600080fd5b6020830191508360208260051b850101111561100c57600080fd5b6000806000806000606086880312156117d857600080fd5b85356117e3816115c1565b9450602086013567ffffffffffffffff8082111561180057600080fd5b61180c89838a0161177b565b9096509450604088013591508082111561182557600080fd5b506118328882890161177b565b969995985093965092949392505050565b6000806000806040858703121561185957600080fd5b843567ffffffffffffffff8082111561187157600080fd5b61187d88838901611607565b9096509450602087013591508082111561189657600080fd5b506118a387828801611607565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361193e5761193e6118de565b5060010190565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006119a2604083018688611945565b82810360208401526119b5818587611945565b979650505050505050565b6000602082840312156119d257600080fd5b8151801515811461160057600080fd5b6000602082840312156119f457600080fd5b8151611600816115c1565b60008085851115611a0f57600080fd5b83861115611a1c57600080fd5b5050820193919092039150565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015611a695780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e6f2049534d20666f756e6420666f72206f726967696e3a2000000000000000815260008251611ad8816019850160208701611706565b9190910160190192915050565b81810381811115610504576105046118de565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220b228bdbbde9b718bad3c2a3328cd105fcdd195acfeca535172d620046167ee6364736f6c63430008130033 From 9333fb8ecf2ee0aa6271d511f4700324e808cb5d Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 28 Jul 2026 08:18:36 +0000 Subject: [PATCH 4/6] docs(runtime): mark SPP change accepted --- docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md b/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md index 4c20b8742..acef9099f 100644 --- a/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md +++ b/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md @@ -1,6 +1,6 @@ # Change: Preserve gas semantics at EVM SPP boundaries -- **Status**: Implemented +- **Status**: Accepted - **Date**: 2026-07-28 - **Tier**: Light - **PR**: #579 From 5894039da69085746f7a1b5be98681ddc4447516 Mon Sep 17 00:00:00 2001 From: abmcar Date: Wed, 29 Jul 2026 08:14:37 +0000 Subject: [PATCH 5/6] test(runtime): fix SPP fixture copyright year --- src/tests/evm_spp_gas_regression_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/evm_spp_gas_regression_data.h b/src/tests/evm_spp_gas_regression_data.h index 02d588444..5ddb074ae 100644 --- a/src/tests/evm_spp_gas_regression_data.h +++ b/src/tests/evm_spp_gas_regression_data.h @@ -1,4 +1,4 @@ -// Copyright (C) 2025 the DTVM authors. All Rights Reserved. +// Copyright (C) 2026 the DTVM authors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #ifndef ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H From 66305e02bbfd0a6e7cd3fe0417092ddf5aab767d Mon Sep 17 00:00:00 2001 From: abmcar Date: Thu, 30 Jul 2026 09:14:20 +0000 Subject: [PATCH 6/6] test(runtime): remove standalone SPP replay regression --- .../README.md | 7 +- src/tests/evm_differential_tests.cpp | 118 +-------- src/tests/evm_spp_gas_regression_data.h | 225 ------------------ 3 files changed, 14 insertions(+), 336 deletions(-) delete mode 100644 src/tests/evm_spp_gas_regression_data.h diff --git a/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md b/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md index acef9099f..f24f9b28b 100644 --- a/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md +++ b/docs/changes/2026-07-28-evm-spp-gas-boundaries/README.md @@ -43,8 +43,9 @@ reduction. 32 bytes. - `src/evm/evm_cache.md` and `docs/modules/evm/cache-build.md` record the source, successor, and CFG invariants used by SPP scheduling. -- Cache-level and interpreter-versus-multipass regressions cover both failure - modes without introducing a new runtime component. +- Cache-level regressions cover both failure modes. An + interpreter-versus-multipass regression covers the unresolved dynamic + `JUMPI` case without introducing a new runtime component. - No API, ABI, configuration, or persisted-data format changes are introduced. - The guards can reduce SPP scheduling opportunities around `SSTORE` and unresolved dynamic jumps. Applying the `SSTORE` boundary before Istanbul is @@ -58,7 +59,7 @@ The production implementation at commit - tracked-source formatting and a clean Release all-target build, with no warning diagnostics from changed files; - focused cache regressions: 2/2; -- focused interpreter-versus-multipass regressions: 2/2; +- focused interpreter-versus-multipass regression: 1/1; - CTest: 12/12 targets; - interpreter unit, Cancun state, and EVM assembly suites: 215/215, 2723/2723, and 209/209; diff --git a/src/tests/evm_differential_tests.cpp b/src/tests/evm_differential_tests.cpp index 2df1bef02..4d7156b6f 100644 --- a/src/tests/evm_differential_tests.cpp +++ b/src/tests/evm_differential_tests.cpp @@ -1,6 +1,5 @@ // Copyright (C) 2025 the DTVM authors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#include #include #include #include @@ -8,12 +7,10 @@ #include #include #include -#include #include #include "compiler/evm_frontend/evm_analyzer.h" #include "evm/evm.h" -#include "evm_spp_gas_regression_data.h" #include "evm_test_host.hpp" #include "runtime/evm_module.h" #include "utils/evm.h" @@ -68,7 +65,6 @@ struct EVMExecutionResult { int64_t GasLeft = 0; std::string OutputHex; std::string LogsSignature; - std::unordered_map RecipientStorage; size_t LogCount = 0; bool JITCompiled = false; }; @@ -83,8 +79,7 @@ EVMExecutionResult runEvmBytecode( common::RunMode Mode, const std::vector &CallData = {}, uint32_t MessageFlags = 0u, bool EnableGasMetering = false, uint64_t GasLimit = 0xFFFF'FFFF'FFFF - zen::evm::BASIC_EXECUTION_COST, - evmc_revision Revision = evmc_revision::EVMC_OSAKA, - bool SeedBlock21800020Tx260State = false) { + evmc_revision Revision = evmc_revision::EVMC_OSAKA) { EVMExecutionResult Empty; RuntimeConfig Config; @@ -93,24 +88,7 @@ EVMExecutionResult runEvmBytecode( Config.EnableEvmGasMetering = EnableGasMetering; auto MockedHost = std::make_unique(); - auto Sender = zen::evm::DEFAULT_DEPLOYER_ADDRESS; - evmc::address Recipient{}; - if (SeedBlock21800020Tx260State) { - Sender = evmc::literals::operator""_address( - "99aaecd05f9b699d1f07bee4eef40d64a2a5cb3d"); - Recipient = evmc::literals::operator""_address( - "5742195a81349f1306361d71a050c4cddc5814fe"); - - evmc::bytes32 Slot33{}; - Slot33.bytes[31] = 0x33; - evmc::bytes32 SenderValue{}; - std::copy(Sender.bytes, Sender.bytes + sizeof(Sender.bytes), - SenderValue.bytes + 12); - evmc::MockedAccount ContractAccount; - ContractAccount.storage[Slot33] = evmc::StorageValue{SenderValue}; - MockedHost->accounts[Recipient] = std::move(ContractAccount); - } - MockedHost->tx_context.tx_origin = Sender; + MockedHost->tx_context.tx_origin = zen::evm::DEFAULT_DEPLOYER_ADDRESS; auto RT = Runtime::newEVMRuntime(Config, MockedHost.get()); if (!RT) { ADD_FAILURE() << "runtime create failed: " << Label; @@ -145,13 +123,13 @@ EVMExecutionResult runEvmBytecode( .flags = MessageFlags, .depth = 0, .gas = static_cast(GasLimit), - .recipient = Recipient, - .sender = Sender, + .recipient = {}, + .sender = zen::evm::DEFAULT_DEPLOYER_ADDRESS, .input_data = CallData.empty() ? nullptr : CallData.data(), .input_size = CallData.size(), .value = {}, .create2_salt = {}, - .code_address = Recipient, + .code_address = {}, .code = reinterpret_cast(Mod->Code), .code_size = Mod->CodeSize, }; @@ -168,19 +146,12 @@ EVMExecutionResult runEvmBytecode( zen::utils::toHex(RawResult.output_data, RawResult.output_size); Exec.LogCount = MockedHost->recorded_logs.size(); Exec.LogsSignature = logsSignature(MockedHost->recorded_logs); - const auto RecipientIt = MockedHost->accounts.find(Recipient); - if (RecipientIt != MockedHost->accounts.end()) { - Exec.RecipientStorage = RecipientIt->second.storage; - } return Exec; } -EVMExecutionResult runEvmBytecodeFile( - const std::string &FilePath, common::RunMode Mode, - const std::vector &CallData = {}, bool EnableGasMetering = false, - uint64_t GasLimit = 0xFFFF'FFFF'FFFF - zen::evm::BASIC_EXECUTION_COST, - evmc_revision Revision = evmc_revision::EVMC_OSAKA, - bool SeedBlock21800020Tx260State = false) { +EVMExecutionResult +runEvmBytecodeFile(const std::string &FilePath, common::RunMode Mode, + const std::vector &CallData = {}) { EVMExecutionResult Empty; std::ifstream Fin(FilePath); @@ -197,9 +168,8 @@ EVMExecutionResult runEvmBytecodeFile( ADD_FAILURE() << "Failed to convert hex to bytecode: " << FilePath; return Empty; } - return runEvmBytecode(FilePath, *BytecodeBuf, Mode, CallData, 0u, - EnableGasMetering, GasLimit, Revision, - SeedBlock21800020Tx260State); + + return runEvmBytecode(FilePath, *BytecodeBuf, Mode, CallData); } // Run `Bytecode` through interpreter and multipass, assert the interpreter @@ -697,74 +667,6 @@ TEST(EVMRangeDifferential, "0000000000000000000000000000000000000000000000005555555555555555"); } -TEST(EVMRangeDifferential, Block21800020Tx260MatchesInterpreter) { - const auto Bytecode = - zen::utils::fromHex(zen::evm::test_data::Block21800020Tx260RuntimeHex); - const auto CallData = - zen::utils::fromHex(zen::evm::test_data::Block21800020Tx260CalldataHex); - ASSERT_TRUE(Bytecode); - ASSERT_TRUE(CallData); - ASSERT_EQ(Bytecode->size(), 7'005u); - ASSERT_EQ(CallData->size(), 164u); - - const auto Interp = runEvmBytecode( - "block21800020_tx260_interp", *Bytecode, common::RunMode::InterpMode, - *CallData, 0u, true, 31'922, evmc_revision::EVMC_CANCUN, true); - const auto Multi = - runEvmBytecode("block21800020_tx260_multipass", *Bytecode, - common::RunMode::MultipassMode, *CallData, 0u, true, - 31'922, evmc_revision::EVMC_CANCUN, true); -#ifdef ZEN_ENABLE_JIT - EXPECT_TRUE(Multi.JITCompiled); -#endif - EXPECT_EQ(Interp.Status, EVMC_SUCCESS); - EXPECT_EQ(Interp.GasLeft, 1'122); - EXPECT_EQ(Interp.LogCount, 3u); - EXPECT_TRUE(Interp.OutputHex.empty()); - constexpr char ExpectedLogsSignature[] = - "3|5742195a81349f1306361d71a050c4cddc5814fe:" - "8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0," - "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," - "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," - ":|5742195a81349f1306361d71a050c4cddc5814fe:" - "8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0," - "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," - "00000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb3d," - ":|5742195a81349f1306361d71a050c4cddc5814fe:" - "7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498," - ":0000000000000000000000000000000000000000000000000000000000000001|"; - EXPECT_EQ(Interp.LogsSignature, ExpectedLogsSignature); - - auto ExpectStorageOracle = [](const EVMExecutionResult &Result) { - const evmc::bytes32 Slot0{}; - evmc::bytes32 Slot33{}; - Slot33.bytes[31] = 0x33; - - ASSERT_EQ(Result.RecipientStorage.size(), 2u); - const auto Slot0It = Result.RecipientStorage.find(Slot0); - ASSERT_NE(Slot0It, Result.RecipientStorage.end()); - EXPECT_EQ( - zen::utils::toHex(Slot0It->second.current.bytes, - sizeof(Slot0It->second.current.bytes)), - "0000000000000000000000000000000000000000000000000000000000000001"); - - const auto Slot33It = Result.RecipientStorage.find(Slot33); - ASSERT_NE(Slot33It, Result.RecipientStorage.end()); - EXPECT_EQ( - zen::utils::toHex(Slot33It->second.current.bytes, - sizeof(Slot33It->second.current.bytes)), - "00000000000000000000000099AAECD05F9B699D1F07BEE4EEF40D64A2A5CB3D"); - }; - ExpectStorageOracle(Interp); - EXPECT_EQ(Multi.Status, Interp.Status); - EXPECT_EQ(Multi.GasLeft, Interp.GasLeft); - EXPECT_EQ(Multi.OutputHex, Interp.OutputHex); - EXPECT_EQ(Multi.LogCount, Interp.LogCount); - EXPECT_EQ(Multi.LogsSignature, Interp.LogsSignature); - EXPECT_EQ(Multi.LogsSignature, ExpectedLogsSignature); - ExpectStorageOracle(Multi); -} - TEST(EVMRangeDifferential, UnresolvedJumpiTakenTargetPreservesGas) { const std::vector Bytecode = { 0x60, 0x00, 0x35, // PC0 condition = calldata[0] diff --git a/src/tests/evm_spp_gas_regression_data.h b/src/tests/evm_spp_gas_regression_data.h deleted file mode 100644 index 5ddb074ae..000000000 --- a/src/tests/evm_spp_gas_regression_data.h +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (C) 2026 the DTVM authors. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#ifndef ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H -#define ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H - -#include - -namespace zen::evm::test_data { - -// Captured from mainnet block 21800020, transaction 260. -// Decoded runtime SHA-256: -// cb4ee5cc0b651a5974d6ee0d6e389ff56cbb793ad279c27ba522335c15b0c1f5 -inline constexpr std::string_view Block21800020Tx260RuntimeHex = - "0x608060405234801561001057600080fd5b50600436106101505760003560e01c80638d" - "3638f4116100cd578063d5438eae11610081578063f2fde38b11610066578063f2fde38b" - "14610347578063f7e83aee1461035a578063fbc69aab1461037d57600080fd5b8063d543" - "8eae14610300578063de523cf31461032757600080fd5b806393c44847116100b2578063" - "93c44847146102915780639d8ecd85146102da578063c4d66de8146102ed57600080fd5b" - "80638d3638f4146102375780638da5cb5b1461027357600080fd5b8063440df4f4116101" - "245780636465e69f116101095780636465e69f146101f5578063715018a61461020f5780" - "637f5a7c7b1461021757600080fd5b8063440df4f4146101cd5780634c0a2ffc146101e2" - "57600080fd5b8062d84fd8146101555780630e72cc061461016a57806315ce45a2146101" - "7d5780633dfd3873146101ba575b600080fd5b6101686101633660046115a6565b610390" - "565b005b6101686101783660046115e3565b6103a4565b61019061018b36600461164956" - "5b6104f2565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260" - "20015b60405180910390f35b6101686101c83660046115e3565b61050a565b6101d56106" - "4b565b6040516101b1919061168b565b6101686101f03660046116cf565b61065c565b61" - "01fd600181565b60405160ff90911681526020016101b1565b610168610672565b606854" - "6101909073ffffffffffffffffffffffffffffffffffffffff1681565b61025e7f000000" - "000000000000000000000000000000000000000000000000000000000181565b60405163" - "ffffffff90911681526020016101b1565b60335473ffffffffffffffffffffffffffffff" - "ffffffffff16610190565b6102cd6040518060400160405280600681526020017f352e31" - "312e32000000000000000000000000000000000000000000000000000081525081565b60" - "40516101b1919061172a565b6101686102e83660046117c0565b610686565b6101686102" - "fb3660046115e3565b610903565b6101907f000000000000000000000000c005dc82818d" - "67af737725bd4bf75435d065d23981565b6069546101909073ffffffffffffffffffffff" - "ffffffffffffffffff1681565b6101686103553660046115e3565b610a97565b61036d61" - "0368366004611843565b610b4b565b60405190151581526020016101b1565b6101906103" - "8b3660046115a6565b610be1565b610398610caa565b6103a181610d2b565b50565b8073" - "ffffffffffffffffffffffffffffffffffffffff81163b1515806103de575073ffffffff" - "ffffffffffffffffffffffffffffffff8116155b61046f576040517f08c379a000000000" - "000000000000000000000000000000000000000000000000815260206004820152602760" - "248201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e7472616374" - "2060448201527f73657474696e6700000000000000000000000000000000000000000000" - "00000060648201526084015b60405180910390fd5b610477610caa565b606980547fffff" - "ffffffffffffffffffff00000000000000000000000000000000000000001673ffffffff" - "ffffffffffffffffffffffffffffffff84169081179091556040519081527fc47cbcc588" - "c67679e52261c45cc315e56562f8d0ccaba16facb9093ff9498799906020015b60405180" - "910390a15050565b600061050161038b8484610d80565b90505b92915050565b8073ffff" - "ffffffffffffffffffffffffffffffffffff81163b151580610544575073ffffffffffff" - "ffffffffffffffffffffffffffff8116155b6105d0576040517f08c379a0000000000000" - "000000000000000000000000000000000000000000008152602060048201526027602482" - "01527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060" - "448201527f73657474696e67000000000000000000000000000000000000000000000000" - "006064820152608401610466565b6105d8610caa565b606880547fffffffffffffffffff" - "ffffff00000000000000000000000000000000000000001673ffffffffffffffffffffff" - "ffffffffffffffffff84169081179091556040519081527f4eab7b127c76430878862236" - "3ad3e9532de3dfba7845bd4f84c125a22544255a906020016104e6565b60606106576065" - "610da3565b905090565b610664610caa565b61066e8282610e3e565b5050565b61067a61" - "0caa565b6106846000610ee4565b565b600054610100900460ff16158080156106a65750" - "600054600160ff909116105b806106c05750303b1580156106c0575060005460ff166001" - "145b61074c576040517f08c379a000000000000000000000000000000000000000000000" - "000000000000815260206004820152602e60248201527f496e697469616c697a61626c65" - "3a20636f6e747261637420697320616c72656160448201527f647920696e697469616c69" - "7a65640000000000000000000000000000000000006064820152608401610466565b6000" - "80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016" - "600117905580156107aa57600080547fffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffff00ff166101001790555b6107b2610f5b565b83821461081b5760" - "40517f08c379a00000000000000000000000000000000000000000000000000000000081" - "5260206004820152600f60248201527f6c656e677468206d69736d617463680000000000" - "0000000000000000000000006044820152606401610466565b8360005b8181101561088d" - "5761087d87878381811061083c5761083c6118af565b9050602002016020810190610851" - "91906115a6565b868684818110610863576108636118af565b9050602002016020810190" - "61087891906115e3565b610e3e565b6108868161190d565b905061081f565b5061089787" - "610ee4565b5080156108fb57600080547fffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f13" - "3852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050" - "505050565b600054610100900460ff16158080156109235750600054600160ff90911610" - "5b8061093d5750303b15801561093d575060005460ff166001145b6109c9576040517f08" - "c379a0000000000000000000000000000000000000000000000000000000008152602060" - "04820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420" - "697320616c72656160448201527f647920696e697469616c697a65640000000000000000" - "000000000000000000006064820152608401610466565b600080547fffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a2757" - "600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00" - "ff166101001790555b610a2f610f5b565b610a3882610ee4565b801561066e5760008054" - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055" - "604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38" - "47402498906020016104e6565b610a9f610caa565b73ffffffffffffffffffffffffffff" - "ffffffffffff8116610b42576040517f08c379a000000000000000000000000000000000" - "000000000000000000000000815260206004820152602660248201527f4f776e61626c65" - "3a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573" - "730000000000000000000000000000000000000000000000000000606482015260840161" - "0466565b6103a181610ee4565b6000610b5783836104f2565b73ffffffffffffffffffff" - "ffffffffffffffffffff1663f7e83aee868686866040518563ffffffff1660e01b815260" - "0401610b95949392919061198e565b6020604051808303816000875af1158015610bb457" - "3d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190" - "610bd891906119c0565b95945050505050565b60008080610bf9606563ffffffff808716" - "90610ffa16565b915091508115610c1457610c0c81611013565b949350505050565b7f00" - "0000000000000000000000c005dc82818d67af737725bd4bf75435d065d23973ffffffff" - "ffffffffffffffffffffffffffffffff16636e5f516e6040518163ffffffff1660e01b81" - "52600401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050" - "506040513d601f19601f82011682018060405250810190610c0c91906119e2565b505091" - "9050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106845760" - "40517f08c379a00000000000000000000000000000000000000000000000000000000081" - "5260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e" - "6f7420746865206f776e65726044820152606401610466565b610d3f606563ffffffff80" - "8416906110bc16565b610d48826110c8565b9061066e576040517f08c379a00000000000" - "00000000000000000000000000000000000000000000008152600401610466919061172a" - "565b6000610d906009600584866119ff565b610d9991611a29565b60e01c939250505056" - "5b60606000610db0836110ff565b90508067ffffffffffffffff811115610dcb57610dcb" - "611a71565b604051908082528060200260200182016040528015610df457816020016020" - "8202803683370190505b50915060005b81811015610ca357610e0c848261110a565b6000" - "1c838281518110610e2157610e216118af565b602090810291909101015280610e368161" - "190d565b915050610dfa565b73ffffffffffffffffffffffffffffffffffffffff81163b" - "610ebc576040517f08c379a0000000000000000000000000000000000000000000000000" - "00000000815260206004820152601660248201527f49534d206d75737420626520612063" - "6f6e7472616374000000000000000000006044820152606401610466565b61066e606563" - "ffffffff841673ffffffffffffffffffffffffffffffffffffffff8416611116565b6033" - "805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffff" - "ffffff000000000000000000000000000000000000000083168117909355604051911691" - "9082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0" - "90600090a35050565b600054610100900460ff16610ff2576040517f08c379a000000000" - "000000000000000000000000000000000000000000000000815260206004820152602b60" - "248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420" - "6960448201527f6e697469616c697a696e67000000000000000000000000000000000000" - "0000006064820152608401610466565b610684611127565b60008061100784846111c756" - "5b915091505b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff" - "8211156110b8576040517f08c379a0000000000000000000000000000000000000000000" - "000000000000008152602060048201526024808201527f5479706543617374733a206279" - "7465733332546f41646472657373206f76657260448201527f666c6f7700000000000000" - "0000000000000000000000000000000000000000006064820152608401610466565b5090" - "565b60006105018383611201565b60606110d98263ffffffff1661121e565b6040516020" - "016110e99190611aa0565b6040516020818303038152906040529050919050565b600061" - "0504826112dc565b600061050183836112e6565b611121838383611310565b5050505056" - "5b600054610100900460ff166111be576040517f08c379a0000000000000000000000000" - "00000000000000000000000000000000815260206004820152602b60248201527f496e69" - "7469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e" - "697469616c697a696e670000000000000000000000000000000000000000006064820152" - "608401610466565b61068433610ee4565b60008181526002830160205260408120548190" - "806111f6576111e9858561132d565b92506000915061100c9050565b6001925090506110" - "0c565b600081815260028301602052604081208190556105018383611339565b60606000" - "61122b83611345565b600101905060008167ffffffffffffffff81111561124b5761124b" - "611a71565b6040519080825280601f01601f191660200182016040528015611275576020" - "820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffff017f30313233343536373839616263646566" - "00000000000000000000000000000000600a86061a8153600a850494508461127f575093" - "92505050565b6000610504825490565b60008260000182815481106112fd576112fd6118" - "af565b9060005260206000200154905092915050565b6000828152600284016020526040" - "8120829055610c0c8484611427565b60006105018383611433565b600061050183836114" - "4b565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310" - "61138e577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083049250" - "6040015b6d04ee2d6d415b85acef810000000083106113ba576d04ee2d6d415b85acef81" - "00000000830492506020015b662386f26fc1000083106113d857662386f26fc100008304" - "92506010015b6305f5e10083106113f0576305f5e100830492506008015b612710831061" - "140457612710830492506004015b60648310611416576064830492506002015b600a8310" - "6105045760010192915050565b6000610501838361153e565b6000818152600183016020" - "5260408120541515610501565b6000818152600183016020526040812054801561153457" - "600061146f600183611ae5565b855490915060009061148390600190611ae5565b905081" - "81146114e85760008660000182815481106114a3576114a36118af565b90600052602060" - "002001549050808760000184815481106114c6576114c66118af565b6000918252602080" - "832090910192909255918252600188019052604090208390555b85548690806114f95761" - "14f9611af8565b6001900381819060005260206000200160009055905585600101600086" - "81526020019081526020016000206000905560019350505050610504565b600091505061" - "0504565b6000818152600183016020526040812054611585575081546001818101845560" - "008481526020808220909301849055845484825282860190935260409020919091556105" - "04565b506000610504565b803563ffffffff811681146115a157600080fd5b919050565b" - "6000602082840312156115b857600080fd5b6105018261158d565b73ffffffffffffffff" - "ffffffffffffffffffffffff811681146103a157600080fd5b6000602082840312156115" - "f557600080fd5b8135611600816115c1565b9392505050565b60008083601f8401126116" - "1957600080fd5b50813567ffffffffffffffff81111561163157600080fd5b6020830191" - "5083602082850101111561100c57600080fd5b6000806020838503121561165c57600080" - "fd5b823567ffffffffffffffff81111561167357600080fd5b61167f8582860161160756" - "5b90969095509350505050565b6020808252825182820181905260009190848201906040" - "850190845b818110156116c3578351835292840192918401916001016116a7565b509096" - "95505050505050565b600080604083850312156116e257600080fd5b6116eb8361158d56" - "5b915060208301356116fb816115c1565b809150509250929050565b60005b8381101561" - "1721578181015183820152602001611709565b50506000910152565b6020815260008251" - "806020840152611749816040850160208701611706565b601f017fffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056" - "5b60008083601f84011261178d57600080fd5b50813567ffffffffffffffff8111156117" - "a557600080fd5b6020830191508360208260051b850101111561100c57600080fd5b6000" - "806000806000606086880312156117d857600080fd5b85356117e3816115c1565b945060" - "2086013567ffffffffffffffff8082111561180057600080fd5b61180c89838a0161177b" - "565b9096509450604088013591508082111561182557600080fd5b506118328882890161" - "177b565b969995985093965092949392505050565b600080600080604085870312156118" - "5957600080fd5b843567ffffffffffffffff8082111561187157600080fd5b61187d8883" - "8901611607565b9096509450602087013591508082111561189657600080fd5b506118a3" - "87828801611607565b95989497509550505050565b7f4e487b7100000000000000000000" - "000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b" - "710000000000000000000000000000000000000000000000000000000060005260116004" - "5260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffff" - "ffffffffffff820361193e5761193e6118de565b5060010190565b818352818160208501" - "3750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006119" - "a2604083018688611945565b82810360208401526119b5818587611945565b9796505050" - "50505050565b6000602082840312156119d257600080fd5b815180151581146116005760" - "0080fd5b6000602082840312156119f457600080fd5b8151611600816115c1565b600080" - "85851115611a0f57600080fd5b83861115611a1c57600080fd5b50508201939190920391" - "50565b7fffffffff00000000000000000000000000000000000000000000000000000000" - "8135818116916004851015611a695780818660040360031b1b83161692505b5050929150" - "50565b7f4e487b7100000000000000000000000000000000000000000000000000000000" - "600052604160045260246000fd5b7f4e6f2049534d20666f756e6420666f72206f726967" - "696e3a2000000000000000815260008251611ad8816019850160208701611706565b9190" - "910160190192915050565b81810381811115610504576105046118de565b7f4e487b7100" - "000000000000000000000000000000000000000000000000000000600052603160045260" - "246000fdfea2646970667358221220b228bdbbde9b718bad3c2a3328cd105fcdd195acfe" - "ca535172d620046167ee6364736f6c63430008130033"; - -// Decoded calldata SHA-256: -// 6f191b9d7f68717789f8a76435fc7a91c255e7b8a9c39e1f5fbe91ded93b220b -inline constexpr std::string_view Block21800020Tx260CalldataHex = - "0x9d8ecd8500000000000000000000000099aaecd05f9b699d1f07bee4eef40d64a2a5cb" - "3d0000000000000000000000000000000000000000000000000000000000000060000000" - "000000000000000000000000000000000000000000000000000000008000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000"; - -static_assert(Block21800020Tx260RuntimeHex.size() == 14'012); -static_assert(Block21800020Tx260CalldataHex.size() == 330); - -} // namespace zen::evm::test_data - -#endif // ZEN_TESTS_EVM_SPP_GAS_REGRESSION_DATA_H