From 37c282f1b95e90e5bb4756f3be11476122e45ef8 Mon Sep 17 00:00:00 2001 From: andri lim Date: Sat, 18 Jan 2020 07:32:39 +0700 Subject: [PATCH] fixes evmc 'gasRefund' --- nimbus/vm/evmc_host.nim | 57 +++++++++++++---------------- nimbus/vm/interpreter/gas_costs.nim | 28 +++++++++++--- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/nimbus/vm/evmc_host.nim b/nimbus/vm/evmc_host.nim index 25eece697..335150a4e 100644 --- a/nimbus/vm/evmc_host.nim +++ b/nimbus/vm/evmc_host.nim @@ -46,44 +46,39 @@ proc hostSetStorageImpl(ctx: Computation, address: var evmc_address, assert storageAddr == ctx.msg.contractAddress - if newValue == currValue: - return EVMC_STORAGE_UNCHANGED - - let - origValue = statedb.getCommittedStorage(storageAddr, slot) - InitRefundEIP2200 = gasFees[ctx.fork][GasSset] - gasFees[ctx.fork][GasSload] - CleanRefundEIP2200 = gasFees[ctx.fork][GasSreset] - gasFees[ctx.fork][GasSload] - ClearRefundEIP2200 = gasFees[ctx.fork][RefundsClear] - var - gasRefund = 0.GasInt status = EVMC_STORAGE_MODIFIED + gasRefund = 0.GasInt + origValue = 0.u256 - if origValue == currValue or ctx.fork < FkIstanbul: - if currValue == 0: - status = EVMC_STORAGE_ADDED - elif newValue == 0: - status = EVMC_STORAGE_DELETED - gasRefund += ClearRefundEIP2200 - else: - status = EVMC_STORAGE_MODIFIED_AGAIN - if origValue != 0: + block: + if newValue == currValue: + status = EVMC_STORAGE_UNCHANGED + break + + origValue = statedb.getCommittedStorage(storageAddr, slot) + + if origValue == currValue or ctx.fork < FkIstanbul: if currValue == 0: - gasRefund -= ClearRefundEIP2200 # Can go negative - if newValue == 0: - gasRefund += ClearRefundEIP2200 - if origValue == newValue: - if origValue == 0: - gasRefund += InitRefundEIP2200 - else: - gasRefund += CleanRefundEIP2200 + status = EVMC_STORAGE_ADDED + elif newValue == 0: + status = EVMC_STORAGE_DELETED + else: + status = EVMC_STORAGE_MODIFIED_AGAIN - if gasRefund > 0: + ctx.vmState.mutateStateDB: + db.setStorage(storageAddr, slot, newValue) + + let gasParam = GasParams(kind: Op.Sstore, + s_status: status, + s_currentValue: currValue, + s_originalValue: origValue + ) + gasRefund = ctx.gasCosts[Sstore].c_handler(newValue, gasParam)[1] + + if gasRefund != 0: ctx.gasMeter.refundGas(gasRefund) - ctx.vmState.mutateStateDB: - db.setStorage(storageAddr, slot, newValue) - result = status proc hostGetBalanceImpl(ctx: Computation, address: var evmc_address): evmc_uint256be {.cdecl.} = diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index 74d10377c..99e28ec65 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -71,8 +71,8 @@ type s_status*: evmc_storage_status else: s_isStorageEmpty*: bool - s_currentValue*: Uint256 - s_originalValue*: Uint256 + s_currentValue*: Uint256 + s_originalValue*: Uint256 of Call, CallCode, DelegateCall, StaticCall: c_isNewAccount*: bool c_gasBalance*: GasInt @@ -222,13 +222,31 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = sstoreLoad = FeeSchedule[GasSload] sstoreSet = FeeSchedule[GasSset] sstoreReset= FeeSchedule[GasSreset] + sstoreDirty= when fork >= FkIstanbul: sstoreLoad else: sstoreReset + InitRefundEIP2200 = FeeSchedule[GasSset] - FeeSchedule[GasSload] + CleanRefundEIP2200 = FeeSchedule[GasSreset] - FeeSchedule[GasSload] + ClearRefundEIP2200 = FeeSchedule[RefundsClear] case gasParams.s_status of EVMC_STORAGE_ADDED: result.gasCost = sstoreSet - of EVMC_STORAGE_MODIFIED, EVMC_STORAGE_DELETED: result.gasCost = sstoreReset - of EVMC_STORAGE_UNCHANGED, EVMC_STORAGE_MODIFIED_AGAIN: - result.gasCost = if fork >= FkIstanbul: sstoreLoad else: sstoreReset + of EVMC_STORAGE_MODIFIED: result.gasCost = sstoreReset + of EVMC_STORAGE_DELETED: + result.gasCost = sstoreReset + result.gasRefund += ClearRefundEIP2200 + of EVMC_STORAGE_UNCHANGED: result.gasCost = sstoreDirty + of EVMC_STORAGE_MODIFIED_AGAIN: + result.gasCost = sstoreDirty + if not gasParams.s_originalValue.isZero: + if gasParams.s_currentValue.isZero: + result.gasRefund -= ClearRefundEIP2200 + if value.isZero: + result.gasRefund += ClearRefundEIP2200 + if gasParams.s_originalValue == value: + if gasParams.s_originalValue.isZero: + result.gasRefund += InitRefundEIP2200 + else: + result.gasRefund += CleanRefundEIP2200 else: when fork < FkIstanbul: # workaround for static evaluation not working for if expression