-
Notifications
You must be signed in to change notification settings - Fork 20.6k
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
Conversation
core/state/statedb.go
Outdated
func (s *StateDB) SendAll(addr common.Address) bool { | ||
stateObject := s.getStateObject(addr) | ||
if stateObject == nil { | ||
return false | ||
} | ||
|
||
stateObject.sendalled = true | ||
return true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs journalling, just like the Suicide
above does it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The operations that need to be journaled are also done when this method is called: https://github.com/ethereum/go-ethereum/pull/27189/files#diff-7da47ad076053fe0f266b3088eb9ee206c7f3f8fe5a93116a3f5e25ee5074213R837-R839 .
Can move them into this method to make it clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, IIUC, you have implicitly journalled the balance movement. But you have not journalled the stateObject.sendalled=true
. So if
a -> b create c (c.create = true, c.sendall = false)
...
a -> b -> c sendall to d. (c.sendall = true)
a b revert
c
now has create
and sendall
, and will be deleted, but it shouldn't be since it was supposedly reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes. good point.
core/vm/instructions.go
Outdated
interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance) | ||
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) | ||
interpreter.evm.StateDB.SendAll(scope.Contract.Address()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way this is implemented, if sendall
is executed many times, it will re-sendall. Just noting it, not sure if it's explicitly stated in the spec.
- A sends 100 wei to b
- A -> b.Sendall( c) // sends 100 to c
- A sends 100 wei to b
- A -> b.Sendall(c) // sends 100 to c again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good observation. This behavior seems in-line with the spec IMO.
core/state/statedb.go
Outdated
newobj.created = true | ||
newobj.sendalled = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it 100% certain that the newobj
is flushed, so that when the next transaction is processed, we no longer have any objects with created
set to true? I am not 100% certain, off the top of my head.
(also, settings sendalled
to false is not necessary, but it might be nice to do so anyway, as you have done)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accounts created in a transaction will be in journal.dirties
, so stateObject.created
will be set to false
in StateDB.Finalise
. Upon revert, a created object will be removed from StateDB.stateObjects
. So it doesn't appear that there can be
a situation where a state object created in a previous transaction can have created
set to true
.
PLEASE DO NOT DO THIS PLEASE Our project utilizes our own version of GasToken (similar to 1inch CHI Token) to save gas fees for our users. Although GasToken no longer saves gas, it still performs CREATE2 and SELFDESTRUCT operations in our contract logic. Our GasToken maintains an offset, consistently executing CREATE2 or SELFDESTRUCT at this offset. After this update, CREATE2 will fail if the current offset has not been properly SELFDESTRUCTed. Our contracts are non-upgradable. After this update, most of our contract functions will revert, and user funds in our contracts, as well as liquidity in other DeFi projects, will be locked indefinitely. We believe that making such breaking changes is highly unacceptable. We opted for non-upgradable contracts to maintain decentralization. Introducing breaking changes like this introduces significant uncertainty for developers and promotes the use of centralized, upgradable contracts in the Ethereum ecosystem. |
This is the wrong forum for discussion -- this is a pr implementing a spec-change, so this is where we discuss the implementation, not the spec change. You should raise this instead on e.g. forum of ethereum magicians, or somewhere listed in the discussions-to on EIP 6780. You should also be specific: what contract (what addresses), how much ether is at risk, and what is preventing you from draning these funds now, in advance. What is the usecase, and exactly how is it implemented? |
Random observation: EIP 6780 removes an ancient quirk. Currently, doing With 6780, that no longer happens, at least not in this implementation. |
So the wording of the EIP could be interpreted to mean that it is possible to burn Eth when calling selfdestruct to self within a contract that was created in the same transaction:
|
As you remark: burn is still possible with selfdestruct-to-self in same transaction. I don't think that needs clarification, because the eip already says basically that "selfdetruct in same transaction is not modified". However, any contracts that rely on the ability to Anyway, it's not directly related to this PR. cc @Dedaub any thoughts? |
core/state/statedb.go
Outdated
@@ -474,6 +474,18 @@ func (s *StateDB) Suicide(addr common.Address) bool { | |||
return true | |||
} | |||
|
|||
func (s *StateDB) Selfdestruct6780(addr common.Address) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the meaning of the returnvalue here? I guess you just mimicked the previous Suicide
... but seems like it's very unused (and totally undocumented)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that appears to be the case. neither Suicide
nor Selfdestruct6780
use the return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR became pretty straight-forward in the end, looks good to me. But before we merge it, I'd like some more tests covering it
func (s *StateDB) Selfdestruct6780(addr common.Address) { | ||
stateObject := s.getStateObject(addr) | ||
if stateObject == nil { | ||
return |
There was a problem hiding this comment.
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.
Needs a rebase now |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Cherry pick ethereum/go-ethereum#27189 --------- Co-authored-by: jwasinger <[email protected]>
Cherry pick ethereum/go-ethereum#27189 --------- Co-authored-by: jwasinger <[email protected]>
EIP-6780: SELFDESTRUCT only in same transaction > SELFDESTRUCT will recover all funds to the caller but not delete the account, except when called in the same transaction as creation --------- Co-authored-by: Martin Holst Swende <[email protected]>
This reverts commit 876a66c.
This reverts commit 876a66c.
EIP-6780: SELFDESTRUCT only in same transaction
I'm taking a stab at this (probably broken atm. needs to be verified with tests)