This post addresses technical errors and questions. For more general and less technical questions about diamonds see this blog post: Answering Some Diamond Questions
1. A state variable in AppStorage or Diamond Storage has the wrong value
A state variable in AppStorage or Diamond Storage has the wrong value or the value 0 when it should not. This is caused by declaring state variables outside AppStorage and Diamond Storage which causes a misalignment of data. This error is commonly caused by a facet inheriting a contract that declares state variables outside AppStorage and Diamond Storage.
The solution is to remove any declarations of state variables outside AppStorage or Diamond Storage and put them in AppStorage or Diamond Storage.
Concerning upgrades checkout this blog post: Rules for Diamond Upgrades
2. Can't add function that already exists
This error is caused by trying to add a function to a diamond that already exists.
You can see what functions are in a diamond by using the ABI of the diamond with the loupe functions. The `diamondCut` function allows a function to be replaced if it already exists but does not allow a function to be added if it already exists.
This error is very easy to handle. If supportsInterface() or some other function has already been added to a diamond then don't try to add it again.
Sometimes people think that "facets" are added to a diamond. They never are. Only functions are added to a diamond. So you don't have to add all the functions of a facet to a diamond, just add the functions of a facet to a diamond that you want to add.
For example if two different facets have the supportsInterface() function, then just add the function from one of the facets, not both. It is easy to filter out functions of a facet and just add the ones you want to add. You can see examples of this in the tests for the reference implementations: https://github.com/mudgen/diamond-1-hardhat/blob/main/test/diamondTest.js#L75
3. ProviderError: VM Exception while processing transaction: revert
This error can happen when calling the diamondCut function to add many functions and not enough gas is used. This can be solved by increasing the amount of gas for the transaction. If using ethersjs then checkout the “gasLimit” override.
4. I have a function in a facet that will call functions from other facets. How can I implement in this case?
Yes, this subject is covered in this article: How to Share Functions Between Facets of a Diamond
5. When using diamond loupe functions is there a way to convert the 4-byte function selectors to function signatures (function name plus parameter types)?
Yes, absolutely, that's what your facet's ABI is for. You can compare the function selectors of a facet to its ABI to get the function signatures (function name plus parameter types) of the function selectors.
6. How Do I Upgrade Diamond Storage or AppStorage?
Add more state variables to your Diamond Storage struct in a contract or Solidity library where the struct(s) is defined.
Then write new functions or modify the code of existing functions to use those new state variables.
Then compile your facet(s). If you are using internal functions of Solidity libraries then the bytecode of those internal functions are added to the facet(s) you compiled.
Then deploy your facet(s).
Then use the `diamondCut` function to add/replace external functions in the diamond that you want to have the new functionality and access the new state variables.
More information and important rules for upgrading Diamond Storage can be found here: Rules for Diamond Upgrades
7. What about Facets that Import Solidity Libraries that Declare and Use Structs?
A facet that declares structs and internal functions amounts to the same thing as a facet that imports a Solidity library that declares structs and internal functions. The Solidity compiler essentially compiles them into the same thing. The big advantage to using Solidity libraries this way is that Solidity libraries are easily shared between facets.
To understand this more I wrote an article that explains the two very different ways Solidity libraries can be used. See here:
8. Problems or Questions about Contract Storage
Read these articles:
9. How to Update Solidity Library used by Facets?
Replace the external functions in a diamond that use the old library with new external functions that use the updated library.
10. Why Must Immutable Functions Be Emitted by the DiamondCut Event and Returned by the Loupe Functions?
Understand these terms:
Diamond: A diamond proxy contract is the contract with the fallback function that delegatecalls to facets. It is the diamond.
Immutable Function: An immutable function is an external function defined directly in a diamond proxy contract, or is inherited by a diamond proxy contract.
This question is answered specifically by this article: Compliance and Transparency of Immutable Functions in Diamonds
Common Diamond Errors & Questions
Hi what's the correct way of handling errors in facets? Does it bubble up?