vm: simplify error handling in vm.EVM.create() #30292 (#1973)

This commit is contained in:
Daniel Liu 2026-01-27 11:24:08 +08:00 committed by GitHub
parent b1c239de97
commit 105044559b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -510,44 +510,46 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
contract := NewContract(caller, AccountRef(address), value, gas)
contract.SetCodeOptionalHash(&address, codeAndHash)
ret, err = evm.Run(contract, nil, false)
// Check whether the max code size has been exceeded, assign err if the case.
if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
err = ErrMaxCodeSizeExceeded
}
// Reject code starting with 0xEF if EIP-3541 is enabled.
if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsEIP1559 {
err = ErrInvalidCode
}
// if the contract creation ran successfully and no errors were returned
// calculate the gas required to store the code. If the code could not
// be stored due to not enough gas set an error and let it be handled
// by the error checking condition below.
if err == nil {
createDataGas := uint64(len(ret)) * params.CreateDataGas
if contract.UseGas(createDataGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) {
evm.StateDB.SetCode(address, ret)
} else {
err = ErrCodeStoreOutOfGas
}
}
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally,
// when we're in homestead this also counts for code storage gas errors.
ret, err = evm.initNewContract(contract, address)
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
contract.UseGas(contract.Gas, evm.Config.Tracer, tracing.GasChangeCallFailedExecution)
}
}
return ret, address, contract.Gas, err
}
// initNewContract runs a new contract's creation code, performs checks on the
// resulting code that is to be deployed, and consumes necessary gas.
func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]byte, error) {
ret, err := evm.Run(contract, nil, false)
if err != nil {
return ret, err
}
// 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
}
// Reject code starting with 0xEF if EIP-3541 is enabled.
if len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsEIP1559 {
return ret, ErrInvalidCode
}
// If the contract creation ran successfully and no errors were returned,
// calculate the gas required to store the code. If there is not enough
// gas to store the code, return a code store out-of-gas error immediately.
createDataGas := uint64(len(ret)) * params.CreateDataGas
if !contract.UseGas(createDataGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) {
return ret, ErrCodeStoreOutOfGas
}
evm.StateDB.SetCode(address, ret)
return ret, nil
}
// Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))