diff --git a/packages/hardhat/contracts/Factory.sol b/packages/hardhat/contracts/Factory.sol new file mode 100644 index 0000000..b1a9f7b --- /dev/null +++ b/packages/hardhat/contracts/Factory.sol @@ -0,0 +1,29 @@ +//SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import "@openzeppelin/contracts/proxy/Clones.sol"; + +contract Factory { + + address public immutable implementation; + address[] public cloneList; + + constructor (address _implementation) public { + implementation = _implementation; + } + + function cloneContract () public returns(address) { + address cloneAddress = Clones.clone(implementation); + cloneList.push(cloneAddress); + return cloneAddress; + } + + function readCloneList() public view returns (address[] memory) { + address[] memory result = new address[](cloneList.length); + for (uint256 i = 0; i < cloneList.length; i++){ + result[i] = cloneList[i]; + } + return result; + } + +} diff --git a/packages/hardhat/deploy/00_deploy_your_contract.ts b/packages/hardhat/deploy/00_deploy_your_contract.ts index 418b912..5cd0843 100644 --- a/packages/hardhat/deploy/00_deploy_your_contract.ts +++ b/packages/hardhat/deploy/00_deploy_your_contract.ts @@ -32,7 +32,14 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn }); // Get the deployed contract - // const yourContract = await hre.ethers.getContract("YourContract", deployer); + const yourContract = await hre.ethers.getContract("YourContract", deployer); + + await deploy("Factory", { + from: deployer, + args: [yourContract.address], + log: true, + autoMine: true, + }); }; export default deployYourContract; diff --git a/packages/nextjs/components/scaffold-eth/Contract/ClonesDropdown.tsx b/packages/nextjs/components/scaffold-eth/Contract/ClonesDropdown.tsx new file mode 100644 index 0000000..731aeab --- /dev/null +++ b/packages/nextjs/components/scaffold-eth/Contract/ClonesDropdown.tsx @@ -0,0 +1,26 @@ +import { ChevronDownIcon } from "@heroicons/react/24/outline"; + +//import { useOutsideClick } from "~~/hooks/scaffold-eth"; + +export const ClonesDropdown = () => { + //const [addressCopied, setAddressCopied] = useState(false); + + //const [selectingNetwork, setSelectingNetwork] = useState(false); + + return ( + <> +
+ + Clones List + + + +
+ + ); +}; diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 008d4eb..4d0a308 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -4,6 +4,227 @@ */ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; -const deployedContracts = {} as const; +const deployedContracts = { + 31337: { + Factory: { + address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + abi: [ + { + inputs: [ + { + internalType: "address", + name: "_implementation", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "cloneContract", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "cloneList", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "implementation", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "readCloneList", + outputs: [ + { + internalType: "address[]", + name: "", + type: "address[]", + }, + ], + stateMutability: "view", + type: "function", + }, + ], + inheritedFunctions: {}, + }, + YourContract: { + address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + abi: [ + { + inputs: [ + { + internalType: "address", + name: "_owner", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "greetingSetter", + type: "address", + }, + { + indexed: false, + internalType: "string", + name: "newGreeting", + type: "string", + }, + { + indexed: false, + internalType: "bool", + name: "premium", + type: "bool", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "GreetingChange", + type: "event", + }, + { + inputs: [], + name: "greeting", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "premium", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "_newGreeting", + type: "string", + }, + ], + name: "setGreeting", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "totalCounter", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "userGreetingCounter", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + stateMutability: "payable", + type: "receive", + }, + ], + inheritedFunctions: {}, + }, + }, +} as const; export default deployedContracts satisfies GenericContractsDeclaration; diff --git a/packages/nextjs/pages/debug.tsx b/packages/nextjs/pages/debug.tsx index 02bdd4a..9ae65b1 100644 --- a/packages/nextjs/pages/debug.tsx +++ b/packages/nextjs/pages/debug.tsx @@ -3,11 +3,18 @@ import type { NextPage } from "next"; import { useLocalStorage } from "usehooks-ts"; import { MetaHeader } from "~~/components/MetaHeader"; import { ContractUI } from "~~/components/scaffold-eth"; +import { ClonesDropdown } from "~~/components/scaffold-eth/Contract/ClonesDropdown"; import { ContractName } from "~~/utils/scaffold-eth/contract"; import { getContractNames } from "~~/utils/scaffold-eth/contractNames"; +//import { useDeployedContractInfo } from "~~/hooks/scaffold-eth"; +//import { useContractRead } from "wagmi"; + const selectedContractStorageKey = "scaffoldEth2.selectedContract"; const contractNames = getContractNames(); +console.log(contractNames); + +// Read from factory, readCloneList const Debug: NextPage = () => { const [selectedContract, setSelectedContract] = useLocalStorage( @@ -45,6 +52,7 @@ const Debug: NextPage = () => { {contractName} ))} + )} {contractNames.map(contractName => (