Enables people to write smart contracts with virtually no size limit.
Diamonds can be upgraded without having to redeploy existing functionality. Parts of a diamond can be added/replaced/removed while leaving other parts alone.
1.**A single address for unlimited contract functionality.** Using a single address for contract functionality makes deployment, testing and integration with other smart contracts, software and user interfaces easier.
1.**Your contract exceeds the 24KB maximum contract size.** You may have related functionality that it makes sense to keep in a single contract, or at a single contract address. A diamond does not have a max contract size.
1.**A diamond provides a way to organize contract code and data.** You may want to build a contract system with a lot of functionality. A diamond provides a systematic way to isolate different functionality and connect them together and share data between them as needed in a gas-efficient way.
1.**A diamond provides a way to upgrade functionality.** Upgradeable diamonds can be upgraded to add/replace/remove functionality. Because diamonds have no max contract size, there is no limit to the amount of functionality that can be added to diamonds over time. Diamonds can be upgradeable or immutable. It is also possible to make an upgradeable diamond and then at a later time remove its upgrade capability.
Diamonds support another form of transparency which is a historical record of all upgrades on a diamond. This is done with the DiamondCut event which is used to record all functions that are added, replaced or removed on a diamond.
This standard is an improvement of [EIP-1538 Transparent Contract Standard](https://eips.ethereum.org/EIPS/eip-1538). The same motivations of that standard apply to this standard.
See the [Learning & References section](https://eips.ethereum.org/EIPS/eip-2535#learning--references) for additional information and uses of diamonds.
When an external function is called on a diamond its fallback function is executed. The fallback function finds in the `selectorToFacet` mapping which facet has the function that has been called and then executes that function from the facet using `delegatecall`.
A diamond's fallback function and `delegatecall` enable a diamond to execute a facet's external function as its own external function. The `msg.sender` and `msg.value` values do not change and only the diamond's contract storage is read and written to.
A diamond can use a `diamondCut` function to add/replace/remove any number of functions from any number of facets in a single transaction. `diamondCut` updates the mapping of function selector to facet address. Other such functions can be used.
An event is emitted any time external functions are added, replaced or removed to report what changed.
A diamond has four standard external functions that can be called to show what facets and functions it currently has.
A diamond can be immutable from inception by not adding any external functions that can add/replace/remove functions. [There are number of reasons to do this.](#different-kinds-of-diamonds)
A state variable or storage layout organizational pattern is needed because Solidity's builtin storage layout system doesn't support proxy contracts or diamonds.
A facet can declare state variables in structs. Each struct is given a specific position in contract storage. This technique is called **Diamond Storage**.
By using Diamond Storage facets can declare their own state variables that do not conflict with the storage locations of state variables declared in other facets.
The AppStorage pattern is implemented by defining a struct called AppStorage that contains the state variables of your application. It can contain any number of state variables of any type, including arrays and mappings, and more can be added in upgrades.
The AppStorage struct is defined or imported and declared as the first and only state variable directly (or via inheritance) in any facet that uses it. This means that AppStorage is always located at position 0 in contract storage.
The AppStorage state variable is often named `s` to provide easy access to it and to distinguish state variables from function arguments, function names, and local variables.
Here is a simple example of a contract that uses AppStorage:
```Solidity
import "./AppStorage.sol"
contract StakingFacet {
AppStorage internal s;
function myFacetFunction(uint256 _nextVar) external {
s.total = s.firstVar + _nextVar;
}
```
The above example accesses the `s.firstVar` state variable and stores a computation in the `s.total` state variable.
Read this article to learn more about AppStorage: [AppStorage Pattern for State Variables in Solidity](https://dev.to/mudgen/appstorage-pattern-for-state-variables-in-solidity-3lki).
Diamonds and facets don't have to use Diamond Storage or AppStorage. They can use or mix with other contract storage strategies such as contract inheritance.
A limitation is that two external functions with the same function signature can't be added to a diamond at the same time because a diamond, or any contract, cannot have two external functions with the same function signature.
1. A stable contract address that provides needed functionality.
1. A single address with the functionality of multiple contracts (facets) that are independent from each other but can share internal functions, libraries and state variables.
1. A way to add, replace and remove multiple external functions atomically (in the same transaction).
1. Fine-grained upgrades, so you can change just the parts of a diamond that need to be changed.
1. Have greater control over when and what functions exist.
1. Decentralized Autonomous Organizations (DAOs) and other governance systems can be used to upgrade diamonds.
1. The ability to show all changes made to a diamond.
1. Increase trust over time by showing all changes made to a diamond.
1. A way to look at a diamond to see its current facets and functions.
1. Have an immutable, trustless diamond.
1. Solves the 24KB maximum contract size limitation. Diamonds can be any size.
1. Separate functionality can be implemented in separate facets and used together in a diamond.
1. Larger contracts have to reduce their size by removing error messages and other things. You can keep your error messages and the full functionality that you need by implementing a diamond.
1. Enables zero, partial or full diamond immutability as desired, and when desired.
1. The ability to develop and improve an application over time with an upgradeable diamond and then make it immutable and trustless if desired.
1. Develop incrementally and let your diamond grow with your application.
1. Diamonds can be large (have many functions) but still be modular because they are compartmented with facets.
1. Contract architectures that call multiple contracts in a single transaction can save gas by condensing those contracts into a single diamond and accessing state variables directly.
1. Save gas by creating external functions for specific use cases, such as bulk transfers.
1. Diamonds are designed for tooling and user-interface software.
An upgradeable diamond has the `diamondCut` function and/or possibly other functions to add/replace/remove functions. It is useful for iterative development or improving an application over time.
A finished diamond was an upgradeable diamond and had a number of upgrades. Then its `diamondCut` function and/or other upgrade functions were removed and upgrades are no longer possible. It is no longer possible to add/replace/remove functions. It has become an immutable diamond.
A single cut diamond adds all functions to itself in its constructor function, but it does not add the `diamondCut` function or any other function that can add/replace/remove functions. This means that a single cut diamond is fully created in its constructor and once created can never be upgraded. It has the same immutability and trustless guarantees as a regular vanilla contract. Why would someone do this? There may be a number of reasons. The two use cases below are good reasons.
1. Your contract hits the max contract size limit. Make it into a single cut diamond. You still break your big contract into smaller facets, modularizing your code.
2. You start with an upgradeable diamond in your development and testing and upgrade it to your heart's delight. Reap the advantages of easy upgrading and a stable address as you work out new features, bugs and kinks. Release the upgradeable diamond on a test network with your application for beta testing and upgrade it when needed. This is iterative development. When it is solid then deploy it as a single cut diamond on the main network.
> The solidity `delegatecall` opcode enables a contract to execute a function from another contract, but it is executed as if the function was from the calling contract. Essentially `delegatecall` enables a contract to "borrow" another contract's function. Functions executed with `delegatecall` affect the contract storage of the calling contract, not the contract where the functions are defined.
2. The word **facet** comes from the diamond industry. It is a side, or flat surface of a diamond. A diamond can have many facets. In this standard a facet is a contract with one or more functions that executes functionality of a diamond.
3. A **loupe** is a magnifying glass that is used to look at diamonds. In this standard a loupe is a facet that provides functions to look at a diamond and its facets.
4. An **immutable function** is a function that is defined directly in a diamond and so cannot be replaced or removed. Or it is a function that is defined in a facet that cannot be replaced or removed because all upgrade functions have been removed from a diamond.
In the diamond industry diamonds are created and shaped by being cut, creating facets. In this standard diamonds are cut by adding, replacing or removing facets and their functions.
The standard `diamondCut` function specified below can be used to add/replace/remove any number of functions from/to a diamond in a single transaction.
The standard `diamondCut` function below is specified for the purpose of interoperability. Diamond tools, software and user-interfaces should expect and use the standard `diamondCut` function. Diamonds that might work with diamond specific tooling to add/replace/remove functions should implement the standard `diamondCut` function.
You can implement your own custom functions that add or replace or remove functions. You can also implement your own non-standard versions of `diamondCut` that have different parameters.
If you want to create your own custom function(s) for adding/replacing/removing functions you might also want to implement the standard `diamondCut` function for interoperability with tools.
The `_diamondCut` argument is an array of FacetCut structs.
Each FacetCut struct contains a facet address and array of function selectors that are updated in a diamond.
To add new functions create a FacetCut struct with `facetAddress` set to the facet that has the new functions and `functionSelectors` set with the function selectors to add. Set the `action` enum to `Add`.
To replace functions create a FacetCut struct with `facetAddress` set to the facet that has the replacement functions and `functionSelectors` set with the function selectors to replace. Set the `action` enum to `Replace`.
To remove functions create a FacetCut struct with `facetAddress` set to `address(0)` and `functionSelectors` set with the function selectors to remove. Set the `action` enum to `Remove`.
It is the design of the `diamondCut` function that cuts are explicit and intentional.
After adding/replacing/removing functions the `_calldata` argument is executed with `delegatecall` on `_init`. This execution is done to initialize data or setup or remove anything needed or no longer needed after adding, replacing and/or removing functions.
The loupe functions can be used in user-interface software. A user interface calls these functions to provide information about and visualize diamonds.
The loupe functions can be used in deployment functionality, upgrade functionality, testing and other software.
Some loupe implementations are not gas efficient and should not be called in on-chain transactions. Some loupe implementations may be gas efficient and can be called in on-chain transactions. Read the documentation of the loupe implementation you use.
1. When a function is called on a diamond it executes immediately if it is an "immutable function" defined directly in the diamond. Otherwise the diamond's fallback function is executed. The fallback function finds the facet associated with the function and executes the function using `delegatecall`. If there is no facet for the function then optionally a default function may be executed. If there is no facet for the function and no default function and no other mechanism to handle it then execution reverts.
1. All immutable functions must be emitted in the `DiamondCut` event as new functions added. And the loupe functions must return information about immutable functions if they exist. The facet address for an immutable function is the diamond's address.
1. Optionally a diamond implements ERC165. If a diamond has the `diamondCut` function then the interface ID used for it is `IDiamondCut.diamondCut.selector`. The interface ID used for the diamond loupe interface is `IDiamondLoupe.facets.selector ^ IDiamondLoupe.facetFunctionSelectors.selector ^ IDiamondLoupe.facetAddresses.selector ^ IDiamondLoupe.facetAddress.selector`.
The diamond address is the address that users interact with. The diamond address does not change. Only facet addresses can change by using the `diamondCut` function, or other function.
This standard is designed to make diamonds work well with user-interface software. Function selectors with the ABI of a contract provide enough information about functions to be useful for user-interface software.
1. Because diamonds do not have a max size limitation it is possible to add gas optimizing functions for use cases. For example someone could use a diamond to implement the ERC721 standard and implement batch transfer functions from the [ERC1412 standard](https://github.com/ethereum/EIPs/issues/1412) to reduce gas (and make batch transfers more convenient).
1. Some contract architectures require calling many contracts in one transaction. Gas savings can be realized by condensing those contracts into a single diamond and accessing contract storage directly.
1. Facets can be small, reducing gas costs. Because it costs more gas to call a function in a contract with many functions than a contract with few functions.
Since Solidity 0.6.4 it is possible to create pointers to structs in arbitrary places in contract storage. This enables diamonds and their facets to create their own storage layouts that are separate from each other and do not conflict with each other, but can still be shared between them. See this blog post for more information: [New Storage Layout For Proxy Contracts and Diamonds](https://medium.com/1milliondevs/new-storage-layout-for-proxy-contracts-and-diamonds-98d01d0eadb). The reference implementations for EIP-2535 uses Diamond Storage.
Diamond Storage is not the same thing as unstructured storage. Unstructured storage reads and writes specific values like unsigned integers and addresses at specified locations in contract storage. Diamond Storage uses structs at specified locations in contract storage for reading and writing. Structs can hold any number of state variables of any type.
Software or a user can verify what version of a function is called by getting the facet address of the function. This can be done by calling the `facetAddress` function from the DiamondLoupe interface. This function takes a function selector as an argument and returns the facet address where it is implemented.
6. Instead of calling an external function defined in another facet you can instead create an internal function version of the external function. Add the internal version of the function to the facet that needs to use it.
Solidity provides the `fallback` function so that specific functionality can be executed when a function is called on a contract that does not exist in the contract. This same behavior can optionally be implemented in a diamond by implementing and using a default function, which is a function that is executed when a function is called on a diamond that does not exist in the diamond.
A default function can be implemented a number of ways and this standard does not specify how it must be implemented.
> **Note:** The design and implementation of diamond ownership/authentication is **not** part of this standard. The examples given in this standard and in the reference implementation are just **examples** of how it could be done.
It is possible to create many different authentication or ownership schemes with EIP-2535. Authentication schemes can be very simple or complex, fine grained or coarse. EIP-2535 does not limit it in any way. For example ownership/authentication could be as simple as a single account address having the authority to add/replace/remove functions. Or a decentralized autonomous organization could have the authority to only add/replace/remove certain functions.
Consensus functionality could be implemented such as an approval function that multiple different people call to approve changes before they are executed with the `diamondCut` function. These are just examples.
If a person can add/replace functions then that person can alter storage willy-nilly. This is very powerful and very dangerous. However the capability can be used while eliminating or reducing the danger. The danger is eliminated or reduced by limiting **who** can add/replace/remove functions, limiting **when** functions can be added/replaced/removed and by **transparency**.
1. Use an upgradeable diamond until it is certain that no new features are needed and then make it a finished diamond by removing the ability to add/replace/remove functions.
1. Program into the `diamondCut` function certain periods of time that the diamond can be upgraded. For example the `diamondCut` function could be programmed so that a diamond could only be upgraded during a specific five hour period each year. Attention and transparency could be applied to that five hour period to ensure upgrades are done right.
A function selector clash occurs when two different function signatures hash to the same four-byte hash. This has the unintended consequence of replacing an existing function in a diamond when the intention was to add a new function. This scenario is not possible with the `diamondCut` function because it prevents adding function selectors that already exist.
Diamonds emit an event every time one or more functions are added, replaced or removed. All source code can be verified. This enables people and software to monitor changes to a contract. If any bad acting function is added to a diamond then it can be seen.
Security and domain experts can review the history of change of a diamond to detect any history of foul play.
## Backwards Compatibility
This standard makes upgradeable diamonds compatible with future standards and functionality because new functions can be added and existing functions can be replaced or removed.
[Ethereum's Maximum Contract Size Limit is Solved with EIP-2535 Diamonds](https://dev.to/mudgen/ethereum-s-maximum-contract-size-limit-is-solved-with-the-diamond-standard-2189)
[EIP-2535 Diamonds: A new paradigm for upgradeability](https://medium.com/derivadex/the-diamond-standard-a-new-paradigm-for-upgradeability-569121a08954)
[New Storage Layout For Proxy Contracts and Diamonds](https://medium.com/1milliondevs/new-storage-layout-for-proxy-contracts-and-diamonds-98d01d0eadb)
[Solidity Libraries Can't Have State Variables -- Oh Yes They Can!](https://dev.to/mudgen/solidity-libraries-can-t-have-state-variables-oh-yes-they-can-3ke9)
[ Smart Contracts Sharing Common Data](https://medium.com/coinmonks/smart-contracts-sharing-common-data-777310263ac0?source=friends_link&sk=b462ff3559ae9c8da243ba31a557e4f4)
[Sharing Common Data Using Libraries](https://medium.com/coinmonks/sharing-common-data-using-libraries-6573857d328c?source=friends_link&sk=1da1ef153b8d15f3f7bb9f4ce429890a)
This standard was inspired by [EIP-1538](./eip-1538.md) and ZeppelinOS's implementation of [Upgradeability with vtables](https://github.com/zeppelinos/labs/tree/master/upgradeability_with_vtable).
This standard was also inspired by the design and implementation of the [Mokens contract](https://etherscan.io/address/0xc1eab49cf9d2e23e43bcf23b36b2be14fc2f8838#code).