Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core/state, core/vm: implement EIP 6780 #27189

Merged
merged 4 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ type stateObject struct {
// or an account that is considered as empty will be marked as deleted at
// the end of transaction and no longer accessible anymore.
deleted bool

// Flag whether the object was created in the current transaction
created bool
}

// empty returns whether the account is considered empty.
Expand Down
15 changes: 15 additions & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,17 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
stateObject.data.Balance = new(big.Int)
}

func (s *StateDB) Selfdestruct6780(addr common.Address) {
stateObject := s.getStateObject(addr)
if stateObject == nil {
return
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also looks like getStateObject will never return nil here because the currently executing address cannot be a deleted state object.

}

if stateObject.created {
s.SelfDestruct(addr)
}
}

// SetTransientState sets transient storage for a given account. It
// adds the change to the journal so that it can be rolled back
// to its previous value if there is a revert.
Expand Down Expand Up @@ -681,6 +692,9 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
delete(s.accountsOrigin, prev.addrHash)
delete(s.storagesOrigin, prev.addrHash)
}

newobj.created = true

s.setStateObject(newobj)
if prev != nil && !prev.deleted {
return newobj, prev
Expand Down Expand Up @@ -910,6 +924,7 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
} else {
obj.finalise(true) // Prefetch slots in the background
}
obj.created = false
s.stateObjectsPending[addr] = struct{}{}
s.stateObjectsDirty[addr] = struct{}{}

Expand Down
12 changes: 12 additions & 0 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

var activators = map[int]func(*JumpTable){
5656: enable5656,
6780: enable6780,
3855: enable3855,
3860: enable3860,
3529: enable3529,
Expand Down Expand Up @@ -291,3 +292,14 @@ func enable4844(jt *JumpTable) {
maxStack: maxStack(1, 1),
}
}

// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT)
func enable6780(jt *JumpTable) {
jt[SELFDESTRUCT] = &operation{
execute: opSelfdestruct6780,
dynamicGas: gasSelfdestructEIP3529,
constantGas: params.SelfdestructGasEIP150,
minStack: minStack(1, 0),
maxStack: maxStack(1, 0),
}
}
16 changes: 16 additions & 0 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,22 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
return nil, errStopToken
}

func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly {
return nil, ErrWriteProtection
}
beneficiary := scope.Stack.pop()
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance)
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance)
interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
tracer.CaptureExit([]byte{}, 0, nil)
}
return nil, errStopToken
}

// following functions are used by the instruction jump table

// make log instruction function
Expand Down
2 changes: 2 additions & 0 deletions core/vm/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ type StateDB interface {
SelfDestruct(common.Address)
HasSelfDestructed(common.Address) bool

Selfdestruct6780(common.Address)

// Exist reports whether the given account exists in state.
// Notably this should also return true for self-destructed accounts.
Exist(common.Address) bool
Expand Down
2 changes: 2 additions & 0 deletions core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ func newCancunInstructionSet() JumpTable {
enable4844(&instructionSet) // EIP-4844 (DATAHASH opcode)
enable1153(&instructionSet) // EIP-1153 "Transient Storage"
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)
enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction
return validate(instructionSet)
}

func newShanghaiInstructionSet() JumpTable {
instructionSet := newMergeInstructionSet()
enable3855(&instructionSet) // PUSH0 instruction
enable3860(&instructionSet) // Limit and meter initcode

return validate(instructionSet)
}

Expand Down