github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/core/vm/operations_verkle.go (about)

     1  // Copyright 2024 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  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/common/math"
    22  	"github.com/ethereum/go-ethereum/params"
    23  )
    24  
    25  func gasSStore4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
    26  	gas := evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), true)
    27  	if gas == 0 {
    28  		gas = params.WarmStorageReadCostEIP2929
    29  	}
    30  	return gas, nil
    31  }
    32  
    33  func gasSLoad4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
    34  	gas := evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), false)
    35  	if gas == 0 {
    36  		gas = params.WarmStorageReadCostEIP2929
    37  	}
    38  	return gas, nil
    39  }
    40  
    41  func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
    42  	address := stack.peek().Bytes20()
    43  	gas := evm.AccessEvents.BalanceGas(address, false)
    44  	if gas == 0 {
    45  		gas = params.WarmStorageReadCostEIP2929
    46  	}
    47  	return gas, nil
    48  }
    49  
    50  func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
    51  	address := stack.peek().Bytes20()
    52  	if _, isPrecompile := evm.precompile(address); isPrecompile {
    53  		return 0, nil
    54  	}
    55  	gas := evm.AccessEvents.VersionGas(address, false)
    56  	gas += evm.AccessEvents.CodeSizeGas(address, false)
    57  	if gas == 0 {
    58  		gas = params.WarmStorageReadCostEIP2929
    59  	}
    60  	return gas, nil
    61  }
    62  
    63  func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
    64  	address := stack.peek().Bytes20()
    65  	if _, isPrecompile := evm.precompile(address); isPrecompile {
    66  		return 0, nil
    67  	}
    68  	gas := evm.AccessEvents.CodeHashGas(address, false)
    69  	if gas == 0 {
    70  		gas = params.WarmStorageReadCostEIP2929
    71  	}
    72  	return gas, nil
    73  }
    74  
    75  func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc {
    76  	return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
    77  		gas, err := oldCalculator(evm, contract, stack, mem, memorySize)
    78  		if err != nil {
    79  			return 0, err
    80  		}
    81  		if _, isPrecompile := evm.precompile(contract.Address()); isPrecompile {
    82  			return gas, nil
    83  		}
    84  		witnessGas := evm.AccessEvents.MessageCallGas(contract.Address())
    85  		if witnessGas == 0 {
    86  			witnessGas = params.WarmStorageReadCostEIP2929
    87  		}
    88  		return witnessGas + gas, nil
    89  	}
    90  }
    91  
    92  var (
    93  	gasCallEIP4762         = makeCallVariantGasEIP4762(gasCall)
    94  	gasCallCodeEIP4762     = makeCallVariantGasEIP4762(gasCallCode)
    95  	gasStaticCallEIP4762   = makeCallVariantGasEIP4762(gasStaticCall)
    96  	gasDelegateCallEIP4762 = makeCallVariantGasEIP4762(gasDelegateCall)
    97  )
    98  
    99  func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
   100  	beneficiaryAddr := common.Address(stack.peek().Bytes20())
   101  	if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
   102  		return 0, nil
   103  	}
   104  	contractAddr := contract.Address()
   105  	statelessGas := evm.AccessEvents.VersionGas(contractAddr, false)
   106  	statelessGas += evm.AccessEvents.CodeSizeGas(contractAddr, false)
   107  	statelessGas += evm.AccessEvents.BalanceGas(contractAddr, false)
   108  	if contractAddr != beneficiaryAddr {
   109  		statelessGas += evm.AccessEvents.BalanceGas(beneficiaryAddr, false)
   110  	}
   111  	// Charge write costs if it transfers value
   112  	if evm.StateDB.GetBalance(contractAddr).Sign() != 0 {
   113  		statelessGas += evm.AccessEvents.BalanceGas(contractAddr, true)
   114  		if contractAddr != beneficiaryAddr {
   115  			statelessGas += evm.AccessEvents.BalanceGas(beneficiaryAddr, true)
   116  		}
   117  	}
   118  	return statelessGas, nil
   119  }
   120  
   121  func gasCodeCopyEip4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
   122  	gas, err := gasCodeCopy(evm, contract, stack, mem, memorySize)
   123  	if err != nil {
   124  		return 0, err
   125  	}
   126  	var (
   127  		codeOffset = stack.Back(1)
   128  		length     = stack.Back(2)
   129  	)
   130  	uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
   131  	if overflow {
   132  		uint64CodeOffset = math.MaxUint64
   133  	}
   134  	_, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, length.Uint64())
   135  	if !contract.IsDeployment {
   136  		gas += evm.AccessEvents.CodeChunksRangeGas(contract.Address(), copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
   137  	}
   138  	return gas, nil
   139  }
   140  
   141  func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
   142  	// memory expansion first (dynamic part of pre-2929 implementation)
   143  	gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize)
   144  	if err != nil {
   145  		return 0, err
   146  	}
   147  	addr := common.Address(stack.peek().Bytes20())
   148  	wgas := evm.AccessEvents.VersionGas(addr, false)
   149  	wgas += evm.AccessEvents.CodeSizeGas(addr, false)
   150  	if wgas == 0 {
   151  		wgas = params.WarmStorageReadCostEIP2929
   152  	}
   153  	var overflow bool
   154  	// We charge (cold-warm), since 'warm' is already charged as constantGas
   155  	if gas, overflow = math.SafeAdd(gas, wgas); overflow {
   156  		return 0, ErrGasUintOverflow
   157  	}
   158  	return gas, nil
   159  }