From 00d1335cea211a5606321ccf3f2146f0b259043d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Tue, 30 Jul 2024 13:03:16 +0200 Subject: [PATCH] Use zodiac-core --- contracts/MyModule.sol | 2 +- deploy/01_mastercopy_module.ts | 19 ++++++++--- deploy/03_proxy_module.ts | 31 +++++++++--------- deploy/eip1193.ts | 21 ++++++++++++ factories/eip2470.ts | 56 ------------------------------- factories/moduleProxyFactory.ts | 58 --------------------------------- package.json | 4 +-- yarn.lock | 41 +++++++++++++---------- 8 files changed, 77 insertions(+), 155 deletions(-) create mode 100644 deploy/eip1193.ts delete mode 100644 factories/eip2470.ts delete mode 100644 factories/moduleProxyFactory.ts diff --git a/contracts/MyModule.sol b/contracts/MyModule.sol index af4beed..c07ceed 100644 --- a/contracts/MyModule.sol +++ b/contracts/MyModule.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; -import "@gnosis.pm/zodiac/contracts/core/Module.sol"; +import "zodiac-core/contracts/core/Module.sol"; contract MyModule is Module { address public button; diff --git a/deploy/01_mastercopy_module.ts b/deploy/01_mastercopy_module.ts index 51316c3..4ef131d 100644 --- a/deploy/01_mastercopy_module.ts +++ b/deploy/01_mastercopy_module.ts @@ -1,8 +1,9 @@ import { ZeroHash } from "ethers" import { DeployFunction } from "hardhat-deploy/types" import { HardhatRuntimeEnvironment } from "hardhat/types" -import { createFactory, deployViaFactory } from "../factories/eip2470" +import { deployFactories, deploySingleton } from "zodiac-core" +import createAdapter from "./eip1193" import MODULE_CONTRACT_ARTIFACT from "../artifacts/contracts/MyModule.sol/MyModule.json" const FirstAddress = "0x0000000000000000000000000000000000000001" @@ -10,14 +11,22 @@ const FirstAddress = "0x0000000000000000000000000000000000000001" const deploy: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { getNamedAccounts, ethers } = hre const { deployer: deployerAddress } = await getNamedAccounts() - const deployer = await ethers.getSigner(deployerAddress) - await createFactory(deployer) + const provider = createAdapter({ + provider: hre.network.provider, + signer: await ethers.getSigner(deployerAddress), + }) + + await deployFactories({ provider }) const MyModule = await ethers.getContractFactory("MyModule") - const tx = await MyModule.getDeployTransaction(FirstAddress, FirstAddress) - const mastercopy = await deployViaFactory({ bytecode: tx.data, salt: ZeroHash }, deployer) + const { address: mastercopy } = await deploySingleton({ + bytecode: MyModule.bytecode, + constructorArgs: { types: ["address", "address"], values: [FirstAddress, FirstAddress] }, + salt: ZeroHash, + provider, + }) hre.deployments.save("MyModuleMastercopy", { abi: MODULE_CONTRACT_ARTIFACT.abi, diff --git a/deploy/03_proxy_module.ts b/deploy/03_proxy_module.ts index 3589931..1d00d47 100644 --- a/deploy/03_proxy_module.ts +++ b/deploy/03_proxy_module.ts @@ -1,16 +1,15 @@ -import { ZeroHash } from "ethers" import { DeployFunction } from "hardhat-deploy/types" import { HardhatRuntimeEnvironment } from "hardhat/types" -import { createFactory, deployModAsProxy } from "../factories/moduleProxyFactory" - import MODULE_CONTRACT_ARTIFACT from "../artifacts/contracts/MyModule.sol/MyModule.json" +import createAdapter from "./eip1193" +import { deployFactories, deployProxy } from "zodiac-core" const deploy: DeployFunction = async function ({ deployments, getNamedAccounts, ethers, - getChainId, + network, }: HardhatRuntimeEnvironment) { console.log("Deploying MyModule Proxy") const { deployer: deployerAddress } = await getNamedAccounts() @@ -18,9 +17,13 @@ const deploy: DeployFunction = async function ({ const buttonDeployment = await deployments.get("Button") const testAvatarDeployment = await deployments.get("TestAvatar") - const myModuleMastercopyDeployment = await deployments.get("MyModuleMastercopy") + const provider = createAdapter({ + provider: network.provider, + signer: await ethers.getSigner(deployerAddress), + }) + /// const chainId = await getChainId() // const network: SupportedNetworks = Number(chainId) // if ((await ethers.provider.getCode(ContractAddresses[network][KnownContracts.FACTORY])) === "0x") { @@ -32,19 +35,17 @@ const deploy: DeployFunction = async function ({ console.log("buttonDeployment.address:", buttonDeployment.address) // Deploys the ModuleFactory (and the Singleton factory) if it is not already deployed - const factory = await createFactory(deployer) - const { transaction } = await deployModAsProxy( - factory, - myModuleMastercopyDeployment.address, - { + await deployFactories({ provider }) + const { address: myModuleProxyAddress } = await deployProxy({ + mastercopy: myModuleMastercopyDeployment.address, + setupArgs: { values: [testAvatarDeployment.address, buttonDeployment.address], types: ["address", "address"], }, - ZeroHash, - ) - const deploymentTransaction = await deployer.sendTransaction(transaction) - const receipt = (await deploymentTransaction.wait())! - const myModuleProxyAddress = receipt.logs[1].address + saltNonce: 0, + provider, + }) + console.log("MyModule minimal proxy deployed to:", myModuleProxyAddress) deployments.save("MyModuleProxy", { diff --git a/deploy/eip1193.ts b/deploy/eip1193.ts new file mode 100644 index 0000000..64daa08 --- /dev/null +++ b/deploy/eip1193.ts @@ -0,0 +1,21 @@ +import { Signer } from "ethers" +import { EIP1193Provider } from "zodiac-core" + +export default function createAdapter({ + provider, + signer, +}: { + provider: EIP1193Provider + signer: Signer +}): EIP1193Provider { + return { + request: async ({ method, params }) => { + if (method == "eth_sendTransaction") { + const { hash } = await signer.sendTransaction((params as any[])[0]) + return hash + } + + return provider.request({ method, params }) + }, + } +} diff --git a/factories/eip2470.ts b/factories/eip2470.ts deleted file mode 100644 index 7f39c7d..0000000 --- a/factories/eip2470.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" - -import { Contract, Signer, ZeroHash, getCreate2Address, keccak256, parseEther } from "ethers" - -export async function deployViaFactory( - { bytecode, salt = ZeroHash }: { bytecode: string; salt?: string }, - deployer: Signer, - displayName?: string, -): Promise { - const provider = deployer.provider! - - const factory = new Contract( - factoryInfo.address, - ["function deploy(bytes memory _initCode, bytes32 _salt) public returns (address payable createdContract)"], - deployer, - ) - - const computedAddress = getCreate2Address(factoryInfo.address, salt, keccak256(bytecode)) - - if ((await provider.getCode(computedAddress)) == "0x") { - const receipt = await (await factory.deploy(bytecode, salt, { gasLimit: 10000000 })).wait() - - if (receipt?.status != 1) { - throw new Error(`Couldn't deploy ${displayName || "contract"} eip-2470 factory`) - } - } - - return computedAddress -} - -const factoryInfo = { - address: "0xce0042b868300000d44a59004da54a005ffdcf9f", - deployer: "0xBb6e024b9cFFACB947A71991E386681B1Cd1477D", - transaction: - "0xf9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b83247000822470", -} - -/** - * If it is not deployed on the network, deploys the singleton factory contract - * - * https://eips.ethereum.org/EIPS/eip-2470 - */ -export async function createFactory(signer: SignerWithAddress) { - const { address, deployer } = factoryInfo - - // fund the singleton factory deployer account - await signer.sendTransaction({ - to: deployer, - value: parseEther("0.0247"), - }) - - // deploy the singleton factory - await signer.provider.broadcastTransaction(factoryInfo.transaction) - - return address -} diff --git a/factories/moduleProxyFactory.ts b/factories/moduleProxyFactory.ts deleted file mode 100644 index 840745f..0000000 --- a/factories/moduleProxyFactory.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { AbiCoder, getCreate2Address, keccak256, solidityPackedKeccak256 } from "ethers" -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" - -import { deployViaFactory } from "./eip2470" - -import { IModuleProxyFactory__factory, Module__factory } from "../typechain-types" - -export function deployModAsProxy( - factory: string, - mastercopy: string, - setupArgs: { - types: Array - values: Array - }, - saltNonce: string, -) { - function predictProxyAddress(initData: string): string { - const mastercopyAddressFormatted = mastercopy.toLowerCase().replace(/^0x/, "") - const byteCode = - "0x602d8060093d393df3363d3d373d3d3d363d73" + mastercopyAddressFormatted + "5af43d82803e903d91602b57fd5bf3" - - const salt = solidityPackedKeccak256( - ["bytes32", "uint256"], - [solidityPackedKeccak256(["bytes"], [initData]), saltNonce], - ) - - return getCreate2Address(factory, salt, keccak256(byteCode)) - } - - const abiCoder = new AbiCoder() - - const encodedInitParams = abiCoder.encode(setupArgs.types, setupArgs.values) - const moduleSetupData = Module__factory.createInterface().encodeFunctionData("setUp", [encodedInitParams]) - - const deployData = IModuleProxyFactory__factory.createInterface().encodeFunctionData("deployModule", [ - mastercopy, - moduleSetupData, - saltNonce, - ]) - const transaction = { - data: deployData, - to: factory, - value: 0, - } - return { - transaction, - expectedModuleAddress: predictProxyAddress(moduleSetupData), - } -} - -export async function createFactory(signer: SignerWithAddress) { - const address = await deployViaFactory({ bytecode: creationBytecode, salt }, signer) - return address -} - -const creationBytecode = - "0x608060405234801561001057600080fd5b506107fe806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f1ab873c14610030575b600080fd5b61004a600480360381019061004591906103b6565b610060565b6040516100579190610564565b60405180910390f35b600061009b848480519060200120846040516020016100809291906104f0565b604051602081830303815290604052805190602001206101a3565b905060008173ffffffffffffffffffffffffffffffffffffffff16846040516100c4919061051c565b6000604051808303816000865af19150503d8060008114610101576040519150601f19603f3d011682016040523d82523d6000602084013e610106565b606091505b5050905080610141576040517f7dabd39900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f2150ada912bf189ed721c44211199e270903fc88008c2a1e1e889ef30fe67c5f60405160405180910390a3509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561021657826040517fc80b883400000000000000000000000000000000000000000000000000000000815260040161020d9190610564565b60405180910390fd5b60008373ffffffffffffffffffffffffffffffffffffffff163b141561027357826040517ffff2336100000000000000000000000000000000000000000000000000000000815260040161026a9190610564565b60405180910390fd5b6000836040516020016102869190610533565b6040516020818303038152906040529050828151602083016000f59150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561031557816040517fdc7a7a2400000000000000000000000000000000000000000000000000000000815260040161030c9190610564565b60405180910390fd5b5092915050565b600061032f61032a846105a4565b61057f565b90508281526020810184848401111561034b5761034a61071b565b5b61035684828561063c565b509392505050565b60008135905061036d8161079a565b92915050565b600082601f83011261038857610387610716565b5b813561039884826020860161031c565b91505092915050565b6000813590506103b0816107b1565b92915050565b6000806000606084860312156103cf576103ce610725565b5b60006103dd8682870161035e565b935050602084013567ffffffffffffffff8111156103fe576103fd610720565b5b61040a86828701610373565b925050604061041b868287016103a1565b9150509250925092565b61042e816105f6565b82525050565b610445610440826105f6565b6106af565b82525050565b61045c61045782610608565b6106c1565b82525050565b600061046d826105d5565b61047781856105e0565b935061048781856020860161064b565b80840191505092915050565b60006104a0600f836105eb565b91506104ab82610748565b600f82019050919050565b60006104c36013836105eb565b91506104ce82610771565b601382019050919050565b6104ea6104e582610632565b6106dd565b82525050565b60006104fc828561044b565b60208201915061050c82846104d9565b6020820191508190509392505050565b60006105288284610462565b915081905092915050565b600061053e826104b6565b915061054a8284610434565b60148201915061055982610493565b915081905092915050565b60006020820190506105796000830184610425565b92915050565b600061058961059a565b9050610595828261067e565b919050565b6000604051905090565b600067ffffffffffffffff8211156105bf576105be6106e7565b5b6105c88261072a565b9050602081019050919050565b600081519050919050565b600081905092915050565b600081905092915050565b600061060182610612565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b8381101561066957808201518184015260208101905061064e565b83811115610678576000848401525b50505050565b6106878261072a565b810181811067ffffffffffffffff821117156106a6576106a56106e7565b5b80604052505050565b60006106ba826106cb565b9050919050565b6000819050919050565b60006106d68261073b565b9050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000600082015250565b7f602d8060093d393df3363d3d373d3d3d363d7300000000000000000000000000600082015250565b6107a3816105f6565b81146107ae57600080fd5b50565b6107ba81610632565b81146107c557600080fd5b5056fea264697066735822122068cfe87f5242e3087c0b46218f6f8e6b1a5960ed6b562cb03d27ec764881916064736f6c63430008060033" -const salt = "0xb8db55294bb8fea809aee38a26aad7ce1ab40d019486aa51af3a3de7e7434530" diff --git a/package.json b/package.json index dc3a9cd..7ccd427 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "homepage": "https://github.com/gnosis/zodiac-mod-starter-kit", "devDependencies": { "@gnosis.pm/safe-contracts": "^1.3.0", - "@gnosis.pm/zodiac": "4.0.3", "@nomicfoundation/hardhat-chai-matchers": "^2.0.7", "@nomicfoundation/hardhat-ethers": "3.0.6", "@nomicfoundation/hardhat-network-helpers": "^1.0.7", @@ -59,6 +58,7 @@ "solidity-coverage": "^0.8.4", "ts-node": "^10.9.1", "typechain": "^8.3.2", - "typescript": "^5.2.2" + "typescript": "^5.2.2", + "zodiac-core": "file:../zodiac-core" } } diff --git a/yarn.lock b/yarn.lock index 18eb3da..602802f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -590,27 +590,11 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== -"@gnosis.pm/mock-contract@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@gnosis.pm/mock-contract/-/mock-contract-4.0.0.tgz#eaf500fddcab81b5f6c22280a7b22ff891dd6f87" - integrity sha512-SkRq2KwPx6vo0LAjSc8JhgQstrQFXRyn2yqquIfub7r2WHi5nUbF8beeSSXsd36hvBcQxQfmOIYNYRpj9JOhrQ== - "@gnosis.pm/safe-contracts@1.3.0", "@gnosis.pm/safe-contracts@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.3.0.tgz#316741a7690d8751a1f701538cfc9ec80866eedc" integrity sha512-1p+1HwGvxGUVzVkFjNzglwHrLNA67U/axP0Ct85FzzH8yhGJb4t9jDjPYocVMzLorDoWAfKicGy1akPY9jXRVw== -"@gnosis.pm/zodiac@4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@gnosis.pm/zodiac/-/zodiac-4.0.3.tgz#3323f496cda279e2a68ca2bf726ad840388e8229" - integrity sha512-yliHytBRlb4wNkeiYsaaAvYZC5VwiUBVfJ+HLEmjnWPG2EHB5tvAOUboDU7XvSQ4GUJAz8h2YUrph0XkH+/xfA== - dependencies: - "@gnosis.pm/mock-contract" "^4.0.0" - "@gnosis.pm/safe-contracts" "1.3.0" - "@openzeppelin/contracts" "^5.0.0" - "@openzeppelin/contracts-upgradeable" "^5.0.0" - ethers "^6.9.2" - "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -896,12 +880,12 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" -"@openzeppelin/contracts-upgradeable@^5.0.0": +"@openzeppelin/contracts-upgradeable@5.0.2", "@openzeppelin/contracts-upgradeable@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105" integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ== -"@openzeppelin/contracts@^5.0.0": +"@openzeppelin/contracts@5.0.2", "@openzeppelin/contracts@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210" integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA== @@ -2927,6 +2911,19 @@ ethers@^5.7.0: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +ethers@^6.13.2: + version "6.13.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.2.tgz#4b67d4b49e69b59893931a032560999e5e4419fe" + integrity sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.17.1" + ethers@^6.9.2: version "6.13.1" resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.1.tgz#2b9f9c7455cde9d38b30fe6589972eb083652961" @@ -6496,3 +6493,11 @@ zksync-web3@^0.14.3: version "0.14.4" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.4.tgz#0b70a7e1a9d45cc57c0971736079185746d46b1f" integrity sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg== + +"zodiac-core@file:../zodiac-core": + version "4.0.3" + dependencies: + "@gnosis.pm/safe-contracts" "1.3.0" + "@openzeppelin/contracts" "5.0.2" + "@openzeppelin/contracts-upgradeable" "5.0.2" + ethers "^6.13.2"