diff --git a/src/compiler/evm_frontend/evm_imported.cpp b/src/compiler/evm_frontend/evm_imported.cpp index f02aa9d84..789aab719 100644 --- a/src/compiler/evm_frontend/evm_imported.cpp +++ b/src/compiler/evm_frontend/evm_imported.cpp @@ -900,10 +900,10 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, } } + uint64_t CallGas = Gas; if (HasValueArgs) { - uint64_t GasCost = 0; std::optional AccountState; - GasCost = HasValue ? zen::evm::CALL_VALUE_COST : 0; + uint64_t GasCost = HasValue ? zen::evm::CALL_VALUE_COST : 0; if (CallKind == EVMC_CALL) { if (HasValue || Instance->getRevision() < EVMC_SPURIOUS_DRAGON) { AccountState = Module->Host->account_exists(TargetAddr); @@ -913,54 +913,38 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, } } - if (Instance->getGas() < GasCost) { - zen::runtime::EVMInstance::triggerInstanceExceptionOnJIT( - Instance, zen::common::ErrorCode::GasLimitExceeded); - } + Instance->chargeGas(GasCost); + } + uint64_t GasLeft = Instance->getGas(); + if (Rev >= EVMC_TANGERINE_WHISTLE) { + const uint64_t GasCap = GasLeft - GasLeft / 64; + CallGas = std::min(CallGas, GasCap); + } else if (CallGas > GasLeft) { + zen::runtime::EVMInstance::triggerInstanceExceptionOnJIT( + Instance, zen::common::ErrorCode::GasLimitExceeded); + } + + if (HasValueArgs) { bool HasEnoughBalance = true; if (HasValue) { + Instance->addGas(zen::evm::CALL_GAS_STIPEND); + CallGas += zen::evm::CALL_GAS_STIPEND; + const auto CallerBalance = Module->Host->get_balance(CurrentMsg->recipient); const intx::uint256 CallerValue = intx::be::load(CallerBalance); HasEnoughBalance = CallerValue >= intx::uint256(Value); - if (!HasEnoughBalance) { - GasCost -= zen::evm::CALL_GAS_STIPEND; - } - if (CallKind == EVMC_CALL && HasEnoughBalance) { - if (!AccountState.has_value()) { - AccountState = Module->Host->account_exists(TargetAddr); - } - if (!AccountState.value()) { - GasCost -= zen::evm::CALL_GAS_STIPEND; - } + if (!HasEnoughBalance) { + Instance->setReturnData({}); + return 0; } } - - Instance->chargeGas(GasCost); - - if (HasValue && !HasEnoughBalance) { - Instance->setReturnData({}); - return 0; - } } uint8_t *MemoryBase = Instance->getMemoryBase(); - uint64_t CallGas = Gas; - uint64_t GasLeft = Instance->getGas(); - if (Rev >= EVMC_TANGERINE_WHISTLE) { - const uint64_t GasCap = GasLeft - GasLeft / 64; - if (CallGas > GasCap) { - CallGas = GasCap; - } - } else if (CallGas > GasLeft) { - Instance->chargeGas(GasLeft + 1); - } - if (HasValueArgs && HasValue) { - CallGas += zen::evm::CALL_GAS_STIPEND; - } if (CurrentMsg->depth >= zen::evm::MAXSTACK) { Instance->setReturnData({}); diff --git a/src/runtime/evm_instance.cpp b/src/runtime/evm_instance.cpp index 01712d436..46ee02a7c 100644 --- a/src/runtime/evm_instance.cpp +++ b/src/runtime/evm_instance.cpp @@ -240,4 +240,20 @@ void EVMInstance::chargeGas(uint64_t GasCost) { Msg->gas = static_cast(NewGas); } +void EVMInstance::addGas(uint64_t GasAmount) { + evmc_message *Msg = getCurrentMessage(); + ZEN_ASSERT(Msg && "Active message required for gas accounting"); + uint64_t GasLeft = getGas(); + if (GasLeft > UINT64_MAX - GasAmount) { +#if defined(ZEN_ENABLE_JIT) && defined(ZEN_ENABLE_CPU_EXCEPTION) + triggerInstanceExceptionOnJIT(this, common::ErrorCode::GasLimitExceeded); +#else + throw common::getError(common::ErrorCode::GasLimitExceeded); +#endif + } + uint64_t NewGas = GasLeft + GasAmount; + setGas(NewGas); + Msg->gas = static_cast(NewGas); +} + } // namespace zen::runtime diff --git a/src/runtime/evm_instance.h b/src/runtime/evm_instance.h index 8d60cee64..2b1cdf04b 100644 --- a/src/runtime/evm_instance.h +++ b/src/runtime/evm_instance.h @@ -57,6 +57,7 @@ class EVMInstance final : public RuntimeObject { bool expandMemoryChecked(uint64_t OffsetA, uint64_t SizeA, uint64_t OffsetB, uint64_t SizeB); void chargeGas(uint64_t GasCost); + void addGas(uint64_t GasAmount); void addGasRefund(uint64_t Amount) { GasRefund += Amount; } void setGasRefund(uint64_t Amount) { GasRefund = Amount; } diff --git a/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt b/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt index 54d42f135..aa807b690 100644 --- a/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt +++ b/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt @@ -187,3 +187,6 @@ 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 multi_vm/evm.call_new_account_creation_cost/external_vm +multi_vm/evm.call_with_value/external_vm +multi_vm/evm.callcode_new_account_create/external_vm +multi_vm/evm.call_value/external_vm