mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-04-12 12:48:33 +00:00
core/vm: fix two bugs
Fixes the collision bugs and create gas ordering
This commit is contained in:
parent
407cf11930
commit
cd2095fb4a
3 changed files with 37 additions and 45 deletions
|
|
@ -539,9 +539,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
|
|||
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
// Burn all gas on collision
|
||||
collisionUsed := GasUsed{RegularGas: gas.RegularGas}
|
||||
gas.RegularGas = 0
|
||||
return nil, common.Address{}, gas, collisionUsed, ErrContractAddressCollision
|
||||
return nil, common.Address{}, GasBudget{}, GasUsed{}, ErrContractAddressCollision
|
||||
}
|
||||
// Create a new account on the state only if the object was not present.
|
||||
// It might be possible the contract code is deployed to a pre-existent
|
||||
|
|
|
|||
|
|
@ -291,10 +291,19 @@ var (
|
|||
gasMLoad = pureMemoryGascost
|
||||
gasMStore8 = pureMemoryGascost
|
||||
gasMStore = pureMemoryGascost
|
||||
gasCreate = pureMemoryGascost
|
||||
)
|
||||
|
||||
func gasCreate(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
return pureMemoryGascost(evm, contract, stack, mem, memorySize)
|
||||
}
|
||||
|
||||
func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return GasCosts{}, err
|
||||
|
|
@ -313,6 +322,9 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS
|
|||
}
|
||||
|
||||
func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return GasCosts{}, err
|
||||
|
|
@ -333,6 +345,9 @@ func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
|||
}
|
||||
|
||||
func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return GasCosts{}, err
|
||||
|
|
@ -532,6 +547,9 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
|||
}
|
||||
|
||||
func gasCreateEip8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return GasCosts{}, err
|
||||
|
|
@ -540,19 +558,20 @@ func gasCreateEip8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
|||
if overflow {
|
||||
return GasCosts{}, ErrGasUintOverflow
|
||||
}
|
||||
// Cap word gas at MaxInitCodeSizeAmsterdam to avoid overflow.
|
||||
// The actual init code size check happens in create() for graceful failure.
|
||||
wordSize := min(size, params.MaxInitCodeSizeAmsterdam)
|
||||
words := (wordSize + 31) / 32
|
||||
// Account creation is a fixed state gas cost, not proportional to init code size.
|
||||
// Code storage state gas is charged separately in initNewContract.
|
||||
stateGas := params.AccountCreationSize * evm.Context.CostPerGasByte
|
||||
// CREATE uses InitCodeWordGas (EIP-3860); Keccak256WordGas is only for CREATE2.
|
||||
if err := CheckMaxInitCodeSize(&evm.chainRules, size); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
// Since size <= MaxInitCodeSizeAmsterdam, these multiplications cannot overflow
|
||||
words := (size + 31) / 32
|
||||
wordGas := params.InitCodeWordGas * words
|
||||
stateGas := params.AccountCreationSize * evm.Context.CostPerGasByte
|
||||
return GasCosts{RegularGas: gas + wordGas, StateGas: stateGas}, nil
|
||||
}
|
||||
|
||||
func gasCreate2Eip8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (GasCosts, error) {
|
||||
if evm.readOnly {
|
||||
return GasCosts{}, ErrWriteProtection
|
||||
}
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return GasCosts{}, err
|
||||
|
|
@ -561,15 +580,14 @@ func gasCreate2Eip8037(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
|
|||
if overflow {
|
||||
return GasCosts{}, ErrGasUintOverflow
|
||||
}
|
||||
// Cap word gas at MaxInitCodeSizeAmsterdam to avoid overflow.
|
||||
// The actual init code size check happens in create() for graceful failure.
|
||||
wordSize := min(size, params.MaxInitCodeSizeAmsterdam)
|
||||
words := (wordSize + 31) / 32
|
||||
// Account creation is a fixed state gas cost, not proportional to init code size.
|
||||
// Code storage state gas is charged separately in initNewContract.
|
||||
stateGas := params.AccountCreationSize * evm.Context.CostPerGasByte
|
||||
if err := CheckMaxInitCodeSize(&evm.chainRules, size); err != nil {
|
||||
return GasCosts{}, err
|
||||
}
|
||||
// Since size <= MaxInitCodeSizeAmsterdam, these multiplications cannot overflow
|
||||
words := (size + 31) / 32
|
||||
// CREATE2 charges both InitCodeWordGas (EIP-3860) and Keccak256WordGas (for address hashing).
|
||||
wordGas := (params.InitCodeWordGas + params.Keccak256WordGas) * words
|
||||
stateGas := params.AccountCreationSize * evm.Context.CostPerGasByte
|
||||
return GasCosts{RegularGas: gas + wordGas, StateGas: stateGas}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -648,28 +648,16 @@ func opSwap16(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
}
|
||||
|
||||
func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
var (
|
||||
value = scope.Stack.pop()
|
||||
offset, size = scope.Stack.pop(), scope.Stack.pop()
|
||||
input = scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
gas = scope.Contract.Gas
|
||||
)
|
||||
gas := scope.Contract.Gas
|
||||
if evm.chainRules.IsEIP150 {
|
||||
gas.RegularGas -= gas.RegularGas / 64
|
||||
}
|
||||
|
||||
// EIP-7954: check init code size after gas is charged (by the gas function)
|
||||
// but before execution. This aborts the caller's execution, ensuring all
|
||||
// regular gas is consumed while the state gas spill is tracked.
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
if err := CheckMaxInitCodeSize(&evm.chainRules, uint64(len(input))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// reuse size int for stackvalue
|
||||
stackvalue := size
|
||||
|
||||
|
|
@ -701,29 +689,17 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
}
|
||||
|
||||
func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
if evm.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
var (
|
||||
endowment = scope.Stack.pop()
|
||||
offset, size = scope.Stack.pop(), scope.Stack.pop()
|
||||
salt = scope.Stack.pop()
|
||||
input = scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
|
||||
gas = scope.Contract.Gas
|
||||
)
|
||||
|
||||
// Apply EIP150
|
||||
gas := scope.Contract.Gas
|
||||
gas.RegularGas -= gas.RegularGas / 64
|
||||
|
||||
// EIP-7954: check init code size after gas is charged (by the gas function)
|
||||
// but before execution. This aborts the caller's execution, ensuring all
|
||||
// regular gas is consumed while the state gas spill is tracked.
|
||||
if evm.chainRules.IsAmsterdam {
|
||||
if err := CheckMaxInitCodeSize(&evm.chainRules, uint64(len(input))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
regularGasUsed := scope.Contract.GasUsed.RegularGas
|
||||
scope.Contract.UseGas(GasCosts{RegularGas: gas.RegularGas}, evm.Config.Tracer, tracing.GasChangeCallContractCreation2)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue