core/vm: implement stack.Address

This commit is contained in:
MariusVanDerWijden 2025-05-06 18:45:30 +02:00
parent dd232413c5
commit 83c0624999
4 changed files with 43 additions and 49 deletions

View file

@ -381,9 +381,9 @@ func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
gas uint64
value, addr = stack.Back(2), stack.Back(1)
value = stack.Back(2)
transfersValue = !value.IsZero()
address = common.Address(addr.Bytes20())
address = stack.Address(1)
)
if evm.chainRules.IsEIP158 {
if transfersValue && evm.StateDB.Empty(address) {
@ -428,9 +428,9 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
return 0, err
}
var (
gas uint64
overflow bool
value, addr = stack.Back(2), stack.Back(1)
gas uint64
overflow bool
value = stack.Back(2)
)
if value.Sign() != 0 && !evm.chainRules.IsEIP4762 {
gas += params.CallValueTransferGas
@ -439,7 +439,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
return 0, ErrGasUintOverflow
}
if evm.chainRules.IsEIP4762 && !contract.IsSystemCall {
address := common.Address(addr.Bytes20())
address := stack.Address(1)
transfersValue := !value.IsZero()
if transfersValue {
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
@ -495,8 +495,7 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
// EIP150 homestead gas reprice fork:
if evm.chainRules.IsEIP150 {
gas = params.SelfdestructGasEIP150
addr := stack.Back(0)
var address = common.Address(addr.Bytes20())
var address = stack.Address(0)
if evm.chainRules.IsEIP158 {
// if empty and transfers value

View file

@ -120,11 +120,10 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
if err != nil {
return 0, err
}
addr := stack.Back(0)
address := common.Address(addr.Bytes20())
addr := stack.Address(0)
// Check slot presence in the access list
if !evm.StateDB.AddressInAccessList(address) {
evm.StateDB.AddAddressToAccessList(address)
if !evm.StateDB.AddressInAccessList(addr) {
evm.StateDB.AddAddressToAccessList(addr)
var overflow bool
// We charge (cold-warm), since 'warm' is already charged as constantGas
if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow {
@ -143,12 +142,11 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
// - extcodesize,
// - (ext) balance
func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := stack.Back(0)
address := common.Address(addr.Bytes20())
addr := stack.Address(0)
// Check slot presence in the access list
if !evm.StateDB.AddressInAccessList(address) {
if !evm.StateDB.AddressInAccessList(addr) {
// If the caller cannot afford the cost, this change will be rolled back
evm.StateDB.AddAddressToAccessList(address)
evm.StateDB.AddAddressToAccessList(addr)
// The warm storage read cost is already charged as constantGas
return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil
}
@ -157,15 +155,14 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) gasFunc {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := stack.Back(addressPosition)
address := common.Address(addr.Bytes20())
addr := stack.Address(addressPosition)
// Check slot presence in the access list
warmAccess := evm.StateDB.AddressInAccessList(address)
warmAccess := evm.StateDB.AddressInAccessList(addr)
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
// the cost to charge for cold access, if any, is Cold - Warm
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
if !warmAccess {
evm.StateDB.AddAddressToAccessList(address)
evm.StateDB.AddAddressToAccessList(addr)
// Charge the remaining difference here already, to correctly calculate available
// gas for call
if !contract.UseGas(coldCost, evm.Config.Tracer, tracing.GasChangeCallStorageColdAccess) {
@ -227,17 +224,16 @@ var (
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
gas uint64
addr = stack.Back(0)
address = common.Address(addr.Bytes20())
gas uint64
addr = stack.Address(0)
)
if !evm.StateDB.AddressInAccessList(address) {
if !evm.StateDB.AddressInAccessList(addr) {
// If the caller cannot afford the cost, this change will be rolled back
evm.StateDB.AddAddressToAccessList(address)
evm.StateDB.AddAddressToAccessList(addr)
gas = params.ColdAccountAccessCostEIP2929
}
// if empty and transfers value
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
if evm.StateDB.Empty(addr) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
gas += params.CreateBySelfdestructGas
}
if refundsEnabled && !evm.StateDB.HasSelfDestructed(contract.Address()) {
@ -258,14 +254,13 @@ var (
func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
total uint64 // total dynamic gas used
addr = stack.Back(1)
address = common.Address(addr.Bytes20())
total uint64 // total dynamic gas used
addr = stack.Address(1)
)
// Check slot presence in the access list
if !evm.StateDB.AddressInAccessList(address) {
evm.StateDB.AddAddressToAccessList(address)
if !evm.StateDB.AddressInAccessList(addr) {
evm.StateDB.AddAddressToAccessList(addr)
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
// the cost to charge for cold access, if any, is Cold - Warm
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
@ -278,7 +273,7 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
}
// Check if code is a delegation and if so, charge for resolution.
if target, ok := types.ParseDelegation(evm.StateDB.GetCode(address)); ok {
if target, ok := types.ParseDelegation(evm.StateDB.GetCode(addr)); ok {
var cost uint64
if evm.StateDB.AddressInAccessList(target) {
cost = params.WarmStorageReadCostEIP2929

View file

@ -19,7 +19,6 @@ package vm
import (
gomath "math"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/params"
)
@ -46,9 +45,8 @@ func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
if contract.IsSystemCall {
return 0, nil
}
addr := stack.Back(0)
address := addr.Bytes20()
gas := evm.AccessEvents.BasicDataGas(address, false)
addr := stack.Address(0)
gas := evm.AccessEvents.BasicDataGas(addr, false)
if gas == 0 {
gas = params.WarmStorageReadCostEIP2929
}
@ -56,15 +54,14 @@ func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
}
func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := stack.Back(0)
address := addr.Bytes20()
if _, isPrecompile := evm.precompile(address); isPrecompile {
addr := stack.Address(0)
if _, isPrecompile := evm.precompile(addr); isPrecompile {
return 0, nil
}
if contract.IsSystemCall {
return 0, nil
}
gas := evm.AccessEvents.BasicDataGas(address, false)
gas := evm.AccessEvents.BasicDataGas(addr, false)
if gas == 0 {
gas = params.WarmStorageReadCostEIP2929
}
@ -75,12 +72,11 @@ func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
if contract.IsSystemCall {
return 0, nil
}
addr := stack.Back(0)
address := addr.Bytes20()
if _, isPrecompile := evm.precompile(address); isPrecompile {
addr := stack.Address(0)
if _, isPrecompile := evm.precompile(addr); isPrecompile {
return 0, nil
}
gas := evm.AccessEvents.CodeHashGas(address, false)
gas := evm.AccessEvents.CodeHashGas(addr, false)
if gas == 0 {
gas = params.WarmStorageReadCostEIP2929
}
@ -115,8 +111,7 @@ var (
)
func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := stack.Back(0)
beneficiaryAddr := common.Address(addr.Bytes20())
beneficiaryAddr := stack.Address(0)
if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
return 0, nil
}
@ -167,9 +162,8 @@ func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memo
if contract.IsSystemCall {
return gas, nil
}
addr := stack.Back(0)
address := common.Address(addr.Bytes20())
wgas := evm.AccessEvents.BasicDataGas(address, false)
addr := stack.Address(0)
wgas := evm.AccessEvents.BasicDataGas(addr, false)
if wgas == 0 {
wgas = params.WarmStorageReadCostEIP2929
}

View file

@ -19,6 +19,7 @@ package vm
import (
"slices"
"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)
@ -185,3 +186,8 @@ func (s *Stack) dup(n int) {
func (s *Stack) Back(n int) uint256.Int {
return s.inner.data[s.bottom+s.size-n-1]
}
// Address returns the n'th item in stack turned into an address
func (s *Stack) Address(n int) common.Address {
return common.Address(s.inner.data[s.bottom+s.size-n-1].Bytes20())
}