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)
Facet state variables are declared in structs. Each struct is given a specific position in contract storage. This technique is called **Diamond Storage**.
Any number of structs, each with a different storage position, can be used by a facet.
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.
By using diamond storage facets can be developed independently, without connection or concern for other facets.
Facets can share state variables by using the same structs at the same storage positions.
Facets can share internal functions and libraries by inheriting the same contracts or using the same libraries.
In these ways facets are separate, independent units but can share state and functionality.
## Facets are Reusable and Composable
A deployed facet can be used by any number of diamonds.
Different combinations of facets can be used with different diamonds.
It is possible to create and deploy a set of facets that are reused by different diamonds over time.
The ability to use the same deployed facets for many diamonds reduces deployment costs.
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.
## Diagrams
### Diamond Structure
This diagram shows the structure of a diamond:
<imgsrc="../assets/eip-2535/DiamondDiagram.png">
### Diamond Storage
The diagram below shows facets with their own data and data shared between them.
Notice that all data is stored in the diamond. But different facets have different access to data.
In this diagram
* Only FacetA can access DataA
* Only FacetB can access DataB
* Only the diamond's own code can access DataD.
* FacetA and FacetB share access to DataAB.
* The diamond's own code, FacetA and FacetB share access to DataABD.
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. An event that shows what functions are added, replaced and removed.
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. Upgrade diamonds to fix bugs, add functionality and implement new standards.
1. Organize your code with a diamond and facets.
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 technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).-->
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.
> **Note:** This specification specifies what needs to be implemented for a contract to be a diamond.
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.
3. 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. It has been designed for maximum flexibility while using the least amount of gas.
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 tightly-packed data encoding used by the `_diamondCut` argument is defined here:
```Solidity
_diamondCut = [
abi.encodePacked(facet, sel1, sel2, sel3, ...),
abi.encodePacked(facet, sel1, sel2, sel4, ...),
...
]
facet is the address of a facet
sel1, sel2, sel3 etc. are four-byte function selectors
```
#### Adding/Replacing/Removing Functions
A diamond contains within it a mapping of function selectors to facet addresses. Functions are added/replaced/removed by modifying this mapping.
The `_diamondCut` argument is an array of bytes arrays.
Each bytes array contains a facet address and one or more function selectors. The mapping in a diamond is updated by each bytes array. The selectors in a bytes array are associated with the facet address in the same bytes array. This is how functions are added or replaced.
However if a facet address in a bytes array is `address(0)` then the function selectors in the same bytes array are removed. This is how functions are removed from a diamond.
The `diamondCut` function reverts if a supplied function selector is already associated with the supplied facet address. The `diamondCut` function reverts if a supplied function selector can’t be removed because it already does not exist.
#### Executing _calldata
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.
If the `_init` value is `address(0)` then `_calldata` is executed with `delegatecall` on the diamond itself.
If `_init` is `address(0)` and `_calldata` contains 0 bytes then `_calldata` execution is skipped. `_calldata` is not executed and the `diamondCut` call can complete successfully.
If `_init` is not `address(0)` and `_calldata` contains 0 bytes then it is an error and `diamondCut` reverts.
#### DiamondCut Event
The `_diamondCut`, `_init`, and `_calldata` arguments are passed directly to the `DiamondCut` event.
Any time one or more functions are added, replaced or removed the `DiamondCut` event MUST be emitted to record changes.
The loupe functions are designed for user-interface software. A user interface calls these functions to provide information about and visualize diamonds.
1. A diamond contains a fallback function and zero or more immutable functions that are defined directly within it.
1. A diamond associates function selectors with facets.
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 execution reverts.
1. Each time functions are added, replaced or removed a `DiamondCut` event is emitted to record it.
1. A diamond implements the DiamondLoupe interface.
1. A diamond implements ERC165. If a diamond has the `diamondCut` function then the interface ID used for it is `Diamond.diamondCut.selector`. The interface ID used for the DiamondLoupe interface is `DiamondLoupe.facets.selector ^ DiamondLoupe.facetFunctionSelectors.selector ^ DiamondLoupe.facetAddresses.selector ^ DiamondLoupe.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.
A reference implementation is given in the [Diamond repository](https://github.com/mudgen/Diamond). Use that implementation to get started implementing diamonds.
<!--The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.-->
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 implementation for the diamond standard 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.
5. Instead of using `delegatecall` to call an external function defined in another facet you can instead create an internal function version of the external function and use that.
>**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 the diamond standard. Authentication schemes can be very simple or complex, fine grained or coarse. The diamond standard 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.
The development of standards and implementations of ownership, control and authentication of diamonds is encouraged.
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. Function selector clashes are very rare but should be prevented by using tools that check for function selector clashes before calling the `diamondCut` function or similar function.
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 the Diamond Standard](https://dev.to/mudgen/ethereum-s-maximum-contract-size-limit-is-solved-with-the-diamond-standard-2189)
[The Diamond Standard: A new paradigm for upgradeability](https://medium.com/derivadex/the-diamond-standard-a-new-paradigm-for-upgradeability-569121a08954)
The Diamond Standard is an improved design over [EIP-1538](https://eips.ethereum.org/EIPS/eip-1538) using ABIEncoderV2 and function selectors.
The Diamond Standard replaces EIP-1538.
This standard was inspired by [EIP-1538](https://eips.ethereum.org/EIPS/eip-1538) 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).
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).