Skip to content

Commit

Permalink
Merge pull request #106 from gnosis/browser-compat
Browse files Browse the repository at this point in the history
Make package usable in browser env
  • Loading branch information
jfschwarz authored Feb 3, 2023
2 parents 40c4137 + 0f9fb3e commit d162234
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 97 deletions.
16 changes: 7 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@typescript-eslint/parser": "^5.40.0",
"chai": "^4.3.6",
"debug": "^4.3.4",
"dotenv": "^16.0.3",
"eslint": "^8.25.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
Expand All @@ -67,32 +68,29 @@
"ethereumjs-abi": "^0.6.8",
"ethereumjs-util": "^7.1.5",
"hardhat": "^2.12.0",
"hardhat-change-network": "^0.0.7",
"hardhat-deploy": "^0.11.18",
"husky": "^8.0.1",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.24",
"rimraf": "^3.0.2",
"solc": "^0.8.17",
"solhint": "^3.3.7",
"solhint-plugin-prettier": "^0.0.5",
"solidity-coverage": "^0.8.2",
"ts-node": "^10.9.1",
"typechain": "^8.1.1",
"typescript": "^4.8.4"
"typescript": "^4.8.4",
"yargs": "^17.6.0"
},
"dependencies": {
"@gnosis.pm/mock-contract": "^4.0.0",
"@gnosis.pm/safe-contracts": "1.3.0",
"@openzeppelin/contracts": "^4.3.2",
"@openzeppelin/contracts-upgradeable": "^4.2.0",
"argv": "^0.0.2",
"dotenv": "^16.0.3",
"ethers": "^5.7.1",
"hardhat-change-network": "^0.0.7",
"solc": "^0.8.17",
"yargs": "^17.6.0"
"ethers": "^5.7.1"
},
"peerDependencies": {
"ethers": "^5.7.1",
"hardhat": "^2.12.0"
"ethers": "^5.7.1"
}
}
23 changes: 4 additions & 19 deletions src/factory/deployModuleFactory.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import "hardhat-deploy";
import "@nomiclabs/hardhat-ethers";
import { constants as ethersConstants } from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { constants as ethersConstants, ethers } from "ethers";
import { MasterCopyInitData } from "./contracts";
import { getSingletonFactory } from "./singletonFactory";
import { KnownContracts } from "./types";
Expand All @@ -19,27 +16,15 @@ const FactorySalt = MasterCopyInitData[KnownContracts.FACTORY].salt;
* @returns The address of the deployed Module Proxy Factory, or the zero address if it was already deployed
*/
export const deployModuleFactory = async (
hre: HardhatRuntimeEnvironment
signer: ethers.providers.JsonRpcSigner
): Promise<string> => {
console.log("Deploying the Module Proxy Factory...");
const singletonFactory = await getSingletonFactory(hre);
const singletonFactory = await getSingletonFactory(signer);
console.log(
" Singleton factory used for deployment:",
singletonFactory.address
);

try {
const Factory = await hre.ethers.getContractFactory("ModuleProxyFactory");
if (Factory.bytecode !== FactoryInitCode) {
console.warn(
" The compiled Module Proxy Factory (from src/factory/contracts.ts) is outdated, it does " +
"not match the bytecode stored at MasterCopyInitData[KnownContracts.FACTORY].initCode"
);
}
} catch (e) {
// This is expected when the zodiac package is imported as a package.
}

const targetAddress = await singletonFactory.callStatic.deploy(
FactoryInitCode,
FactorySalt
Expand All @@ -65,7 +50,7 @@ export const deployModuleFactory = async (
result.transactionHash
);

if ((await hre.ethers.provider.getCode(targetAddress)).length < 3) {
if ((await signer.provider.getCode(targetAddress)).length < 3) {
// will return "0x" when there is no code
throw new Error(
" \x1B[31m✘ Deployment unsuccessful: No code at target address.\x1B[0m"
Expand Down
65 changes: 27 additions & 38 deletions src/factory/mastercopyDeployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import {
BytesLike,
ContractFactory,
constants as ethersConstants,
ethers,
} from "ethers";
import { keccak256, getCreate2Address, getAddress } from "ethers/lib/utils";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import assert from "node:assert";
import { getSingletonFactory } from "./singletonFactory";

const { AddressZero } = ethersConstants;
Expand All @@ -20,7 +19,7 @@ const { AddressZero } = ethersConstants;
* @returns The address of the deployed module mastercopy or the zero address if it was already deployed
*/
export const deployMastercopy = async (
hre: HardhatRuntimeEnvironment,
signer: ethers.providers.JsonRpcSigner,
mastercopyContractFactory: ContractFactory,
args: Array<any>,
salt: string
Expand All @@ -30,7 +29,7 @@ export const deployMastercopy = async (
if (!deploymentTx.data) {
throw new Error("Unable to create the deployment data (no init code).");
}
return await deployMastercopyWithInitData(hre, deploymentTx.data, salt);
return await deployMastercopyWithInitData(signer, deploymentTx.data, salt);
};

/**
Expand All @@ -45,13 +44,13 @@ export const deployMastercopy = async (
* }
*/
export const computeTargetAddress = async (
hre: HardhatRuntimeEnvironment,
signer: ethers.providers.JsonRpcSigner,
mastercopyContractFactory: ContractFactory,
args: Array<any>,
salt: string
): Promise<{ address: string; isDeployed: boolean }> => {
const deploymentTx = mastercopyContractFactory.getDeployTransaction(...args);
const singletonFactory = await getSingletonFactory(hre);
const singletonFactory = await getSingletonFactory(signer);

if (!deploymentTx.data) {
throw new Error("Unable to create the deployment data (no init code).");
Expand All @@ -73,10 +72,11 @@ export const computeTargetAddress = async (
);

// Sanity check
assert(
computedAddress === targetAddress || targetAddress === AddressZero,
"The computed address does not match the target address and the target address is not 0x0."
);
if (computedAddress !== targetAddress && targetAddress !== AddressZero) {
throw new Error(
"The computed address does not match the target address and the target address is not 0x0."
);
}

return {
address: computedAddress,
Expand All @@ -85,11 +85,11 @@ export const computeTargetAddress = async (
};

export const deployMastercopyWithInitData = async (
hre: HardhatRuntimeEnvironment,
signer: ethers.providers.JsonRpcSigner,
initCode: BytesLike,
salt: string
): Promise<string> => {
const singletonFactory = await getSingletonFactory(hre);
const singletonFactory = await getSingletonFactory(signer);

// throws if this for some reason is not a valid address
const targetAddress = getAddress(
Expand All @@ -110,44 +110,33 @@ export const deployMastercopyWithInitData = async (
}

// Sanity check
assert.equal(
targetAddress,
computedTargetAddress,
"The computed address does not match the target address."
);
if (targetAddress !== computedTargetAddress) {
throw new Error("The computed address does not match the target address.");
}

let deployData;
switch (hre.network.name) {
let gasLimit;
switch (signer.provider.network.name) {
case "optimism":
deployData = await singletonFactory.deploy(initCode, salt, {
gasLimit: 6000000,
});
gasLimit = 6000000;
break;
case "arbitrum":
deployData = await singletonFactory.deploy(initCode, salt, {
gasLimit: 200000000,
});
gasLimit = 200000000;
break;
case "avalanche":
deployData = await singletonFactory.deploy(initCode, salt, {
gasLimit: 8000000,
});
gasLimit = 8000000;
break;
case "mumbai":
deployData = await singletonFactory.deploy(initCode, salt, {
gasLimit: 8000000,
});
gasLimit = 8000000;
break;
default:
deployData = await singletonFactory.deploy(initCode, salt, {
gasLimit: 10000000,
});
break;
gasLimit = 10000000;
}
const deployTx = await singletonFactory.deploy(initCode, salt, {
gasLimit,
});
await deployTx.wait();

await deployData.wait();

if ((await hre.ethers.provider.getCode(targetAddress)).length > 2) {
if ((await signer.provider.getCode(targetAddress)).length > 2) {
console.log(
` \x1B[32m✔ Mastercopy deployed to: ${targetAddress} 🎉\x1B[0m `
);
Expand Down
12 changes: 7 additions & 5 deletions src/factory/moduleDeployer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Provider } from "@ethersproject/providers";
import { ethers, Contract, Signer, BigNumber } from "ethers";
import { ABI } from "hardhat-deploy/dist/types";
import { ModuleProxyFactory__factory } from "../../abi-typechain-types";

import {
Expand All @@ -10,6 +10,8 @@ import {
} from "./contracts";
import { KnownContracts } from "./types";

type ABI = any[] | readonly any[];

type TxAndExpectedAddress = {
transaction: {
data: string;
Expand All @@ -36,7 +38,7 @@ export const deployAndSetUpModule = (
types: Array<string>;
values: Array<any>;
},
provider: ethers.providers.JsonRpcProvider,
provider: Provider,
chainId: number,
saltNonce: string
): TxAndExpectedAddress => {
Expand Down Expand Up @@ -73,7 +75,7 @@ export const deployAndSetUpCustomModule = (
types: Array<string>;
values: Array<any>;
},
provider: ethers.providers.JsonRpcProvider,
provider: Provider,
chainId: number,
saltNonce: string
): TxAndExpectedAddress => {
Expand Down Expand Up @@ -163,7 +165,7 @@ export const calculateProxyAddress = (
export const getModuleInstance = <T extends KnownContracts>(
moduleName: T,
moduleAddress: string,
provider: ethers.providers.JsonRpcProvider | Signer
provider: Provider | Signer
) => {
const moduleIsNotSupported =
!Object.keys(ContractFactories).includes(moduleName);
Expand All @@ -178,7 +180,7 @@ export const getModuleInstance = <T extends KnownContracts>(

export const getModuleFactoryAndMasterCopy = <T extends KnownContracts>(
moduleName: T,
provider: ethers.providers.JsonRpcProvider,
provider: Provider,
chainId: SupportedNetworks
) => {
const chainContracts = ContractAddresses[chainId as SupportedNetworks];
Expand Down
26 changes: 10 additions & 16 deletions src/factory/singletonFactory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Contract } from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { Contract, ethers } from "ethers";

const singletonFactoryAbi = [
"function deploy(bytes memory _initCode, bytes32 _salt) public returns (address payable createdContract)",
];
Expand All @@ -14,40 +14,34 @@ const SingletonFactoryAddress = "0xce0042b868300000d44a59004da54a005ffdcf9f";
* @returns Singleton Factory contract
*/
export const getSingletonFactory = async (
hardhat: HardhatRuntimeEnvironment
signer: ethers.providers.JsonRpcSigner
): Promise<Contract> => {
const [deployer] = await hardhat.ethers.getSigners();

const singletonDeployer = "0xBb6e024b9cFFACB947A71991E386681B1Cd1477D";
const singletonFactory = new hardhat.ethers.Contract(
const singletonFactory = new ethers.Contract(
SingletonFactoryAddress,
singletonFactoryAbi,
deployer
signer
);

// check if singleton factory is deployed.
if (
(await hardhat.ethers.provider.getCode(singletonFactory.address)) === "0x"
) {
if ((await signer.provider.getCode(singletonFactory.address)) === "0x") {
console.log(
"Singleton factory is not deployed on this chain. Deploying singleton factory..."
);
// fund the singleton factory deployer account
await deployer.sendTransaction({
await signer.sendTransaction({
to: singletonDeployer,
value: hardhat.ethers.utils.parseEther("0.0247"),
value: ethers.utils.parseEther("0.0247"),
});

// deploy the singleton factory
await (
await hardhat.ethers.provider.sendTransaction(
await signer.provider.sendTransaction(
"0xf9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b83247000822470"
)
).wait();

if (
(await hardhat.ethers.provider.getCode(singletonFactory.address)) == "0x"
) {
if ((await signer.provider.getCode(singletonFactory.address)) == "0x") {
throw Error(
"Singleton factory could not be deployed to correct address, deployment haulted."
);
Expand Down
6 changes: 3 additions & 3 deletions src/tasks/deploy-replay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const deploy = async (

try {
hre.changeNetwork(network);
const [wallet] = await hre.ethers.getSigners();
await hre.ethers.provider.getBalance(wallet.address);
const [deployer] = await hre.ethers.getSigners();
const signer = hre.ethers.provider.getSigner(deployer.address);
for (let index = 0; index < contracts.length; index++) {
const initData: InitData = MasterCopyInitData[contracts[index]];
if (
Expand All @@ -36,7 +36,7 @@ export const deploy = async (
console.log(` \x1B[4m${contracts[index]}\x1B[0m`);
try {
await deployMastercopyWithInitData(
hre,
signer,
initData.initCode,
initData.salt
);
Expand Down
17 changes: 15 additions & 2 deletions src/tasks/singleton-deployment.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { task } from "hardhat/config";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { KnownContracts, MasterCopyInitData } from "../factory";
import { deployModuleFactory } from "../factory/deployModuleFactory";

export const deploy = async (_: null, hre: HardhatRuntimeEnvironment) =>
deployModuleFactory(hre);
const FactoryInitCode = MasterCopyInitData[KnownContracts.FACTORY].initCode;

export const deploy = async (_: null, hre: HardhatRuntimeEnvironment) => {
const Factory = await hre.ethers.getContractFactory("ModuleProxyFactory");
if (Factory.bytecode !== FactoryInitCode) {
console.warn(
" The compiled Module Proxy Factory (from src/factory/contracts.ts) is outdated, it does " +
"not match the bytecode stored at MasterCopyInitData[KnownContracts.FACTORY].initCode"
);
}

const [deployer] = await hre.ethers.getSigners();
await deployModuleFactory(hre.ethers.provider.getSigner(deployer.address));
};

task(
"singleton-deployment",
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1536,11 +1536,6 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==

argv@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab"
integrity sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==

arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
Expand Down

0 comments on commit d162234

Please sign in to comment.