From f4557b5ec7fb6a26ceb75d7bcb22a3f41ce738f3 Mon Sep 17 00:00:00 2001 From: Outcry <843648230@qq.com> Date: Thu, 22 Jan 2026 04:44:02 +0000 Subject: [PATCH] fix(evm): incorrect results due to CALL execution order issue --- src/compiler/evm_frontend/evm_imported.cpp | 48 ++++++++++--------- src/runtime/evm_instance.cpp | 2 +- .../EVMOneMultipassUnitTestsRunList.txt | 2 + 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/compiler/evm_frontend/evm_imported.cpp b/src/compiler/evm_frontend/evm_imported.cpp index d85ce2d40..cbeb7e557 100644 --- a/src/compiler/evm_frontend/evm_imported.cpp +++ b/src/compiler/evm_frontend/evm_imported.cpp @@ -878,6 +878,28 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, return 0; } + // Calculate required memory sizes for input and output + // Only expand memory if we actually need to access it + bool needArgsMemory = ArgsSize > 0; + bool needRetMemory = RetSize > 0; + if (needArgsMemory && needRetMemory) { + if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize, RetOffset, + RetSize)) { + Instance->setReturnData({}); + return 0; + } + } else if (needArgsMemory) { + if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize)) { + Instance->setReturnData({}); + return 0; + } + } else if (needRetMemory) { + if (!Instance->expandMemoryChecked(RetOffset, RetSize)) { + Instance->setReturnData({}); + return 0; + } + } + bool HasEnoughBalance = true; if (TransfersValue) { const auto CallerBalance = Module->Host->get_balance(CurrentMsg->recipient); @@ -885,6 +907,10 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, intx::be::load(CallerBalance); HasEnoughBalance = CallerValue >= intx::uint256(Value); uint64_t ValueCost = zen::evm::CALL_VALUE_COST; + if (Instance->getGas() < ValueCost) { + zen::runtime::EVMInstance::triggerInstanceExceptionOnJIT( + Instance, zen::common::ErrorCode::GasLimitExceeded); + } if (!HasEnoughBalance) { ValueCost -= zen::evm::CALL_GAS_STIPEND; } @@ -905,28 +931,6 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, return 0; } - // Calculate required memory sizes for input and output - // Only expand memory if we actually need to access it - bool needArgsMemory = ArgsSize > 0; - bool needRetMemory = RetSize > 0; - if (needArgsMemory && needRetMemory) { - if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize, RetOffset, - RetSize)) { - Instance->setReturnData({}); - return 0; - } - } else if (needArgsMemory) { - if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize)) { - Instance->setReturnData({}); - return 0; - } - } else if (needRetMemory) { - if (!Instance->expandMemoryChecked(RetOffset, RetSize)) { - Instance->setReturnData({}); - return 0; - } - } - uint8_t *MemoryBase = Instance->getMemoryBase(); uint64_t CallGas = Gas; uint64_t GasLeft = Instance->getGas(); diff --git a/src/runtime/evm_instance.cpp b/src/runtime/evm_instance.cpp index e0500577a..01712d436 100644 --- a/src/runtime/evm_instance.cpp +++ b/src/runtime/evm_instance.cpp @@ -223,10 +223,10 @@ bool EVMInstance::expandMemoryChecked(uint64_t OffsetA, uint64_t SizeA, expandMemory(RequiredSize); return true; } + void EVMInstance::chargeGas(uint64_t GasCost) { evmc_message *Msg = getCurrentMessage(); ZEN_ASSERT(Msg && "Active message required for gas accounting"); - uint64_t GasLeft = getGas(); if (GasLeft < GasCost) { #if defined(ZEN_ENABLE_JIT) && defined(ZEN_ENABLE_CPU_EXCEPTION) diff --git a/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt b/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt index 906031d24..b39145b51 100644 --- a/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt +++ b/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt @@ -182,3 +182,5 @@ multi_vm/evm.undefined_instruction_analysis_overflow/external_vm multi_vm/evm.undefined_instruction_block_cost_negative/external_vm multi_vm/evm.call_oog_after_depth_check/external_vm multi_vm/evm.delegatecall_oog_depth_limit/external_vm +multi_vm/evm.call_failing_with_value/external_vm +multi_vm/evm.call_with_value_depth_limit/external_v \ No newline at end of file