Skip to content

Commit b49047f

Browse files
cfflsrjl493456442
andauthored
core/state: fix SetStorage override behavior (ethereum#30185) (ethereum#1393)
This pull request fixes the broken feature where the entire storage set is overridden. Originally, the storage set override was achieved by marking the associated account as deleted, preventing access to the storage slot on disk. However, since ethereum#29520, this flag is also checked when accessing the account, rendering the account unreachable. A fix has been applied in this pull request, which re-creates a new state object with all account metadata inherited. Co-authored-by: rjl493456442 <[email protected]>
1 parent d689876 commit b49047f

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

core/state/statedb.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -854,22 +854,28 @@ func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
854854
// storage. This function should only be used for debugging and the mutations
855855
// must be discarded afterwards.
856856
func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
857-
// SetStorage needs to wipe existing storage. We achieve this by pretending
858-
// that the account self-destructed earlier in this block, by flagging
859-
// it in stateObjectsDestruct. The effect of doing so is that storage lookups
860-
// will not hit disk, since it is assumed that the disk-data is belonging
857+
// SetStorage needs to wipe the existing storage. We achieve this by marking
858+
// the account as self-destructed in this block. The effect is that storage
859+
// lookups will not hit the disk, as it is assumed that the disk data belongs
861860
// to a previous incarnation of the object.
862861
//
863-
// TODO(rjl493456442) this function should only be supported by 'unwritable'
864-
// state and all mutations made should all be discarded afterwards.
865-
if _, ok := s.stateObjectsDestruct[addr]; !ok {
866-
s.stateObjectsDestruct[addr] = nil
862+
// TODO (rjl493456442): This function should only be supported by 'unwritable'
863+
// state, and all mutations made should be discarded afterward.
864+
obj := s.getStateObject(addr)
865+
if obj != nil {
866+
if _, ok := s.stateObjectsDestruct[addr]; !ok {
867+
s.stateObjectsDestruct[addr] = obj
868+
}
867869
}
868-
869-
stateObject := s.getOrNewStateObject(addr)
870-
870+
newObj := s.createObject(addr)
871871
for k, v := range storage {
872-
stateObject.SetState(k, v)
872+
newObj.SetState(k, v)
873+
}
874+
// Inherit the metadata of original object if it was existent
875+
if obj != nil {
876+
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
877+
newObj.SetNonce(obj.Nonce())
878+
newObj.SetBalance(obj.Balance(), tracing.BalanceChangeUnspecified)
873879
}
874880
}
875881

internal/ethapi/api_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,15 +855,24 @@ func TestEstimateGas(t *testing.T) {
855855

856856
func TestCall(t *testing.T) {
857857
t.Parallel()
858+
858859
// Initialize test accounts
859860
var (
860861
accounts = newAccounts(3)
862+
dad = common.HexToAddress("0x0000000000000000000000000000000000000dad")
861863
genesis = &core.Genesis{
862864
Config: params.MergedTestChainConfig,
863865
Alloc: types.GenesisAlloc{
864866
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
865867
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
866868
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
869+
dad: {
870+
Balance: big.NewInt(params.Ether),
871+
Nonce: 1,
872+
Storage: map[common.Hash]common.Hash{
873+
common.Hash{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
874+
},
875+
},
867876
},
868877
}
869878
genBlocks = 10
@@ -1024,6 +1033,32 @@ func TestCall(t *testing.T) {
10241033
// },
10251034
// want: "0x0122000000000000000000000000000000000000000000000000000000000000",
10261035
// },
1036+
// Clear the entire storage set
1037+
{
1038+
blockNumber: rpc.LatestBlockNumber,
1039+
call: TransactionArgs{
1040+
From: &accounts[1].addr,
1041+
// Yul:
1042+
// object "Test" {
1043+
// code {
1044+
// let dad := 0x0000000000000000000000000000000000000dad
1045+
// if eq(balance(dad), 0) {
1046+
// revert(0, 0)
1047+
// }
1048+
// let slot := sload(0)
1049+
// mstore(0, slot)
1050+
// return(0, 32)
1051+
// }
1052+
// }
1053+
Input: hex2Bytes("610dad6000813103600f57600080fd5b6000548060005260206000f3"),
1054+
},
1055+
overrides: StateOverride{
1056+
dad: OverrideAccount{
1057+
State: &map[common.Hash]common.Hash{},
1058+
},
1059+
},
1060+
want: "0x0000000000000000000000000000000000000000000000000000000000000000",
1061+
},
10271062
}
10281063
for i, tc := range testSuite {
10291064
result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)

0 commit comments

Comments
 (0)