Prototype external storage contract for 7702 CoinbaseSmartWallets #108
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
TL;DR: Implemented an external storage pattern for the
CoinbaseSmartWallet
to better handle lacking storage guarantees between EIP-7702 delegate transitions. The solution uses a singleton storage contract that namespaces wallet state by both the wallet's address AND its code hash (EXTCODEHASH). This ensures:The key innovation is using EXTCODEHASH validation to ensure storage can only be accessed by the specific implementation we expect, rather than relying solely on address-based access control or traditional storage namespacing.
Longer discussion from slack:
"Currently, developers are responsible for preventing storage slot collisions when upgrading EOAs to smart accounts. While Storage Namespace solutions can reduce the likelihood of such conflicts, they do not fully eliminate the risk of EOA storage being overwritten."
I keep thinking that it could be interesting to basically use a separate contract to store wallet state (for example, in the case of CBSW, we're just talking about ownership state). The only issue is that access to read/write on this separate storage contract would presumably need to be gated by something like msg.sender == address(this) , or some other EOA-based signature or auth scheme, which isn't really any more robust against meddling from foreign delegates since they also operate as address(this). Perhaps slightly more robust than namespaced storage which is more likely to be interacted with inadvertently, but still lacks true guarantees.
Another possible idea would be to gate access to the separate storage based on
msg.sender == address(this)
ANDmsg.sender.EXTCODEHASH == our_expected_eip7702proxy_address_hash
. This would at least guarantee that only OUR delegate is able to access storage at this separate storage contract. The issue with that would be that upgrading the proxy (which would lead to a differentEXTCODEHASH
) would essentially require re-establishing or migrating ownership from the original system's state to a completely blank storage slate. That said, perhaps upgrading the proxy is an unlikely enough situation (after all, natively deployed smart wallets can't upgrade their proxy) that this blank-slate migration/re-initialization of some sort would be considered acceptable.