diff --git a/src/compiler/evm_frontend/evm_imported.cpp b/src/compiler/evm_frontend/evm_imported.cpp index 2b5c6dd4f..5db92a1d9 100644 --- a/src/compiler/evm_frontend/evm_imported.cpp +++ b/src/compiler/evm_frontend/evm_imported.cpp @@ -870,9 +870,10 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, Instance->chargeGas(zen::evm::ADDITIONAL_COLD_ACCOUNT_ACCESS_COST); } - const bool TransfersValue = - (CallKind == EVMC_CALL || CallKind == EVMC_CALLCODE) && Value != 0; - if (TransfersValue && Instance->isStaticMode()) { + const bool HasValueArgs = CallKind == EVMC_CALL || CallKind == EVMC_CALLCODE; + const bool HasValue = Value != 0; + + if (HasValueArgs && HasValue && Instance->isStaticMode()) { triggerStaticModeViolation(Instance); return 0; } @@ -899,35 +900,51 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, } } - bool HasEnoughBalance = true; - if (TransfersValue) { - const auto CallerBalance = Module->Host->get_balance(CurrentMsg->recipient); - const intx::uint256 CallerValue = - intx::be::load(CallerBalance); - HasEnoughBalance = CallerValue >= intx::uint256(Value); - uint64_t ValueCost = zen::evm::CALL_VALUE_COST; - if (Instance->getGas() < ValueCost) { + if (HasValueArgs) { + uint64_t GasCost = 0; + std::optional AccountState; + 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); + if (!AccountState.value()) { + GasCost += zen::evm::ACCOUNT_CREATION_COST; + } + } + } + + if (Instance->getGas() < GasCost) { zen::runtime::EVMInstance::triggerInstanceExceptionOnJIT( Instance, zen::common::ErrorCode::GasLimitExceeded); } - if (!HasEnoughBalance) { - ValueCost -= zen::evm::CALL_GAS_STIPEND; - } - const bool ChargeAccountCreation = - CallKind == EVMC_CALL && HasEnoughBalance && - !Module->Host->account_exists(TargetAddr); - if (ChargeAccountCreation) { - ValueCost -= zen::evm::CALL_GAS_STIPEND; - } - Instance->chargeGas(ValueCost); - if (ChargeAccountCreation) { - Instance->chargeGas(zen::evm::ACCOUNT_CREATION_COST); + + bool HasEnoughBalance = true; + if (HasValue) { + 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 (TransfersValue && !HasEnoughBalance) { - Instance->setReturnData({}); - return 0; + Instance->chargeGas(GasCost); + + if (HasValue && !HasEnoughBalance) { + Instance->setReturnData({}); + return 0; + } } uint8_t *MemoryBase = Instance->getMemoryBase(); @@ -941,7 +958,7 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, } else if (CallGas > GasLeft) { Instance->chargeGas(GasLeft + 1); } - if (TransfersValue) { + if (HasValueArgs && HasValue) { CallGas += zen::evm::CALL_GAS_STIPEND; } @@ -984,16 +1001,10 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance, GasLeft = 0; } uint64_t GasUsed = CallGas > GasLeft ? CallGas - GasLeft : 0; - if (TransfersValue) { - GasUsed = GasUsed > zen::evm::CALL_GAS_STIPEND - ? GasUsed - zen::evm::CALL_GAS_STIPEND - : 0; - } if (GasUsed > 0) { - if (GasUsed > 0) { - Instance->chargeGas(GasUsed); - } + Instance->chargeGas(GasUsed); } + if (Result.gas_refund > 0) { Instance->addGasRefund(Result.gas_refund); } diff --git a/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt b/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt index 50880f02e..54d42f135 100644 --- a/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt +++ b/tests/evmone_unittests/EVMOneMultipassUnitTestsRunList.txt @@ -185,4 +185,5 @@ 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 +multi_vm/evm.call_with_value_depth_limit/external_v +multi_vm/evm.call_new_account_creation_cost/external_vm