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

View file

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

View file

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

View file

@ -19,6 +19,7 @@ package vm
import ( import (
"slices" "slices"
"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
@ -185,3 +186,8 @@ func (s *Stack) dup(n int) {
func (s *Stack) Back(n int) uint256.Int { func (s *Stack) Back(n int) uint256.Int {
return s.inner.data[s.bottom+s.size-n-1] 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())
}