github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/core/vm/operations_acl_optimism.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "errors" 21 22 "github.com/ethereum-optimism/optimism/l2geth/common" 23 "github.com/ethereum-optimism/optimism/l2geth/common/math" 24 "github.com/ethereum-optimism/optimism/l2geth/params" 25 ) 26 27 // These functions are modified to work without the access list logic. 28 // Access lists will be added in the future and these functions can 29 // be reverted to their upstream implementations. 30 31 // Modified dynamic gas cost to always return the cold cost 32 func gasSLoadEIP2929Optimism(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 33 return params.ColdSloadCostEIP2929, nil 34 } 35 36 func gasExtCodeCopyEIP2929Optimism(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 37 // memory expansion first (dynamic part of pre-2929 implementation) 38 gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize) 39 if err != nil { 40 return 0, err 41 } 42 var overflow bool 43 if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow { 44 return 0, errors.New("gas uint64 overflow") 45 } 46 return gas, nil 47 } 48 49 func gasEip2929AccountCheckOptimism(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 50 return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil 51 } 52 53 func makeCallVariantGasCallEIP2929Optimism(oldCalculator gasFunc) gasFunc { 54 return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 55 // The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so 56 // the cost to charge for cold access, if any, is Cold - Warm 57 coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929 58 if !contract.UseGas(coldCost) { 59 return 0, ErrOutOfGas 60 } 61 // Now call the old calculator, which takes into account 62 // - create new account 63 // - transfer value 64 // - memory expansion 65 // - 63/64ths rule 66 gas, err := oldCalculator(evm, contract, stack, mem, memorySize) 67 if err != nil { 68 return gas, err 69 } 70 // In case of a cold access, we temporarily add the cold charge back, and also 71 // add it to the returned gas. By adding it to the return, it will be charged 72 // outside of this function, as part of the dynamic gas, and that will make it 73 // also become correctly reported to tracers. 74 contract.Gas += coldCost 75 return gas + coldCost, nil 76 } 77 } 78 79 var ( 80 gasCallEIP2929Optimism = makeCallVariantGasCallEIP2929Optimism(gasCall) 81 gasDelegateCallEIP2929Optimism = makeCallVariantGasCallEIP2929Optimism(gasDelegateCall) 82 gasStaticCallEIP2929Optimism = makeCallVariantGasCallEIP2929Optimism(gasStaticCall) 83 gasCallCodeEIP2929Optimism = makeCallVariantGasCallEIP2929Optimism(gasCallCode) 84 gasSelfdestructEIP2929Optimism = makeSelfdestructGasFnOptimism(true) 85 ) 86 87 // makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-2539 88 func makeSelfdestructGasFnOptimism(refundsEnabled bool) gasFunc { 89 gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { 90 address := common.BigToAddress(stack.peek()) 91 gas := params.ColdAccountAccessCostEIP2929 92 93 // if empty and transfers value 94 if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { 95 gas += params.CreateBySelfdestructGas 96 } 97 if refundsEnabled && !evm.StateDB.HasSuicided(contract.Address()) { 98 evm.StateDB.AddRefund(params.SelfdestructRefundGas) 99 } 100 return gas, nil 101 } 102 return gasFunc 103 }