Skip to content

Commit c170cc0

Browse files
authored
core/vm: reject contract creation if the storage is non-empty (#28912)
This change implements EIP-7610, which rejects the contract deployment if the destination has non-empty storage.
1 parent 3c75c64 commit c170cc0

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

core/vm/evm.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,13 +439,19 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
439439
if evm.chainRules.IsBerlin {
440440
evm.StateDB.AddAddressToAccessList(address)
441441
}
442-
// Ensure there's no existing contract already at the designated address
442+
// Ensure there's no existing contract already at the designated address.
443+
// Account is regarded as existent if any of these three conditions is met:
444+
// - the nonce is nonzero
445+
// - the code is non-empty
446+
// - the storage is non-empty
443447
contractHash := evm.StateDB.GetCodeHash(address)
444-
if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) {
448+
storageRoot := evm.StateDB.GetStorageRoot(address)
449+
if evm.StateDB.GetNonce(address) != 0 ||
450+
(contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code
451+
(storageRoot != (common.Hash{}) && storageRoot != types.EmptyRootHash) { // non-empty storage
445452
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
446453
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
447454
}
448-
449455
return nil, common.Address{}, 0, ErrContractAddressCollision
450456
}
451457
// Create a new account on the state

core/vm/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type StateDB interface {
4949
GetCommittedState(common.Address, common.Hash) common.Hash
5050
GetState(common.Address, common.Hash) common.Hash
5151
SetState(common.Address, common.Hash, common.Hash)
52+
GetStorageRoot(addr common.Address) common.Hash
5253

5354
GetTransientState(addr common.Address, key common.Hash) common.Hash
5455
SetTransientState(addr common.Address, key, value common.Hash)

tests/block_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ func TestExecutionSpecBlocktests(t *testing.T) {
6464
}
6565
bt := new(testMatcher)
6666

67+
// These tests fail as of https://github.com/ethereum/go-ethereum/pull/28666, since we
68+
// no longer delete "leftover storage" when deploying a contract.
69+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/self_destructing_initcode_create_tx.json`)
70+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/self_destructing_initcode.json`)
71+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/recreate_self_destructed_contract_different_txs.json`)
72+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/delegatecall_from_new_contract_to_pre_existing_contract.json`)
73+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/create_selfdestruct_same_tx.json`)
74+
6775
bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
6876
execBlockTest(t, bt, test)
6977
})

tests/state_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,22 @@ func initMatcher(st *testMatcher) {
5454
// Uses 1GB RAM per tested fork
5555
st.skipLoad(`^stStaticCall/static_Call1MB`)
5656

57+
// These tests fail as of https://github.com/ethereum/go-ethereum/pull/28666, since we
58+
// no longer delete "leftover storage" when deploying a contract.
59+
st.skipLoad(`^stSStoreTest/InitCollision\.json`)
60+
st.skipLoad(`^stRevertTest/RevertInCreateInInit\.json`)
61+
st.skipLoad(`^stExtCodeHash/dynamicAccountOverwriteEmpty\.json`)
62+
st.skipLoad(`^stCreate2/create2collisionStorage\.json`)
63+
st.skipLoad(`^stCreate2/RevertInCreateInInitCreate2\.json`)
64+
5765
// Broken tests:
5866
// EOF is not part of cancun
5967
st.skipLoad(`^stEOF/`)
68+
69+
// The tests under Pyspecs are the ones that are published as execution-spec tests.
70+
// We run these tests separately, no need to _also_ run them as part of the
71+
// reference tests.
72+
st.skipLoad(`^Pyspecs/`)
6073
}
6174

6275
func TestState(t *testing.T) {

0 commit comments

Comments
 (0)