From 8d16201f0f792e2323b869cb925f5e270bda5c59 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Wed, 24 Sep 2025 07:57:02 +0800 Subject: [PATCH] core/vm: reject contract creation if the storage is non-empty #28912 (#1569) This change implements EIP-7610, which rejects the contract deployment if the destination has non-empty storage. Co-authored-by: rjl493456442 --- core/vm/evm.go | 12 +++++++++--- core/vm/interface.go | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index ffe6d99f89..dcace041ea 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -442,13 +442,19 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if evm.chainRules.IsEIP1559 { evm.StateDB.AddAddressToAccessList(address) } - // Ensure there's no existing contract already at the designated address + // Ensure there's no existing contract already at the designated address. + // Account is regarded as existent if any of these three conditions is met: + // - the nonce is nonzero + // - the code is non-empty + // - the storage is non-empty contractHash := evm.StateDB.GetCodeHash(address) - if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) { + storageRoot := evm.StateDB.GetStorageRoot(address) + if evm.StateDB.GetNonce(address) != 0 || + (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code + (storageRoot != (common.Hash{}) && storageRoot != types.EmptyRootHash) { // non-empty storage if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } - return nil, common.Address{}, 0, ErrContractAddressCollision } // Create a new account on the state diff --git a/core/vm/interface.go b/core/vm/interface.go index a685689995..2109922399 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -48,6 +48,7 @@ type StateDB interface { GetCommittedState(common.Address, common.Hash) common.Hash GetState(common.Address, common.Hash) common.Hash SetState(common.Address, common.Hash, common.Hash) + GetStorageRoot(addr common.Address) common.Hash GetTransientState(addr common.Address, key common.Hash) common.Hash SetTransientState(addr common.Address, key, value common.Hash)