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  }