Skip to content

Commit ef12453

Browse files
committed
core/vm: reject contract creation if the storage is non-empty
1 parent 7aafad2 commit ef12453

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ func TestBlockchain(t *testing.T) {
4949
// using 4.6 TGas
5050
bt.skipLoad(`.*randomStatetest94.json.*`)
5151

52+
// The tests under Pyspecs are the ones that are published as execution-spect tests.
53+
// We run these tests separately, no need to _also_ run them as part of the
54+
// reference tests.
55+
bt.skipLoad(`^Pyspecs/`)
56+
5257
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
5358
execBlockTest(t, bt, test)
5459
})
@@ -64,6 +69,14 @@ func TestExecutionSpecBlocktests(t *testing.T) {
6469
}
6570
bt := new(testMatcher)
6671

72+
// These tests fail as of https://github.com/ethereum/go-ethereum/pull/28666, since we
73+
// no longer delete "leftover storage" when deploying a contract.
74+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/self_destructing_initcode_create_tx.json`)
75+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/self_destructing_initcode.json`)
76+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/recreate_self_destructed_contract_different_txs.json`)
77+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/delegatecall_from_new_contract_to_pre_existing_contract.json`)
78+
bt.skipLoad(`^cancun/eip6780_selfdestruct/selfdestruct/create_selfdestruct_same_tx.json`)
79+
6780
bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
6881
execBlockTest(t, bt, test)
6982
})

tests/state_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ 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+
st.skipLoad(`^stRevertTest/RevertInCreateInInit\.json`)
65+
st.skipLoad(`^stExtCodeHash/dynamicAccountOverwriteEmpty\.json`)
66+
st.skipLoad(`^stCreate2/create2collisionStorage\.json`)
67+
st.skipLoad(`^stCreate2/RevertInCreateInInitCreate2\.json`)
68+
5769
// Broken tests:
5870
// EOF is not part of cancun
5971
st.skipLoad(`^stEOF/`)

0 commit comments

Comments
 (0)