diff --git a/basic/79-hardhat-foundry/.gitignore b/basic/79-hardhat-foundry/.gitignore index 14bf4a17e..a14cb90b6 100644 --- a/basic/79-hardhat-foundry/.gitignore +++ b/basic/79-hardhat-foundry/.gitignore @@ -81,3 +81,4 @@ certora_* /**/*.js /lib +/contracts/diamond-2 diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/.gitattributes b/basic/79-hardhat-foundry/contracts/diamond-2/.gitattributes deleted file mode 100644 index 52031de51..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.sol linguist-language=Solidity diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/.gitignore b/basic/79-hardhat-foundry/contracts/diamond-2/.gitignore deleted file mode 100644 index 5f9b8f0b0..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules - -#Hardhat files -cache -artifacts -.env \ No newline at end of file diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/.prettierignore b/basic/79-hardhat-foundry/contracts/diamond-2/.prettierignore deleted file mode 100644 index 4c43fe68f..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -*.js \ No newline at end of file diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/.prettierrc b/basic/79-hardhat-foundry/contracts/diamond-2/.prettierrc deleted file mode 100644 index d0aeabad0..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/.prettierrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "overrides": [ - { - "files": "*.sol", - "options": { - "printWidth": 150, - "tabWidth": 4, - "useTabs": false, - "singleQuote": false, - "bracketSpacing": false, - "explicitTypes": "always" - } - } - ] -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/LICENSE b/basic/79-hardhat-foundry/contracts/diamond-2/LICENSE deleted file mode 100644 index 3c4508b8a..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 Nick Mudge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/README.md b/basic/79-hardhat-foundry/contracts/diamond-2/README.md deleted file mode 100644 index 195529af7..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# Diamond-2-Hardhat Implementation - -This is a gas-optimized reference implementation for [EIP-2535 Diamonds](https://github.com/ethereum/EIPs/issues/2535). To learn about other implementations go here: https://github.com/mudgen/diamond - -This implementation uses Hardhat and Solidity 0.8.* - -Specifically this is a gas efficient implementation of the `diamondCut` function. Adding/replacing/removing is optimized to take the least gas. - -**Note:** The loupe functions in DiamondLoupeFacet.sol MUST be added to a diamond and are required by the EIP-2535 Diamonds standard. - -The loupe functions are NOT gas optimized. In this implementation the `facets`, `facetFunctionSelectors`, `facetAddresses` loupe functions are not meant to be called on-chain and may use too much gas or run out of gas when called in on-chain transactions. In this implementation these functions should be called by off-chain software like websites and Javascript libraries etc., where gas costs do not matter. - - -## Installation - -1. Clone this repo: -```console -git clone git@github.com:mudgen/diamond-2-hardhat.git -``` - -2. Install NPM packages: -```console -cd diamond-2-hardhat -npm install -``` - -## Deployment - -```console -npx hardhat run scripts/deploy.js -``` - -### How the scripts/deploy.js script works - -1. DiamondCutFacet is deployed. -1. The diamond is deployed, passing as arguments to the diamond constructor the owner address of the diamond and the DiamondCutFacet address. DiamondCutFacet has the `diamondCut` external function which is used to upgrade the diamond to add more functions. -1. The `DiamondInit` contract is deployed. This contains an `init` function which is called on the first diamond upgrade to initialize state of some state variables. Information on how the `diamondCut` function works is here: https://eips.ethereum.org/EIPS/eip-2535#diamond-interface -1. Facets are deployed. -1. The diamond is upgraded. The `diamondCut` function is used to add functions from facets to the diamond. In addition the `diamondCut` function calls the `init` function from the `DiamondInit` contract using `delegatecall` to initialize state variables. - -How a diamond is deployed is not part of the EIP-2535 Diamonds standard. This implementation shows a usable example. - -## Run tests: -```console -npx hardhat test -``` - -## Upgrade a diamond - -Check the `scripts/deploy.js` and or the `test/diamondTest.js` 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 - -**Note:** In this implementation the loupe functions are NOT gas optimized. The `facets`, `facetFunctionSelectors`, `facetAddresses` loupe functions are not meant to be called on-chain and may use too much gas or run out of gas when called in on-chain transactions. In this implementation these functions should be called by off-chain software like websites and Javascript libraries etc., where gas costs do not matter. - -However the `facetAddress` loupe function is gas efficient and can be called in on-chain transactions. - -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.js` file shows how to deploy a diamond. - -The `test/diamondTest.js` 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 web3.js: - -```javascript -let myUsefulFacet = new web3.eth.Contract(MyUsefulFacet.abi, diamondAddress); -``` - -In the code above we create a contract variable so we can call contract functions with it. - -In this example we know we will use a diamond because we pass a diamond's address as the second argument. But we are using an ABI from the MyUsefulFacet facet so we can call functions that are defined in that facet. MyUsefulFacet's functions must have been added to the diamond (using diamondCut) in order for the diamond to use the function information provided by the ABI of course. - -Similarly you need to use the ABI of a facet in Solidity code in order to call functions from a diamond. Here's an example of Solidity code that calls a function from a diamond: - -```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. - diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/Diamond.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/Diamond.sol deleted file mode 100644 index b66775208..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/Diamond.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -* -* Implementation of a diamond. -/******************************************************************************/ - -import { LibDiamond } from "./libraries/LibDiamond.sol"; -import { IDiamondCut } from "./interfaces/IDiamondCut.sol"; - -contract Diamond { - - constructor(address _contractOwner, address _diamondCutFacet) payable { - LibDiamond.setContractOwner(_contractOwner); - - // Add the diamondCut external function from the diamondCutFacet - IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1); - bytes4[] memory functionSelectors = new bytes4[](1); - functionSelectors[0] = IDiamondCut.diamondCut.selector; - cut[0] = IDiamondCut.FacetCut({ - facetAddress: _diamondCutFacet, - action: IDiamondCut.FacetCutAction.Add, - functionSelectors: functionSelectors - }); - LibDiamond.diamondCut(cut, address(0), ""); - } - - // Find facet for function that is called and execute the - // function if a facet is found and return any value. - fallback() external payable { - LibDiamond.DiamondStorage storage ds; - bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION; - // get diamond storage - assembly { - ds.slot := position - } - // get facet from function selector - address facet = address(bytes20(ds.facets[msg.sig])); - require(facet != address(0), "Diamond: Function does not exist"); - // Execute external function from facet using delegatecall and return any value. - assembly { - // copy function selector and any arguments - calldatacopy(0, 0, calldatasize()) - // execute function call using the facet - let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0) - // get any return value - returndatacopy(0, 0, returndatasize()) - // return any return value or error back to the caller - switch result - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } - - receive() external payable {} -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/DiamondCutFacet.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/DiamondCutFacet.sol deleted file mode 100644 index ddf68c2f4..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/DiamondCutFacet.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ - -import { IDiamondCut } from "../interfaces/IDiamondCut.sol"; -import { LibDiamond } from "../libraries/LibDiamond.sol"; - -// Remember to add the loupe functions from DiamondLoupeFacet to the diamond. -// The loupe functions are required by the EIP2535 Diamonds standard - -contract DiamondCutFacet is IDiamondCut { - /// @notice Add/replace/remove any number of functions and optionally execute - /// a function with delegatecall - /// @param _diamondCut Contains the facet addresses and function selectors - /// @param _init The address of the contract or facet to execute _calldata - /// @param _calldata A function call, including function selector and arguments - /// _calldata is executed with delegatecall on _init - function diamondCut( - FacetCut[] calldata _diamondCut, - address _init, - bytes calldata _calldata - ) external override { - LibDiamond.enforceIsContractOwner(); - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - uint256 originalSelectorCount = ds.selectorCount; - uint256 selectorCount = originalSelectorCount; - bytes32 selectorSlot; - // Check if last selector slot is not full - // "selectorCount & 7" is a gas efficient modulo by eight "selectorCount % 8" - if (selectorCount & 7 > 0) { - // get last selectorSlot - // "selectorCount >> 3" is a gas efficient division by 8 "selectorCount / 8" - selectorSlot = ds.selectorSlots[selectorCount >> 3]; - } - // loop through diamond cut - for (uint256 facetIndex; facetIndex < _diamondCut.length; ) { - (selectorCount, selectorSlot) = LibDiamond.addReplaceRemoveFacetSelectors( - selectorCount, - selectorSlot, - _diamondCut[facetIndex].facetAddress, - _diamondCut[facetIndex].action, - _diamondCut[facetIndex].functionSelectors - ); - - unchecked { - facetIndex++; - } - } - if (selectorCount != originalSelectorCount) { - ds.selectorCount = uint16(selectorCount); - } - // If last selector slot is not full - // "selectorCount & 7" is a gas efficient modulo by eight "selectorCount % 8" - if (selectorCount & 7 > 0) { - // "selectorCount >> 3" is a gas efficient division by 8 "selectorCount / 8" - ds.selectorSlots[selectorCount >> 3] = selectorSlot; - } - emit DiamondCut(_diamondCut, _init, _calldata); - LibDiamond.initializeDiamondCut(_init, _calldata); - } -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/DiamondLoupeFacet.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/DiamondLoupeFacet.sol deleted file mode 100644 index 04ec4a1e4..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/DiamondLoupeFacet.sol +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ - -import { LibDiamond } from "../libraries/LibDiamond.sol"; -import { IDiamondLoupe } from "../interfaces/IDiamondLoupe.sol"; -import { IERC165 } from "../interfaces/IERC165.sol"; - -// The functions in DiamondLoupeFacet MUST be added to a diamond. -// The EIP-2535 Diamond standard requires these functions - -contract DiamondLoupeFacet is IDiamondLoupe, IERC165 { - // Diamond Loupe Functions - //////////////////////////////////////////////////////////////////// - /// These functions are expected to be called frequently by tools. - // - // struct Facet { - // address facetAddress; - // bytes4[] functionSelectors; - // } - /// @notice Gets all facets and their selectors. - /// @return facets_ Facet - function facets() external override view returns (Facet[] memory facets_) { - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - facets_ = new Facet[](ds.selectorCount); - uint16[] memory numFacetSelectors = new uint16[](ds.selectorCount); - uint256 numFacets; - uint256 selectorIndex; - // loop through function selectors - for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) { - bytes32 slot = ds.selectorSlots[slotIndex]; - for (uint256 selectorSlotIndex; selectorSlotIndex < 8; selectorSlotIndex++) { - selectorIndex++; - if (selectorIndex > ds.selectorCount) { - break; - } - // " << 5 is the same as multiplying by 32 ( * 32) - bytes4 selector = bytes4(slot << (selectorSlotIndex << 5)); - address facetAddress_ = address(bytes20(ds.facets[selector])); - bool continueLoop; - for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) { - if (facets_[facetIndex].facetAddress == facetAddress_) { - facets_[facetIndex].functionSelectors[numFacetSelectors[facetIndex]] = selector; - // probably will never have more than 256 functions from one facet contract - require(numFacetSelectors[facetIndex] < 255); - numFacetSelectors[facetIndex]++; - continueLoop = true; - break; - } - } - if (continueLoop) { - continue; - } - facets_[numFacets].facetAddress = facetAddress_; - facets_[numFacets].functionSelectors = new bytes4[](ds.selectorCount); - facets_[numFacets].functionSelectors[0] = selector; - numFacetSelectors[numFacets] = 1; - numFacets++; - } - } - for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) { - uint256 numSelectors = numFacetSelectors[facetIndex]; - bytes4[] memory selectors = facets_[facetIndex].functionSelectors; - // setting the number of selectors - assembly { - mstore(selectors, numSelectors) - } - } - // setting the number of facets - assembly { - mstore(facets_, numFacets) - } - } - - /// @notice Gets all the function selectors supported by a specific facet. - /// @param _facet The facet address. - /// @return _facetFunctionSelectors The selectors associated with a facet address. - function facetFunctionSelectors(address _facet) external override view returns (bytes4[] memory _facetFunctionSelectors) { - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - uint256 numSelectors; - _facetFunctionSelectors = new bytes4[](ds.selectorCount); - uint256 selectorIndex; - // loop through function selectors - for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) { - bytes32 slot = ds.selectorSlots[slotIndex]; - for (uint256 selectorSlotIndex; selectorSlotIndex < 8; selectorSlotIndex++) { - selectorIndex++; - if (selectorIndex > ds.selectorCount) { - break; - } - // " << 5 is the same as multiplying by 32 ( * 32) - bytes4 selector = bytes4(slot << (selectorSlotIndex << 5)); - address facet = address(bytes20(ds.facets[selector])); - if (_facet == facet) { - _facetFunctionSelectors[numSelectors] = selector; - numSelectors++; - } - } - } - // Set the number of selectors in the array - assembly { - mstore(_facetFunctionSelectors, numSelectors) - } - } - - /// @notice Get all the facet addresses used by a diamond. - /// @return facetAddresses_ - function facetAddresses() external override view returns (address[] memory facetAddresses_) { - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - facetAddresses_ = new address[](ds.selectorCount); - uint256 numFacets; - uint256 selectorIndex; - // loop through function selectors - for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) { - bytes32 slot = ds.selectorSlots[slotIndex]; - for (uint256 selectorSlotIndex; selectorSlotIndex < 8; selectorSlotIndex++) { - selectorIndex++; - if (selectorIndex > ds.selectorCount) { - break; - } - // " << 5 is the same as multiplying by 32 ( * 32) - bytes4 selector = bytes4(slot << (selectorSlotIndex << 5)); - address facetAddress_ = address(bytes20(ds.facets[selector])); - bool continueLoop; - for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) { - if (facetAddress_ == facetAddresses_[facetIndex]) { - continueLoop = true; - break; - } - } - if (continueLoop) { - continue; - } - facetAddresses_[numFacets] = facetAddress_; - numFacets++; - } - } - // Set the number of facet addresses in the array - assembly { - mstore(facetAddresses_, numFacets) - } - } - - /// @notice Gets the facet that supports the given selector. - /// @dev If facet is not found return address(0). - /// @param _functionSelector The function selector. - /// @return facetAddress_ The facet address. - function facetAddress(bytes4 _functionSelector) external override view returns (address facetAddress_) { - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - facetAddress_ = address(bytes20(ds.facets[_functionSelector])); - } - - // This implements ERC-165. - function supportsInterface(bytes4 _interfaceId) external override view returns (bool) { - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - return ds.supportedInterfaces[_interfaceId]; - } -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/OwnershipFacet.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/OwnershipFacet.sol deleted file mode 100644 index 45cba09ba..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/OwnershipFacet.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { LibDiamond } from "../libraries/LibDiamond.sol"; -import { IERC173 } from "../interfaces/IERC173.sol"; - -contract OwnershipFacet is IERC173 { - function transferOwnership(address _newOwner) external override { - LibDiamond.enforceIsContractOwner(); - LibDiamond.setContractOwner(_newOwner); - } - - function owner() external override view returns (address owner_) { - owner_ = LibDiamond.contractOwner(); - } -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/Test1Facet.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/Test1Facet.sol deleted file mode 100644 index 3e7f5c655..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/Test1Facet.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract Test1Facet { - event TestEvent(address something); - - function test1Func1() external {} - - function test1Func2() external {} - - function test1Func3() external {} - - function test1Func4() external {} - - function test1Func5() external {} - - function test1Func6() external {} - - function test1Func7() external {} - - function test1Func8() external {} - - function test1Func9() external {} - - function test1Func10() external {} - - function test1Func11() external {} - - function test1Func12() external {} - - function test1Func13() external {} - - function test1Func14() external {} - - function test1Func15() external {} - - function test1Func16() external {} - - function test1Func17() external {} - - function test1Func18() external {} - - function test1Func19() external {} - - function test1Func20() external {} - - function supportsInterface(bytes4 _interfaceID) external view returns (bool) {} -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/Test2Facet.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/Test2Facet.sol deleted file mode 100644 index d0b893e16..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/facets/Test2Facet.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract Test2Facet { - function test2Func1() external {} - - function test2Func2() external {} - - function test2Func3() external {} - - function test2Func4() external {} - - function test2Func5() external {} - - function test2Func6() external {} - - function test2Func7() external {} - - function test2Func8() external {} - - function test2Func9() external {} - - function test2Func10() external {} - - function test2Func11() external {} - - function test2Func12() external {} - - function test2Func13() external {} - - function test2Func14() external {} - - function test2Func15() external {} - - function test2Func16() external {} - - function test2Func17() external {} - - function test2Func18() external {} - - function test2Func19() external {} - - function test2Func20() external {} -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IDiamondCut.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IDiamondCut.sol deleted file mode 100644 index 2972f6954..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IDiamondCut.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ - -interface IDiamondCut { - enum FacetCutAction {Add, Replace, Remove} - // Add=0, Replace=1, Remove=2 - - struct FacetCut { - address facetAddress; - FacetCutAction action; - bytes4[] functionSelectors; - } - - /// @notice Add/replace/remove any number of functions and optionally execute - /// a function with delegatecall - /// @param _diamondCut Contains the facet addresses and function selectors - /// @param _init The address of the contract or facet to execute _calldata - /// @param _calldata A function call, including function selector and arguments - /// _calldata is executed with delegatecall on _init - function diamondCut( - FacetCut[] calldata _diamondCut, - address _init, - bytes calldata _calldata - ) external; - - event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IDiamondLoupe.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IDiamondLoupe.sol deleted file mode 100644 index c3b2570fe..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IDiamondLoupe.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ - -// A loupe is a small magnifying glass used to look at diamonds. -// These functions look at diamonds -interface IDiamondLoupe { - /// These functions are expected to be called frequently - /// by tools. - - struct Facet { - address facetAddress; - bytes4[] functionSelectors; - } - - /// @notice Gets all facet addresses and their four byte function selectors. - /// @return facets_ Facet - function facets() external view returns (Facet[] memory facets_); - - /// @notice Gets all the function selectors supported by a specific facet. - /// @param _facet The facet address. - /// @return facetFunctionSelectors_ - function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_); - - /// @notice Get all the facet addresses used by a diamond. - /// @return facetAddresses_ - function facetAddresses() external view returns (address[] memory facetAddresses_); - - /// @notice Gets the facet that supports the given selector. - /// @dev If facet is not found return address(0). - /// @param _functionSelector The function selector. - /// @return facetAddress_ The facet address. - function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_); -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IERC165.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IERC165.sol deleted file mode 100644 index 04b7bcc9a..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IERC165.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IERC165 { - /// @notice Query if a contract implements an interface - /// @param interfaceId The interface identifier, as specified in ERC-165 - /// @dev Interface identification is specified in ERC-165. This function - /// uses less than 30,000 gas. - /// @return `true` if the contract implements `interfaceID` and - /// `interfaceID` is not 0xffffffff, `false` otherwise - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IERC173.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IERC173.sol deleted file mode 100644 index a70804845..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/interfaces/IERC173.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title ERC-173 Contract Ownership Standard -/// Note: the ERC-165 identifier for this interface is 0x7f5828d0 -/* is ERC165 */ -interface IERC173 { - /// @dev This emits when ownership of a contract changes. - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /// @notice Get the address of the owner - /// @return owner_ The address of the owner. - function owner() external view returns (address owner_); - - /// @notice Set the address of the new owner of the contract - /// @dev Set _newOwner to address(0) to renounce any ownership. - /// @param _newOwner The address of the new owner of the contract - function transferOwnership(address _newOwner) external; -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/libraries/LibDiamond.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/libraries/LibDiamond.sol deleted file mode 100644 index de956407a..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/libraries/LibDiamond.sol +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -/******************************************************************************/ -import { IDiamondCut } from "../interfaces/IDiamondCut.sol"; - -// Remember to add the loupe functions from DiamondLoupeFacet to the diamond. -// The loupe functions are required by the EIP2535 Diamonds standard - -error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata); - -library LibDiamond { - bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage"); - - struct DiamondStorage { - // maps function selectors to the facets that execute the functions. - // and maps the selectors to their position in the selectorSlots array. - // func selector => address facet, selector position - mapping(bytes4 => bytes32) facets; - // array of slots of function selectors. - // each slot holds 8 function selectors. - mapping(uint256 => bytes32) selectorSlots; - // The number of function selectors in selectorSlots - uint16 selectorCount; - // Used to query if a contract implements an interface. - // Used to implement ERC-165. - mapping(bytes4 => bool) supportedInterfaces; - // owner of the contract - address contractOwner; - } - - function diamondStorage() internal pure returns (DiamondStorage storage ds) { - bytes32 position = DIAMOND_STORAGE_POSITION; - assembly { - ds.slot := position - } - } - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - function setContractOwner(address _newOwner) internal { - DiamondStorage storage ds = diamondStorage(); - address previousOwner = ds.contractOwner; - ds.contractOwner = _newOwner; - emit OwnershipTransferred(previousOwner, _newOwner); - } - - function contractOwner() internal view returns (address contractOwner_) { - contractOwner_ = diamondStorage().contractOwner; - } - - function enforceIsContractOwner() internal view { - require(msg.sender == diamondStorage().contractOwner, "LibDiamond: Must be contract owner"); - } - - event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata); - - bytes32 constant CLEAR_ADDRESS_MASK = bytes32(uint256(0xffffffffffffffffffffffff)); - bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224)); - - // Internal function version of diamondCut - // This code is almost the same as the external diamondCut, - // except it is using 'Facet[] memory _diamondCut' instead of - // 'Facet[] calldata _diamondCut'. - // The code is duplicated to prevent copying calldata to memory which - // causes an error for a two dimensional array. - function diamondCut( - IDiamondCut.FacetCut[] memory _diamondCut, - address _init, - bytes memory _calldata - ) internal { - DiamondStorage storage ds = diamondStorage(); - uint256 originalSelectorCount = ds.selectorCount; - uint256 selectorCount = originalSelectorCount; - bytes32 selectorSlot; - // Check if last selector slot is not full - // "selectorCount & 7" is a gas efficient modulo by eight "selectorCount % 8" - if (selectorCount & 7 > 0) { - // get last selectorSlot - // "selectorSlot >> 3" is a gas efficient division by 8 "selectorSlot / 8" - selectorSlot = ds.selectorSlots[selectorCount >> 3]; - } - // loop through diamond cut - for (uint256 facetIndex; facetIndex < _diamondCut.length; ) { - (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors( - selectorCount, - selectorSlot, - _diamondCut[facetIndex].facetAddress, - _diamondCut[facetIndex].action, - _diamondCut[facetIndex].functionSelectors - ); - - unchecked { - facetIndex++; - } - } - if (selectorCount != originalSelectorCount) { - ds.selectorCount = uint16(selectorCount); - } - // If last selector slot is not full - // "selectorCount & 7" is a gas efficient modulo by eight "selectorCount % 8" - if (selectorCount & 7 > 0) { - // "selectorSlot >> 3" is a gas efficient division by 8 "selectorSlot / 8" - ds.selectorSlots[selectorCount >> 3] = selectorSlot; - } - emit DiamondCut(_diamondCut, _init, _calldata); - initializeDiamondCut(_init, _calldata); - } - - function addReplaceRemoveFacetSelectors( - uint256 _selectorCount, - bytes32 _selectorSlot, - address _newFacetAddress, - IDiamondCut.FacetCutAction _action, - bytes4[] memory _selectors - ) internal returns (uint256, bytes32) { - DiamondStorage storage ds = diamondStorage(); - require(_selectors.length > 0, "LibDiamondCut: No selectors in facet to cut"); - if (_action == IDiamondCut.FacetCutAction.Add) { - enforceHasContractCode(_newFacetAddress, "LibDiamondCut: Add facet has no code"); - for (uint256 selectorIndex; selectorIndex < _selectors.length; ) { - bytes4 selector = _selectors[selectorIndex]; - bytes32 oldFacet = ds.facets[selector]; - require(address(bytes20(oldFacet)) == address(0), "LibDiamondCut: Can't add function that already exists"); - // add facet for selector - ds.facets[selector] = bytes20(_newFacetAddress) | bytes32(_selectorCount); - // "_selectorCount & 7" is a gas efficient modulo by eight "_selectorCount % 8" - // " << 5 is the same as multiplying by 32 ( * 32) - uint256 selectorInSlotPosition = (_selectorCount & 7) << 5; - // clear selector position in slot and add selector - _selectorSlot = (_selectorSlot & ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) | (bytes32(selector) >> selectorInSlotPosition); - // if slot is full then write it to storage - if (selectorInSlotPosition == 224) { - // "_selectorSlot >> 3" is a gas efficient division by 8 "_selectorSlot / 8" - ds.selectorSlots[_selectorCount >> 3] = _selectorSlot; - _selectorSlot = 0; - } - _selectorCount++; - - unchecked { - selectorIndex++; - } - } - } else if (_action == IDiamondCut.FacetCutAction.Replace) { - enforceHasContractCode(_newFacetAddress, "LibDiamondCut: Replace facet has no code"); - for (uint256 selectorIndex; selectorIndex < _selectors.length; ) { - bytes4 selector = _selectors[selectorIndex]; - bytes32 oldFacet = ds.facets[selector]; - address oldFacetAddress = address(bytes20(oldFacet)); - // only useful if immutable functions exist - require(oldFacetAddress != address(this), "LibDiamondCut: Can't replace immutable function"); - require(oldFacetAddress != _newFacetAddress, "LibDiamondCut: Can't replace function with same function"); - require(oldFacetAddress != address(0), "LibDiamondCut: Can't replace function that doesn't exist"); - // replace old facet address - ds.facets[selector] = (oldFacet & CLEAR_ADDRESS_MASK) | bytes20(_newFacetAddress); - - unchecked { - selectorIndex++; - } - } - } else if (_action == IDiamondCut.FacetCutAction.Remove) { - require(_newFacetAddress == address(0), "LibDiamondCut: Remove facet address must be address(0)"); - // "_selectorCount >> 3" is a gas efficient division by 8 "_selectorCount / 8" - uint256 selectorSlotCount = _selectorCount >> 3; - // "_selectorCount & 7" is a gas efficient modulo by eight "_selectorCount % 8" - uint256 selectorInSlotIndex = _selectorCount & 7; - for (uint256 selectorIndex; selectorIndex < _selectors.length; ) { - if (_selectorSlot == 0) { - // get last selectorSlot - selectorSlotCount--; - _selectorSlot = ds.selectorSlots[selectorSlotCount]; - selectorInSlotIndex = 7; - } else { - selectorInSlotIndex--; - } - bytes4 lastSelector; - uint256 oldSelectorsSlotCount; - uint256 oldSelectorInSlotPosition; - // adding a block here prevents stack too deep error - { - bytes4 selector = _selectors[selectorIndex]; - bytes32 oldFacet = ds.facets[selector]; - require(address(bytes20(oldFacet)) != address(0), "LibDiamondCut: Can't remove function that doesn't exist"); - // only useful if immutable functions exist - require(address(bytes20(oldFacet)) != address(this), "LibDiamondCut: Can't remove immutable function"); - // replace selector with last selector in ds.facets - // gets the last selector - // " << 5 is the same as multiplying by 32 ( * 32) - lastSelector = bytes4(_selectorSlot << (selectorInSlotIndex << 5)); - if (lastSelector != selector) { - // update last selector slot position info - ds.facets[lastSelector] = (oldFacet & CLEAR_ADDRESS_MASK) | bytes20(ds.facets[lastSelector]); - } - delete ds.facets[selector]; - uint256 oldSelectorCount = uint16(uint256(oldFacet)); - // "oldSelectorCount >> 3" is a gas efficient division by 8 "oldSelectorCount / 8" - oldSelectorsSlotCount = oldSelectorCount >> 3; - // "oldSelectorCount & 7" is a gas efficient modulo by eight "oldSelectorCount % 8" - // " << 5 is the same as multiplying by 32 ( * 32) - oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5; - } - if (oldSelectorsSlotCount != selectorSlotCount) { - bytes32 oldSelectorSlot = ds.selectorSlots[oldSelectorsSlotCount]; - // clears the selector we are deleting and puts the last selector in its place. - oldSelectorSlot = - (oldSelectorSlot & ~(CLEAR_SELECTOR_MASK >> oldSelectorInSlotPosition)) | - (bytes32(lastSelector) >> oldSelectorInSlotPosition); - // update storage with the modified slot - ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot; - } else { - // clears the selector we are deleting and puts the last selector in its place. - _selectorSlot = - (_selectorSlot & ~(CLEAR_SELECTOR_MASK >> oldSelectorInSlotPosition)) | - (bytes32(lastSelector) >> oldSelectorInSlotPosition); - } - if (selectorInSlotIndex == 0) { - delete ds.selectorSlots[selectorSlotCount]; - _selectorSlot = 0; - } - - unchecked { - selectorIndex++; - } - } - _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex; - } else { - revert("LibDiamondCut: Incorrect FacetCutAction"); - } - return (_selectorCount, _selectorSlot); - } - - function initializeDiamondCut(address _init, bytes memory _calldata) internal { - if (_init == address(0)) { - return; - } - enforceHasContractCode(_init, "LibDiamondCut: _init address has no code"); - (bool success, bytes memory error) = _init.delegatecall(_calldata); - if (!success) { - if (error.length > 0) { - // bubble up error - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(error) - revert(add(32, error), returndata_size) - } - } else { - revert InitializationFunctionReverted(_init, _calldata); - } - } - } - - function enforceHasContractCode(address _contract, string memory _errorMessage) internal view { - uint256 contractSize; - assembly { - contractSize := extcodesize(_contract) - } - require(contractSize > 0, _errorMessage); - } -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/upgradeInitializers/DiamondInit.sol b/basic/79-hardhat-foundry/contracts/diamond-2/contracts/upgradeInitializers/DiamondInit.sol deleted file mode 100644 index 661f866ac..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/contracts/upgradeInitializers/DiamondInit.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/******************************************************************************\ -* Author: Nick Mudge (https://twitter.com/mudgen) -* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 -* -* Implementation of a diamond. -/******************************************************************************/ - -import {LibDiamond} from "../libraries/LibDiamond.sol"; -import { IDiamondLoupe } from "../interfaces/IDiamondLoupe.sol"; -import { IDiamondCut } from "../interfaces/IDiamondCut.sol"; -import { IERC173 } from "../interfaces/IERC173.sol"; -import { IERC165 } from "../interfaces/IERC165.sol"; - -// It is expected that this contract is customized if you want to deploy your diamond -// with data from a deployment script. Use the init function to initialize state variables -// of your diamond. Add parameters to the init funciton if you need to. - -contract DiamondInit { - - // You can add parameters to this function in order to pass in - // data to set your own state variables - function init() external { - // adding ERC165 data - LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); - ds.supportedInterfaces[type(IERC165).interfaceId] = true; - ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true; - ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true; - ds.supportedInterfaces[type(IERC173).interfaceId] = true; - - // add your own state variables - // EIP-2535 specifies that the `diamondCut` function takes two optional - // arguments: address _init and bytes calldata _calldata - // These arguments are used to execute an arbitrary function using delegatecall - // in order to set state variables in the diamond during deployment or an upgrade - // More info here: https://eips.ethereum.org/EIPS/eip-2535#diamond-interface - } - - -} diff --git a/basic/79-hardhat-foundry/contracts/diamond-2/package.json b/basic/79-hardhat-foundry/contracts/diamond-2/package.json deleted file mode 100644 index 67ff0c0e3..000000000 --- a/basic/79-hardhat-foundry/contracts/diamond-2/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "contracts-starter", - "version": "1.0.0", - "description": "Template for contract projects.", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/mudgen/contracts-starter.git" - }, - "author": "Nick Mudge", - "license": "MIT", - "bugs": { - "url": "https://github.com/mudgen/contracts-starter/issues" - }, - "homepage": "https://github.com/mudgen/contracts-starter#readme", - "devDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.2", - "@nomiclabs/hardhat-waffle": "^2.0.1", - "chai": "^4.3.4", - "dotenv": "^8.6.0", - "ethereum-waffle": "^3.4.0", - "ethers": "^5.4.1", - "hardhat": "^2.4.1", - "prettier": "^2.3.2", - "prettier-plugin-solidity": "^1.0.0-beta.13", - "standard": "^16.0.3" - } -}