core/state: fix SetStorage override behavior #30185 (#1764)

This commit is contained in:
Daniel Liu 2025-11-15 19:20:26 +08:00 committed by GitHub
parent 71e8e27f84
commit c66f8f9fb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -434,17 +434,31 @@ func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
}
// SetStorage replaces the entire storage for the specified account with given
// storage. This function should only be used for debugging.
// storage. This function should only be used for debugging and the mutations
// must be discarded afterwards.
func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
// SetStorage needs to wipe existing storage. We achieve this by pretending
// that the account self-destructed earlier in this block, by flagging
// it in stateObjectsDestruct. The effect of doing so is that storage lookups
// will not hit disk, since it is assumed that the disk-data is belonging
// SetStorage needs to wipe the existing storage. We achieve this by marking
// the account as self-destructed in this block. The effect is that storage
// lookups will not hit the disk, as it is assumed that the disk data belongs
// to a previous incarnation of the object.
s.stateObjectsDestruct[addr] = struct{}{}
stateObject := s.GetOrNewStateObject(addr)
//
// TODO(rjl493456442): This function should only be supported by 'unwritable'
// state, and all mutations made should be discarded afterward.
obj := s.getStateObject(addr)
if obj != nil {
if _, ok := s.stateObjectsDestruct[addr]; !ok {
s.stateObjectsDestruct[addr] = struct{}{}
}
}
newObj, _ := s.createObject(addr)
for k, v := range storage {
stateObject.SetState(s.db, k, v)
newObj.SetState(s.db, k, v)
}
// Inherit the metadata of original object if it was existent
if obj != nil {
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
newObj.SetNonce(obj.Nonce())
newObj.SetBalance(obj.Balance(), tracing.BalanceChangeUnspecified)
}
}