# Diamond-3-Hardhat Implementation + Typechain Support This is a simple example implementation for [EIP-2535 Diamond Standard](https://github.com/ethereum/EIPs/issues/2535). To learn about other implementations go here: https://github.com/mudgen/diamond The standard loupe functions have been gas-optimized in this implementation and can be called in on-chain transactions. However keep in mind that a diamond can have any number of functions and facets so it is still possible to get out-of-gas errors when calling loupe functions. Except for the `facetAddress` loupe function which has a fixed gas cost. ## Installation 1. Clone this repo: ```console git clone https://github.com/Timidan/diamond-3-hardhat.git ``` 2. Install NPM packages: ```console cd diamond-3-hardhat npm install or yarn install ``` ## Deployment ```console npx hardhat run scripts/deploy.ts ``` ## Run tests: ```console npx hardhat test ``` ## Upgrade a diamond Check the `scripts/deploy.ts` and or the `test/diamondTest.ts` file for examples of upgrades. Note that upgrade functionality is optional. It is possible to deploy a diamond that can't be upgraded, which is a 'Single Cut Diamond'. It is also possible to deploy an upgradeable diamond and at a later date remove its `diamondCut` function so it can't be upgraded any more. Note that any number of functions from any number of facets can be added/replaced/removed on a diamond in a single transaction. In addition an initialization function can be executed in the same transaction as an upgrade to initialize any state variables required for an upgrade. This 'everything done in a single transaction' capability ensures a diamond maintains a correct and consistent state during upgrades. ## Facet Information The `contracts/Diamond.sol` file shows an example of implementing a diamond. The `contracts/facets/DiamondCutFacet.sol` file shows how to implement the `diamondCut` external function. The `contracts/facets/DiamondLoupeFacet.sol` file shows how to implement the four standard loupe functions. The `contracts/libraries/LibDiamond.sol` file shows how to implement Diamond Storage and a `diamondCut` internal function. The `scripts/deploy.ts` file shows how to deploy a diamond. The `test/diamondTest.ts` file gives tests for the `diamondCut` function and the Diamond Loupe functions. ## How to Get Started Making Your Diamond 1. Reading and understand [EIP-2535 Diamonds](https://github.com/ethereum/EIPs/issues/2535). If something is unclear let me know! 2. Use a diamond reference implementation. You are at the right place because this is the README for a diamond reference implementation. This diamond implementation is boilerplate code that makes a diamond compliant with EIP-2535 Diamonds. Specifically you can copy and use the [DiamondCutFacet.sol](./contracts/facets/DiamondCutFacet.sol) and [DiamondLoupeFacet.sol](./contracts/facets/DiamondLoupeFacet.sol) contracts. They implement the `diamondCut` function and the loupe functions. The [Diamond.sol](./contracts/Diamond.sol) contract could be used as is, or it could be used as a starting point and customized. This contract is the diamond. Its deployment creates a diamond. It's address is a stable diamond address that does not change. The [LibDiamond.sol](./contracts/libraries/LibDiamond.sol) library could be used as is. It shows how to implement Diamond Storage. This contract includes contract ownership which you might want to change if you want to implement DAO-based ownership or other form of contract ownership. Go for it. Diamonds can work with any kind of contract ownership strategy. This library contains an internal function version of `diamondCut` that can be used in the constructor of a diamond or other places. ## Calling Diamond Functions In order to call a function that exists in a diamond you need to use the ABI information of the facet that has the function. Here is an example that uses ethers.js: ```typescript let myUsefulFacet = await ethers.getContract(facetName,diamondDeployedAddress) as facetNameType; ``` ```solidity string result = MyUsefulFacet(address(diamondContract)).getResult() ``` ## Get Help and Join the Community If you need help or would like to discuss diamonds then send me a message [on twitter](https://twitter.com/mudgen), or [email me](mailto:nick@perfectabstractions.com). Or join the [EIP-2535 Diamonds Discord server](https://discord.gg/kQewPw2). ## Useful Links 1. [Introduction to the Diamond Standard, EIP-2535 Diamonds](https://eip2535diamonds.substack.com/p/introduction-to-the-diamond-standard) 1. [EIP-2535 Diamonds](https://github.com/ethereum/EIPs/issues/2535) 1. [Understanding Diamonds on Ethereum](https://dev.to/mudgen/understanding-diamonds-on-ethereum-1fb) 1. [Solidity Storage Layout For Proxy Contracts and Diamonds](https://medium.com/1milliondevs/solidity-storage-layout-for-proxy-contracts-and-diamonds-c4f009b6903) 1. [New Storage Layout For Proxy Contracts and Diamonds](https://medium.com/1milliondevs/new-storage-layout-for-proxy-contracts-and-diamonds-98d01d0eadb) 1. [Upgradeable smart contracts using the Diamond Standard](https://hiddentao.com/archives/2020/05/28/upgradeable-smart-contracts-using-diamond-standard) 1. [buidler-deploy supports diamonds](https://github.com/wighawag/buidler-deploy/) ## Author This example implementation was written by Nick Mudge. Contact: - https://twitter.com/mudgen - nick@perfectabstractions.com ## License MIT license. See the license file. Anyone can use or modify this software for their purposes.