{"id":21820145,"url":"https://github.com/5afe/contract-storage","last_synced_at":"2026-04-12T16:08:44.110Z","repository":{"id":235672765,"uuid":"714317180","full_name":"5afe/contract-storage","owner":"5afe","description":"CREATE2 and SELFDESTRUCT Storage Mechanism Proof of Concept","archived":false,"fork":false,"pushed_at":"2023-11-04T14:57:12.000Z","size":10,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-26T07:23:41.222Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/5afe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-11-04T14:57:02.000Z","updated_at":"2023-11-08T01:31:36.000Z","dependencies_parsed_at":"2024-04-24T07:44:40.239Z","dependency_job_id":"98242cf0-7cdd-4048-89c5-3e910e4914af","html_url":"https://github.com/5afe/contract-storage","commit_stats":null,"previous_names":["5afe/contract-storage"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5afe%2Fcontract-storage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5afe%2Fcontract-storage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5afe%2Fcontract-storage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5afe%2Fcontract-storage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/5afe","download_url":"https://codeload.github.com/5afe/contract-storage/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244782474,"owners_count":20509821,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-27T16:28:50.940Z","updated_at":"2026-04-12T16:08:44.083Z","avatar_url":"https://github.com/5afe.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Contract Storage\n\nThis repository implements a contract-based storage mechanism. Specifically, it\nuses `CREATE2` to deploy contracts to well known addresses whose code contains\nthe actual stored values.\n\nThis makes use of two things:\n\n- `CREATE2` to deploy contracts to deterministic addresses. Additionally the\n  value being stored per contract is read using `SLOAD` in the caller, meaning\n  that the storage contract ends up at the same address regardless of the stored\n  value.\n- `SELFDESTRUCT` to remove a contract code. Critically, this allows a new\n  contract to be deployed at the same address using `CREATE2` which a\n  potentially different stored value.\n\nThis repository provides a `ContractStorage` abstract class with `cload`,\n`cstore` functions (analogous to `{m,s,t}{load,store}` op-codes) for reading and\nwriting to and from contract storage. It comes in two flavours: `Slot` and\n`DynamicSlot`.\n\n## `Slot` Storage\n\nThe basic kind of contract storage is the `Slot`. It works by deploying a\ncontract using `CREATE2` whose address is salted with the slot value. In order\nto change the value, **two** transactions are needed:\n\n1. A first transaction that `creset`s the `Slot`.\n2. A second transaction that `cstore`s the new value.\n\nUnfortunately, both steps cannot be incuded in the same EVM transaction. This is\nbecause `SELFDESTRUCT` _schedules a contract for deletion, but does not delete\nit right away_. This means that the contract will act as if it has code even\nafter `SELFDESTRUCT` is called until the end of the transaction. Namely, this\nprevents:\n\n- Calling `CREATE2` where the code would end on the same address as the\n  `SELFDESTRUCT`-ed contract\n- Reading the value from the contract will return as if it is still set\n\n## `DynamicSlot` Storage\n\nThis is a system with a \"`Slot` queue\" which allows for values to be updated\nwithin a transaction. It allows specifying an arrity, or the maximum number of\nupdates that the `DynamicSlot` can do within a given EVM transaction (because of\nthe same `SELFDESTRUCT` limitations that exist for `Slot`).\n\nThis does not work in ERC-4337 `validateUserOp` calls, as it potentially reads\nfrom contracts with empty code (the empty `Slot`s in the queue).\n\n## Stability\n\nIn general **it it not recommended to use this module**. `SELFDESTRUCT` has been\nofficially deprecated, and this code relies on it to updating values.\n\n## Potential Uses\n\nOne potential usage of this mechanism is for storing whether or not a module is\nenabled in the Safe Core Protocol registry. The use of contract storage over\nmore conventional storage (i.e. `S{LOAD,STORE`) would allow registry checks in\n`validateUserOp` without requiring a staked _paymaster_.\n\nThe being said, because of the stability concerns, I'm not sure I recommend\nusing it, especially since `SELFDESTRUCT` is officially deprecated, but it is a\nfun thought experiment and potential solution to the ERC-4337 storage\nrestrictions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5afe%2Fcontract-storage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F5afe%2Fcontract-storage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5afe%2Fcontract-storage/lists"}