Skip to content

Commit 3857f45

Browse files
rjl493456442ziogaschr
authored andcommitted
core/state: fix SetStorage override behavior (#30185)
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 #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.
1 parent 0255965 commit 3857f45

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

core/state/statedb.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -546,20 +546,28 @@ func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
546546
// storage. This function should only be used for debugging and the mutations
547547
// must be discarded afterwards.
548548
func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
549-
// SetStorage needs to wipe existing storage. We achieve this by pretending
550-
// that the account self-destructed earlier in this block, by flagging
551-
// it in stateObjectsDestruct. The effect of doing so is that storage lookups
552-
// will not hit disk, since it is assumed that the disk-data is belonging
549+
// SetStorage needs to wipe the existing storage. We achieve this by marking
550+
// the account as self-destructed in this block. The effect is that storage
551+
// lookups will not hit the disk, as it is assumed that the disk data belongs
553552
// to a previous incarnation of the object.
554553
//
555-
// TODO(rjl493456442) this function should only be supported by 'unwritable'
556-
// state and all mutations made should all be discarded afterwards.
557-
if _, ok := s.stateObjectsDestruct[addr]; !ok {
558-
s.stateObjectsDestruct[addr] = nil
554+
// TODO (rjl493456442): This function should only be supported by 'unwritable'
555+
// state, and all mutations made should be discarded afterward.
556+
obj := s.getStateObject(addr)
557+
if obj != nil {
558+
if _, ok := s.stateObjectsDestruct[addr]; !ok {
559+
s.stateObjectsDestruct[addr] = obj.origin
560+
}
559561
}
560-
stateObject := s.getOrNewStateObject(addr)
562+
newObj := s.createObject(addr)
561563
for k, v := range storage {
562-
stateObject.SetState(k, v)
564+
newObj.SetState(k, v)
565+
}
566+
// Inherit the metadata of original object if it was existent
567+
if obj != nil {
568+
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
569+
newObj.SetNonce(obj.Nonce())
570+
newObj.SetBalance(obj.Balance())
563571
}
564572
}
565573

internal/ethapi/api_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -827,15 +827,24 @@ func TestEstimateGas(t *testing.T) {
827827

828828
func TestCall(t *testing.T) {
829829
t.Parallel()
830+
830831
// Initialize test accounts
831832
var (
832833
accounts = newAccounts(3)
834+
dad = common.HexToAddress("0x0000000000000000000000000000000000000dad")
833835
genesis = &core.Genesis{
834836
Config: params.MergedTestChainConfig,
835837
Alloc: types.GenesisAlloc{
836838
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
837839
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
838840
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
841+
dad: {
842+
Balance: big.NewInt(params.Ether),
843+
Nonce: 1,
844+
Storage: map[common.Hash]common.Hash{
845+
common.Hash{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
846+
},
847+
},
839848
},
840849
}
841850
genBlocks = 10
@@ -995,6 +1004,32 @@ func TestCall(t *testing.T) {
9951004
},
9961005
want: "0x0122000000000000000000000000000000000000000000000000000000000000",
9971006
},
1007+
// Clear the entire storage set
1008+
{
1009+
blockNumber: rpc.LatestBlockNumber,
1010+
call: TransactionArgs{
1011+
From: &accounts[1].addr,
1012+
// Yul:
1013+
// object "Test" {
1014+
// code {
1015+
// let dad := 0x0000000000000000000000000000000000000dad
1016+
// if eq(balance(dad), 0) {
1017+
// revert(0, 0)
1018+
// }
1019+
// let slot := sload(0)
1020+
// mstore(0, slot)
1021+
// return(0, 32)
1022+
// }
1023+
// }
1024+
Input: hex2Bytes("610dad6000813103600f57600080fd5b6000548060005260206000f3"),
1025+
},
1026+
overrides: StateOverride{
1027+
dad: OverrideAccount{
1028+
State: &map[common.Hash]common.Hash{},
1029+
},
1030+
},
1031+
want: "0x0000000000000000000000000000000000000000000000000000000000000000",
1032+
},
9981033
}
9991034
for i, tc := range testSuite {
10001035
result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)

0 commit comments

Comments
 (0)