diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 4ba7b5f130..3a457eeaec 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -27,7 +27,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/tests" @@ -177,9 +179,12 @@ func Transaction(ctx *cli.Context) error { r.Error = errors.New("gas * maxFeePerGas exceeds 256 bits") } // Check whether the init code size has been exceeded. - if chainConfig.IsShanghai(new(big.Int), 0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - r.Error = errors.New("max initcode size exceeded") + if tx.To() == nil { + if err := vm.CheckMaxInitCodeSize(&rules, uint64(len(tx.Data()))); err != nil { + r.Error = err + } } + if chainConfig.IsOsaka(new(big.Int), 0) && tx.Gas() > params.MaxTxGas { r.Error = errors.New("gas limit exceeds maximum") } diff --git a/core/state_transition.go b/core/state_transition.go index 62474b5f5b..c9ad731173 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -483,8 +483,10 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { } // Check whether the init code size has been exceeded. - if rules.IsShanghai && contractCreation && len(msg.Data) > params.MaxInitCodeSize { - return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) + if contractCreation { + if err := vm.CheckMaxInitCodeSize(&rules, uint64(len(msg.Data))); err != nil { + return nil, err + } } // Execute the preparatory steps for state transition which includes: diff --git a/core/txpool/validation.go b/core/txpool/validation.go index e0a333dfa5..13b1bfa312 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -86,8 +87,10 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return fmt.Errorf("%w: type %d rejected, pool not yet in Prague", core.ErrTxTypeNotSupported, tx.Type()) } // Check whether the init code size has been exceeded - if rules.IsShanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) + if tx.To() == nil { + if err := vm.CheckMaxInitCodeSize(&rules, uint64(len(tx.Data()))); err != nil { + return err + } } if rules.IsOsaka && tx.Gas() > params.MaxTxGas { return fmt.Errorf("%w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas()) diff --git a/core/vm/common.go b/core/vm/common.go index 2990f58972..6b8ba94257 100644 --- a/core/vm/common.go +++ b/core/vm/common.go @@ -17,12 +17,43 @@ package vm import ( + "fmt" "math" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" ) +// CheckMaxInitCodeSize checks the size of contract initcode against the protocol-defined limit. +func CheckMaxInitCodeSize(rules *params.Rules, size uint64) error { + if rules.IsAmsterdam { + if size > params.MaxInitCodeSizeAmsterdam { + return fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, size, params.MaxCodeSizeAmsterdam) + } + } else if rules.IsShanghai { + if size > params.MaxInitCodeSize { + return fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, size, params.MaxInitCodeSize) + } + } + + return nil +} + +// CheckMaxCodeSize checks the size of contract code against the protocol-defined limit. +func CheckMaxCodeSize(rules *params.Rules, size uint64) error { + if rules.IsAmsterdam { + if size > params.MaxCodeSizeAmsterdam { + return fmt.Errorf("%w: code size %v limit %v", ErrMaxCodeSizeExceeded, size, params.MaxCodeSizeAmsterdam) + } + } else if rules.IsEIP158 { + if size > params.MaxCodeSize { + return fmt.Errorf("%w: code size %v limit %v", ErrMaxCodeSizeExceeded, size, params.MaxCodeSize) + } + } + return nil +} + // calcMemSize64 calculates the required memory size, and returns // the size and whether the result overflowed uint64 func calcMemSize64(off, l *uint256.Int) (uint64, bool) { diff --git a/core/vm/evm.go b/core/vm/evm.go index 7a31ab1126..28c4ace7b0 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -594,8 +594,8 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b } // Check whether the max code size has been exceeded, assign err if the case. - if evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { - return ret, ErrMaxCodeSizeExceeded + if err := CheckMaxCodeSize(&evm.chainRules, uint64(len(ret))); err != nil { + return ret, err } // Reject code starting with 0xEF if EIP-3541 is enabled. diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 23a2cbbf4d..aa1ad918bb 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -18,7 +18,6 @@ package vm import ( "errors" - "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -318,10 +317,10 @@ func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m if overflow { return 0, ErrGasUintOverflow } - if size > params.MaxInitCodeSize { - return 0, fmt.Errorf("%w: size %d", ErrMaxInitCodeSizeExceeded, size) + if err := CheckMaxInitCodeSize(&evm.chainRules, size); err != nil { + return 0, err } - // Since size <= params.MaxInitCodeSize, these multiplication cannot overflow + // Since size <= the protocol-defined maximum initcode size limit, these multiplication cannot overflow moreGas := params.InitCodeWordGas * ((size + 31) / 32) if gas, overflow = math.SafeAdd(gas, moreGas); overflow { return 0, ErrGasUintOverflow @@ -337,10 +336,10 @@ func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, if overflow { return 0, ErrGasUintOverflow } - if size > params.MaxInitCodeSize { - return 0, fmt.Errorf("%w: size %d", ErrMaxInitCodeSizeExceeded, size) + if err := CheckMaxInitCodeSize(&evm.chainRules, size); err != nil { + return 0, err } - // Since size <= params.MaxInitCodeSize, these multiplication cannot overflow + // Since size <= the protocol-defined maximum initcode size limit, these multiplication cannot overflow moreGas := (params.InitCodeWordGas + params.Keccak256WordGas) * ((size + 31) / 32) if gas, overflow = math.SafeAdd(gas, moreGas); overflow { return 0, ErrGasUintOverflow diff --git a/params/protocol_params.go b/params/protocol_params.go index bb506af015..cebf5008c8 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -134,8 +134,10 @@ const ( DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks. - MaxCodeSize = 24576 // Maximum bytecode to permit for a contract - MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions + MaxCodeSize = 24576 // Maximum bytecode to permit for a contract + MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions + MaxCodeSizeAmsterdam = 32768 // Maximum bytecode to permit for a contract post Amsterdam + MaxInitCodeSizeAmsterdam = 2 * MaxCodeSizeAmsterdam // Maximum initcode to permit in a creation transaction and create instructions post Amsterdam // Precompiled contract gas prices