Skip to content

Commit

Permalink
Remove redundant writes when a state object is reverted (#21)
Browse files Browse the repository at this point in the history
* Remove redundant writes when a state object is reverted

* Change IsDirty to Transaction level

We don't want a reverted transaction to show up in written trace because it was touched by a previous transaction.

* Add storage read whenever there is a sstore

This fixes an issue when a storage slot is
* written but got reverted
* never read by sLoad opcode

When this happens, we still need to include the storage slot in the trace.
  • Loading branch information
cffls authored Nov 7, 2024
1 parent 20d868e commit 2070797
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 1 deletion.
5 changes: 5 additions & 0 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ func (sdb *IntraBlockState) SeenAccount(addr libcommon.Address) bool {
return ok
}

func (sdb *IntraBlockState) IsDirtyJournal(addr libcommon.Address) bool {
_, ok := sdb.journal.dirties[addr]
return ok
}

func (sdb *IntraBlockState) HasLiveState(addr libcommon.Address, key *libcommon.Hash) bool {
if stateObject := sdb.stateObjects[addr]; stateObject != nil {
if _, ok := stateObject.originStorage[*key]; ok {
Expand Down
1 change: 1 addition & 0 deletions core/vm/evmtypes/evmtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type IntraBlockState interface {
SetState(common.Address, *common.Hash, uint256.Int)
HasLiveAccount(addr common.Address) bool
SeenAccount(addr common.Address) bool
IsDirtyJournal(addr common.Address) bool
HasLiveState(addr common.Address, key *common.Hash) bool

GetTransientState(addr common.Address, key common.Hash) uint256.Int
Expand Down
3 changes: 2 additions & 1 deletion eth/tracers/native/zero.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (t *zeroTracer) CaptureTxEnd(restGas uint64) {
trace.StorageRead = nil
}

if len(trace.StorageWritten) == 0 || !hasLiveAccount {
if len(trace.StorageWritten) == 0 || !hasLiveAccount || !t.env.IntraBlockState().IsDirtyJournal(addr) {
trace.StorageWritten = nil
} else {
// A slot write could be reverted if the transaction is reverted. We will need to read the value from the statedb again to get the correct value.
Expand Down Expand Up @@ -379,6 +379,7 @@ func (t *zeroTracer) addSLOADToAccount(addr libcommon.Address, key libcommon.Has

func (t *zeroTracer) addSSTOREToAccount(addr libcommon.Address, key libcommon.Hash, value *uint256.Int) {
t.tx.Traces[addr].StorageWritten[key] = value
t.tx.Traces[addr].StorageReadMap[key] = struct{}{}
t.addOpCodeToAccount(addr, vm.SSTORE)
}

Expand Down

0 comments on commit 2070797

Please sign in to comment.