This repository exists to correct the effects a known issue in multiple EIP-2535 Diamond proxy implementations.
The issue in question manifests when a zero-selector is added to a diamond proxy at position 8n + 1. If it is later removed, the diamondCut function treats it as an empty slot rather than a function signature and ignores it, corrupting the storage of the proxy.
Follow the Development insructions below to setup the Hardhat environment.
Use the included Hardhat tasks to correct the storage of an affected diamond proxy. It is recommended to use the high-level repair task.
yarn run hardhat repair TODOThe repair task consists of multiple component tasks which can be run individually. See the Hardhat help menu for more information.
All tasks make use of the Solidstate hardhat-txn-dot-xyz plugin, which delegates transaction signing to a web browser. This is intended to make it easier for multisig account users to update their diamond proxies.
The following is a description of each of the arguments accepted by the tasks.
| Argument | Description |
|---|---|
diamond |
Address of the diamond proxy with corrupted storage. |
proxy |
Address of the StorageRewrite contract. |
authorizedSender |
Address of the account permitted to call the rewrite function on the StorageRewrite contract. Defaults to the EIP-173 owner of the diamond proxy. |
storageLayoutSeed |
String seed used to calculate slot of storage layout struct, where slot = keccak256(seed) |
selectorMappingOffset |
Index within the storage struct where the diamond proxy's "selectorSlots" mapping is located. |
facetsMappingOffset |
Index within the storage struct where the diamond proxy's "facets" mapping is located. |
selectorCountOffset |
Index within the storage struct where the diamond proxy's total selector count is stored. |
slots |
JSON array of the data to be written to storage, generated by the storage-calculate-diff task. |
The following are storage slot seeds and offset values for known common diamond implementations. Values for other implementations must be calculated manually.
| Implementation | storageLayoutSeed |
selectorMappingOffset |
facetsMappingOffset |
selectorCountOffset |
|---|---|---|---|---|
| Solidstate | solidstate.contracts.storage.DiamondBase |
2n |
0n |
1n |
| Reference ("diamond-2") | diamond.standard.diamond.storage |
1n |
0n |
2n |
Install dependencies via Yarn:
yarn installSetup Husky to format code on commit:
yarn prepareCompile contracts via Hardhat:
yarn run hardhat compileThe Hardhat environment relies on the following environment variables. The dotenv package will attempt to read them from the .env and .env.secret files, if they are present.
| Key | Description |
|---|---|
API_KEY_ETHERSCAN |
Etherscan API key for source code verification |
NODE_URL_MAINNET |
JSON-RPC node URL for mainnet network |
PKEY_MAINNET |
private key for production use on mainnet network |
REPORT_GAS |
if true, a gas report will be generated after running tests |
By default, Hardhat uses the Hardhat Network in-process. An additional network, mainnet, is available, and its behavior is determined by the configuration of environment variables.
Test contracts via Hardhat:
yarn run hardhat testActivate gas usage reporting by setting the REPORT_GAS environment variable to "true":
REPORT_GAS=true yarn run hardhat testGenerate a code coverage report using solidity-coverage:
yarn run hardhat coverageA static documentation site can be generated using hardhat-docgen:
yarn run hardhat docgen