mirror of
https://github.com/status-im/EIPs.git
synced 2025-02-23 12:18:16 +00:00
Automatically merged updates to draft EIP(s) 2535 (#3452)
Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft, Review, or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
This commit is contained in:
parent
3b0eef561b
commit
c6f1a82f93
@ -13,7 +13,7 @@ created: 2020-02-22
|
||||
|
||||
## Simple Summary
|
||||
|
||||
Enables people to write contracts with virtually no size limit in a modular and gas-efficient way.
|
||||
Enables people to write smart contracts with virtually no size limit in a modular and gas-efficient way.
|
||||
|
||||
Diamonds can be upgraded on the fly without having to redeploy existing functionality.
|
||||
|
||||
@ -27,9 +27,10 @@ Terminology from the diamond industry.
|
||||
|
||||
There are a number of different reasons to use diamonds. Here are some of them:
|
||||
|
||||
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.
|
||||
2. **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.
|
||||
3. **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.
|
||||
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 Transparency
|
||||
|
||||
@ -103,7 +104,15 @@ A diamond that is mutable can be made immutable by removing such functions.
|
||||
|
||||
A diamond can be upgraded if it has a diamondCut external function or other function(s) that can add/replace/remove functions.
|
||||
|
||||
## Facets and State Variables
|
||||
## Organizing State Variables in 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.
|
||||
|
||||
Described below are diamond storage and AppStorage which are two state variable organizational patterns that have been successfully used in diamonds.
|
||||
|
||||
Another successful pattern has been to write a storage contract that contains all state variables and is inherited by all facets.
|
||||
|
||||
## Facets, State Variables and Diamond Storage
|
||||
|
||||
A facet defines external functions and can define or use internal functions, libraries, and state variables.
|
||||
|
||||
@ -152,9 +161,38 @@ By using diamond storage facets can declare their own state variables that do no
|
||||
|
||||
By using diamond storage facets can be developed independently, without connection or concern for other facets.
|
||||
|
||||
## AppStorage
|
||||
|
||||
A specialized version of diamond storage is AppStorage. This pattern is used to more conveniently and easily share state variables between 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 Can Use Other Contract Storage Strategies
|
||||
|
||||
Diamonds and facets don't have to use diamond storage. They can use other contract storage strategies such as contract inheritance.
|
||||
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.
|
||||
|
||||
Diamonds only need to implement the [Specification section](#specification) of this standard.
|
||||
|
||||
@ -439,7 +477,7 @@ A diamond implements the following implementation points:
|
||||
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. 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. 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`.
|
||||
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.
|
||||
|
||||
@ -483,7 +521,7 @@ Here are some solutions to this:
|
||||
1. Put common internal functions in a contract that is inherited by multiple facets.
|
||||
1. Put common internal functions in a Solidity library and use the library in facets.
|
||||
1. A type safe way to call an external function defined in another facet is to do this: MyOtherFacet(this).myFunction(arg1, arg2)
|
||||
1. A more gas-efficent way to call an external function defined in another facet is to use `delegatecall`. Here is an example of doing that:
|
||||
1. A more gas-efficient way to call an external function defined in another facet is to use `delegatecall`. Here is an example of doing that:
|
||||
```Solidity
|
||||
DiamondStorage storage ds = diamondStorage();
|
||||
bytes4 functionSelector = bytes4(keccak256("myFunction(uint256)"));
|
||||
@ -552,6 +590,8 @@ This standard makes upgradeable diamonds compatible with future standards and fu
|
||||
|
||||
### Diamond Articles
|
||||
|
||||
[Why Ethereum Diamonds Need A Standard](https://dev.to/mudgen/why-diamonds-need-a-standard-1i1h)
|
||||
|
||||
[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)
|
||||
|
||||
[Understanding Diamonds](https://dev.to/mudgen/understanding-diamonds-on-ethereum-1fb)
|
||||
@ -566,6 +606,8 @@ This standard makes upgradeable diamonds compatible with future standards and fu
|
||||
|
||||
[Ethereum Diamonds for On-Chain Decentralized Governance](https://dev.to/mudgen/ethereum-diamonds-for-on-chain-decentralized-governance-39op)
|
||||
|
||||
[How to Share Functions Between Facets of a Diamond](https://dev.to/mudgen/how-to-share-functions-between-facets-of-a-diamond-1njb)
|
||||
|
||||
### Diamond Storage Articles
|
||||
|
||||
[How Diamond Storage Works](https://dev.to/mudgen/how-diamond-storage-works-90e)
|
||||
@ -582,9 +624,9 @@ This standard makes upgradeable diamonds compatible with future standards and fu
|
||||
|
||||
### Diamond Tools
|
||||
|
||||
[buidler-deploy](https://github.com/wighawag/buidler-deploy#diamonds-and-facets)
|
||||
[Louper](https://louper.dev/) A user interface for all diamonds.
|
||||
|
||||
[Diamond Setter](https://github.com/lampshade9909/DiamondSetter)
|
||||
[buidler-deploy](https://github.com/wighawag/buidler-deploy#diamonds-and-facets)
|
||||
|
||||
### Implementations
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user