From cdcb138f7f7301d19f0b0b463c991c871ec28dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 13:52:42 +0200 Subject: [PATCH 01/35] Update README file --- packages/safe-core-sdk/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/safe-core-sdk/README.md b/packages/safe-core-sdk/README.md index 8c04ddae5..701230c50 100644 --- a/packages/safe-core-sdk/README.md +++ b/packages/safe-core-sdk/README.md @@ -153,7 +153,9 @@ The property `contractNetworks` can be added to provide the Safe contract addres ```js const contractNetworks: ContractNetworksConfig = { [chainId]: { - multiSendAddress: '0x' + multiSendAddress: '0x', + safeMasterCopyAddress: '0x', + safeProxyFactoryAddress: '0x' } } const safeSdk = await Safe.create({ ethAdapter, safeAddress, contractNetworks }) @@ -172,7 +174,9 @@ The property `contractNetworks` can be added to provide the Safe contract addres ```js const contractNetworks: ContractNetworksConfig = { [chainId]: { - multiSendAddress: '0x' + multiSendAddress: '0x', + safeMasterCopyAddress: '0x', + safeProxyFactoryAddress: '0x' } } const safeSdk = await Safe.create({ ethAdapter, safeAddress, contractNetworks }) From 2f1bdec8bdee6a1fda326b4611766de0cf23bb9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 15:27:37 +0200 Subject: [PATCH 02/35] Update script that generates typechain files --- .../scripts/generateTypechainFiles.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts index e083ef31e..92dc2d416 100644 --- a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts +++ b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts @@ -16,11 +16,6 @@ const typeChainDirectoryBuildPath = path.join(__dirname, `../${outDirBuild}`) // Will be included in dist/ folder const safeContractsPath = '../../node_modules/@gnosis.pm/safe-contracts/build/contracts' const openZeppelinContractsPath = '../../node_modules/openzeppelin-solidity/build/contracts' -const safeContracts = [ - `${safeContractsPath}/GnosisSafe.json`, - `${safeContractsPath}/GnosisSafeProxyFactory.json`, - `${safeContractsPath}/MultiSend.json`, -].join(' ') // Won't be included in dist/ folder const testContracts = [ `${safeContractsPath}/DailyLimitModule.json`, @@ -38,7 +33,7 @@ execSync(`rimraf ${outDirSrc} ${outDirTests}`, (error) => { // Generate Typechain files function generateTypechainFiles(typechainVersion, outDir, contractList) { - execSync(`typechain --target ${typechainVersion} --out-dir ${outDir}${typechainVersion} ${contractList}`, (error) => { + execSync(`typechain --target ${typechainVersion} --out-dir ${outDir} ${contractList}`, (error) => { if (error) { console.log(error.message) } @@ -65,16 +60,26 @@ function moveTypechainFiles(typechainVersion, inDir, outDir) { }) } +function getSafeDeploymentsContracts(contractVersion) { + return `../../node_modules/@gnosis.pm/safe-deployments/dist/assets/${contractVersion}/*.json` +} + const web3V1 = 'web3-v1' const ethersV5 = 'ethers-v5' // Src: Web3 V1 types -generateTypechainFiles(web3V1, outDirSrc, safeContracts) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.0.0'`, getSafeDeploymentsContracts('v1.0.0')) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.1.1'`, getSafeDeploymentsContracts('v1.1.1')) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.2.0'`, getSafeDeploymentsContracts('v1.2.0')) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.3.0'`, getSafeDeploymentsContracts('v1.3.0')) moveTypechainFiles(web3V1, typeChainDirectorySrcPath, typeChainDirectoryBuildPath) // Src: Ethers V5 types -generateTypechainFiles(ethersV5, outDirSrc, safeContracts) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.0.0'`, getSafeDeploymentsContracts('v1.0.0')) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.1.1'`, getSafeDeploymentsContracts('v1.1.1')) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.2.0'`, getSafeDeploymentsContracts('v1.2.0')) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.3.0'`, getSafeDeploymentsContracts('v1.3.0')) moveTypechainFiles(ethersV5, typeChainDirectorySrcPath, typeChainDirectoryBuildPath) // Tests: Ethers V5 types -generateTypechainFiles(ethersV5, outDirTests, testContracts) +generateTypechainFiles(ethersV5, `${outDirTests}${ethersV5}`, testContracts) From 3201af5cd8aed762d6b86ae82403871d6261c87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 15:29:26 +0200 Subject: [PATCH 03/35] Update Safe contracts with new generated types --- packages/safe-core-sdk/package.json | 3 ++- .../src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts | 2 +- .../src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts | 2 +- .../GnosisSafeProxyFactoryEthersV5Contract.ts | 4 ++-- .../GnosisSafeProxyFactoryWeb3Contract.ts | 4 ++-- .../src/contracts/MultiSend/MultiSendEthersV5Contract.ts | 2 +- .../src/contracts/MultiSend/MultiSendWeb3Contract.ts | 2 +- yarn.lock | 5 +++++ 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/safe-core-sdk/package.json b/packages/safe-core-sdk/package.json index 817e09050..3e56d470c 100644 --- a/packages/safe-core-sdk/package.json +++ b/packages/safe-core-sdk/package.json @@ -18,7 +18,7 @@ "test:ganache:ethers": "export TEST_NETWORK=ganache && export ETH_LIB=ethers && hardhat --network localhost deploy && nyc hardhat --network localhost test", "test:hardhat:web3": "export TEST_NETWORK=hardhat && export ETH_LIB=web3 && hardhat deploy && nyc hardhat test", "test:hardhat:ethers": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && hardhat deploy && nyc hardhat test", - "test": "yarn test:hardhat:web3 && yarn test:hardhat:ethers", + "test": "yarn test:hardhat:ethers", "coverage": "nyc report --reporter=text-lcov | coveralls", "format": "prettier --write \"{src,tests,hardhat}/**/*.ts\"", "lint": "tslint -p tsconfig.json" @@ -87,6 +87,7 @@ }, "dependencies": { "@gnosis.pm/safe-core-sdk-types": "^0.1.1", + "@gnosis.pm/safe-deployments": "^1.4.0", "ethereumjs-util": "^7.0.10" } } diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts index a1420f13c..86eb678cf 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts @@ -1,7 +1,7 @@ import { BigNumber } from '@ethersproject/bignumber' import { ContractTransaction } from '@ethersproject/contracts' import { SafeTransaction, SafeTransactionData } from '@gnosis.pm/safe-core-sdk-types' -import { GnosisSafe, GnosisSafeInterface } from '../../../typechain/src/ethers-v5/GnosisSafe' +import { GnosisSafe, GnosisSafeInterface } from '../../../typechain/src/ethers-v5/v1.2.0/GnosisSafe' import { EthersTransactionResult, TransactionOptions } from '../../utils/transactions/types' import GnosisSafeContract from './GnosisSafeContract' diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts index 508f56bcb..2d6fe868b 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts @@ -1,7 +1,7 @@ import { BigNumber } from '@ethersproject/bignumber' import { SafeTransaction, SafeTransactionData } from '@gnosis.pm/safe-core-sdk-types' import { PromiEvent, TransactionReceipt } from 'web3-core/types' -import { GnosisSafe } from '../../../typechain/src/web3-v1/GnosisSafe' +import { GnosisSafe } from '../../../typechain/src/web3-v1/v1.2.0/gnosis_safe' import { TransactionOptions, Web3TransactionResult } from '../../utils/transactions/types' import GnosisSafeContract from './GnosisSafeContract' diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts index 1d059640f..9785bba8f 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts @@ -1,9 +1,9 @@ import { ContractTransaction, Event } from '@ethersproject/contracts' -import { GnosisSafeProxyFactory } from '../../../typechain/src/ethers-v5/GnosisSafeProxyFactory' +import { ProxyFactory } from '../../../typechain/src/ethers-v5/v1.1.1/ProxyFactory' import GnosisSafeProxyFactoryContract, { CreateProxyProps } from './GnosisSafeProxyFactoryContract' class GnosisSafeProxyFactoryEthersV5Contract implements GnosisSafeProxyFactoryContract { - constructor(public contract: GnosisSafeProxyFactory) {} + constructor(public contract: ProxyFactory) {} getAddress(): string { return this.contract.address diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts index 0cc0a2584..20f8cde1a 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts @@ -1,9 +1,9 @@ import { PromiEvent, TransactionReceipt } from 'web3-core/types' -import { GnosisSafeProxyFactory } from '../../../typechain/src/web3-v1/GnosisSafeProxyFactory' +import { ProxyFactory } from '../../../typechain/src/web3-v1/v1.1.1/proxy_factory' import GnosisSafeProxyFactoryContract, { CreateProxyProps } from './GnosisSafeProxyFactoryContract' class GnosisSafeProxyFactoryWeb3Contract implements GnosisSafeProxyFactoryContract { - constructor(public contract: GnosisSafeProxyFactory) {} + constructor(public contract: ProxyFactory) {} getAddress(): string { return this.contract.options.address diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts index 8ccf3aec9..c0be63f85 100644 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts @@ -1,4 +1,4 @@ -import { MultiSend, MultiSendInterface } from '../../../typechain/src/ethers-v5/MultiSend' +import { MultiSend, MultiSendInterface } from '../../../typechain/src/ethers-v5/v1.1.1/MultiSend' import MultiSendContract from './MultiSendContract' class MultiSendEthersV5Contract implements MultiSendContract { diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts index 0f3a10410..6b4a14aa7 100644 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts @@ -1,4 +1,4 @@ -import { MultiSend } from '../../../typechain/src/web3-v1/MultiSend' +import { MultiSend } from '../../../typechain/src/web3-v1/v1.1.1/multi_send' import MultiSendContract from './MultiSendContract' class MultiSendWeb3Contract implements MultiSendContract { diff --git a/yarn.lock b/yarn.lock index e227bd102..611d68c19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1151,6 +1151,11 @@ resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-deployments/-/safe-deployments-1.1.0.tgz#63133f4576c5d5f2779f61d322e1e449fb701b1c" integrity sha512-eIH4gvBQLEksQXFN2vOG+JZpdSCR+q6uoZD7n8Jx/PF2nIaWVYV1CWo6kbWDwfwzgAQkDddM+8WBjnc84fbB+Q== +"@gnosis.pm/safe-deployments@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-deployments/-/safe-deployments-1.4.0.tgz#d49d3d36cc014ef62306d09c0f4761895a17d7a6" + integrity sha512-q4salJNQ/Gx0DnZJytAFO/U4OwGI6xTGtTJSOZK+C9Fh2NW8sep+YfSunHQvCLcu4b7WgWEBhxnCV6rpyveLHg== + "@graphql-tools/batch-delegate@^6.2.4", "@graphql-tools/batch-delegate@^6.2.6": version "6.2.6" resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-6.2.6.tgz#fbea98dc825f87ef29ea5f3f371912c2a2aa2f2c" From 477b985254c244b9f72eac18e73a4d5cf0da0ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 15:45:11 +0200 Subject: [PATCH 04/35] Remove old contract networks configuration --- .../src/configuration/contracts.ts | 58 ------------------- packages/safe-core-sdk/src/types/index.ts | 14 +++++ 2 files changed, 14 insertions(+), 58 deletions(-) delete mode 100644 packages/safe-core-sdk/src/configuration/contracts.ts diff --git a/packages/safe-core-sdk/src/configuration/contracts.ts b/packages/safe-core-sdk/src/configuration/contracts.ts deleted file mode 100644 index d5e3fbc29..000000000 --- a/packages/safe-core-sdk/src/configuration/contracts.ts +++ /dev/null @@ -1,58 +0,0 @@ -export interface ContractNetworkConfig { - /** multiSendAddress - Address of the MultiSend contract deployed on a specific network */ - multiSendAddress: string - /** safeMasterCopyAddress - Address of the Gnosis Safe Master Copy contract deployed on a specific network */ - safeMasterCopyAddress: string - /** safeProxyFactoryAddress - Address of the Gnosis Safe Proxy Factory contract deployed on a specific network */ - safeProxyFactoryAddress: string -} - -export interface ContractNetworksConfig { - /** id - Network id */ - [id: string]: ContractNetworkConfig -} - -export const defaultContractNetworks: ContractNetworksConfig = { - // mainnet - 1: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - }, - // rinkeby - 4: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - }, - // goerli - 5: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - }, - // kovan - 42: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - }, - // xdai - 100: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - }, - // energy web chain - 246: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - }, - // energy web volta - 73799: { - multiSendAddress: '0x8D29bE29923b68abfDD21e541b9374737B49cdAD', - safeMasterCopyAddress: '0x6851D6fDFAfD08c0295C392436245E5bc78B0185', - safeProxyFactoryAddress: '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B' - } -} diff --git a/packages/safe-core-sdk/src/types/index.ts b/packages/safe-core-sdk/src/types/index.ts index b2e45b434..d75107122 100644 --- a/packages/safe-core-sdk/src/types/index.ts +++ b/packages/safe-core-sdk/src/types/index.ts @@ -24,3 +24,17 @@ export interface AbiItem { type: string gas?: number } + +export interface ContractNetworkConfig { + /** multiSendAddress - Address of the MultiSend contract deployed on a specific network */ + multiSendAddress: string + /** safeMasterCopyAddress - Address of the Gnosis Safe Master Copy contract deployed on a specific network */ + safeMasterCopyAddress: string + /** safeProxyFactoryAddress - Address of the Gnosis Safe Proxy Factory contract deployed on a specific network */ + safeProxyFactoryAddress: string +} + +export interface ContractNetworksConfig { + /** id - Network id */ + [id: string]: ContractNetworkConfig +} From e87d217b634a0d800537f705b039b4b929912eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 15:47:17 +0200 Subject: [PATCH 05/35] Use new contract types in ContractManager and EthAdapters --- packages/safe-core-sdk/src/Safe.ts | 5 +- .../src/ethereumLibs/EthAdapter.ts | 7 +- .../src/ethereumLibs/EthersAdapter.ts | 91 ++++++++++++------ .../src/ethereumLibs/Web3Adapter.ts | 93 ++++++++++++------- packages/safe-core-sdk/src/index.ts | 2 +- .../src/managers/contractManager.ts | 21 ++--- 6 files changed, 137 insertions(+), 82 deletions(-) diff --git a/packages/safe-core-sdk/src/Safe.ts b/packages/safe-core-sdk/src/Safe.ts index 99276beae..52ad4ea4a 100644 --- a/packages/safe-core-sdk/src/Safe.ts +++ b/packages/safe-core-sdk/src/Safe.ts @@ -6,11 +6,11 @@ import { SafeTransaction, SafeTransactionDataPartial } from '@gnosis.pm/safe-core-sdk-types' -import { ContractNetworksConfig } from './configuration/contracts' import EthAdapter from './ethereumLibs/EthAdapter' import ContractManager from './managers/contractManager' import ModuleManager from './managers/moduleManager' import OwnerManager from './managers/ownerManager' +import { ContractNetworksConfig } from './types' import { sameString } from './utils' import { generatePreValidatedSignature, generateSignature } from './utils/signatures' import { estimateGasForTransactionExecution } from './utils/transactions/gas' @@ -75,7 +75,6 @@ class Safe { * Creates an instance of the Safe Core SDK. * @param config - Ethers Safe configuration * @returns The Safe Core SDK instance - * @throws "Safe contracts not found in the current network" * @throws "Safe Proxy contract is not deployed in the current network" * @throws "MultiSend contract is not deployed in the current network" */ @@ -89,7 +88,6 @@ class Safe { * Initializes the Safe Core SDK instance. * @param config - Safe configuration * @throws "Signer must be connected to a provider" - * @throws "Safe contracts not found in the current network" * @throws "Safe Proxy contract is not deployed in the current network" * @throws "MultiSend contract is not deployed in the current network" */ @@ -107,7 +105,6 @@ class Safe { /** * Returns a new instance of the Safe Core SDK. * @param config - Connect Safe configuration - * @throws "Safe contracts not found in the current network" * @throws "Safe Proxy contract is not deployed in the current network" * @throws "MultiSend contract is not deployed in the current network" */ diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts index b671e9a9f..6e580d267 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts @@ -23,10 +23,11 @@ interface EthAdapter { getBalance(address: string): Promise getChainId(): Promise getContract(address: string, abi: AbiItem[]): any - getSafeContract(safeAddress: string): Promise - getMultiSendContract(multiSendAddress: string): Promise + getSafeContract(chainId: number, customContractAddress?: string): Promise + getMultiSendContract(chainId: number, customContractAddress?: string): Promise getGnosisSafeProxyFactoryContract( - proxyFactoryAddress: string + chainId: number, + customContractAddress?: string ): Promise getContractCode(address: string): Promise getTransaction(transactionHash: string): Promise diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index 71a4345e9..42266620d 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -3,9 +3,14 @@ import { Signer } from '@ethersproject/abstract-signer' import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' import { Provider } from '@ethersproject/providers' -import { GnosisSafeProxyFactory__factory } from '../../typechain/src/ethers-v5/factories/GnosisSafeProxyFactory__factory' -import { GnosisSafe__factory } from '../../typechain/src/ethers-v5/factories/GnosisSafe__factory' -import { MultiSend__factory } from '../../typechain/src/ethers-v5/factories/MultiSend__factory' +import { + getMultiSendDeployment, + getProxyFactoryDeployment, + getSafeSingletonDeployment +} from '@gnosis.pm/safe-deployments' +import { MultiSend__factory } from '../../typechain/src/ethers-v5/v1.1.1/factories/MultiSend__factory' +import { ProxyFactory__factory } from '../../typechain/src/ethers-v5/v1.1.1/factories/ProxyFactory__factory' +import { GnosisSafe__factory } from '../../typechain/src/ethers-v5/v1.2.0/factories/GnosisSafe__factory' import GnosisSafeEthersV5Contract from '../contracts/GnosisSafe/GnosisSafeEthersV5Contract' import GnosisSafeProxyFactoryEthersV5Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract' import MultiSendEthersV5Contract from '../contracts/MultiSend/MultiSendEthersV5Contract' @@ -56,41 +61,67 @@ class EthersAdapter implements EthAdapter { return (await this.#provider.getNetwork()).chainId } - async getSafeContract(safeAddress: string): Promise { - const safeContractCode = await this.getContractCode(safeAddress) - if (safeContractCode === '0x') { + async getSafeContract(chainId: number, customContractAddress?: string): Promise { + let contractAddress: string | undefined + if (customContractAddress) { + contractAddress = customContractAddress + } else { + const safeSingletonDeployment = getSafeSingletonDeployment({ + network: chainId.toString(), + released: true + }) + contractAddress = + safeSingletonDeployment?.networkAddresses[chainId] ?? + safeSingletonDeployment?.defaultAddress + } + if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { throw new Error('Safe Proxy contract is not deployed in the current network') } - const safeContract = GnosisSafe__factory.connect(safeAddress, this.#signer) - const wrapperSafeContract = new GnosisSafeEthersV5Contract(safeContract) - return wrapperSafeContract - } - - async getMultiSendContract(multiSendAddress: string): Promise { - const multiSendContractCode = await this.getContractCode(multiSendAddress) - if (multiSendContractCode === '0x') { - throw new Error('MultiSend contract is not deployed in the current network') + const safeContract = GnosisSafe__factory.connect(contractAddress, this.#signer) + return new GnosisSafeEthersV5Contract(safeContract) + } + + async getMultiSendContract(chainId: number, customContractAddress?: string): Promise { + let contractAddress: string | undefined + if (customContractAddress) { + contractAddress = customContractAddress + } else { + const multiSendDeployment = getMultiSendDeployment({ + network: chainId.toString(), + released: true + }) + contractAddress = + multiSendDeployment?.networkAddresses[chainId] ?? + multiSendDeployment?.defaultAddress } - const multiSendContract = MultiSend__factory.connect(multiSendAddress, this.#signer) - const wrappedMultiSendContract = new MultiSendEthersV5Contract(multiSendContract) - return wrappedMultiSendContract + if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { + throw new Error('Safe Proxy contract is not deployed in the current network') + } + const multiSendContract = MultiSend__factory.connect(contractAddress, this.#signer) + return new MultiSendEthersV5Contract(multiSendContract) } async getGnosisSafeProxyFactoryContract( - proxyFactoryAddress: string + chainId: number, + customContractAddress?: string ): Promise { - const proxyFactoryContractCode = await this.getContractCode(proxyFactoryAddress) - if (proxyFactoryContractCode === '0x') { - throw new Error('Safe Proxy Factory contract is not deployed in the current network') + let contractAddress: string | undefined + if (customContractAddress) { + contractAddress = customContractAddress + } else { + const proxyFactoryDeployment = getProxyFactoryDeployment({ + network: chainId.toString(), + released: true + }) + contractAddress = + proxyFactoryDeployment?.networkAddresses[chainId] ?? + proxyFactoryDeployment?.defaultAddress + } + if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { + throw new Error('Safe Proxy contract is not deployed in the current network') } - const proxyFactoryContract = GnosisSafeProxyFactory__factory.connect( - proxyFactoryAddress, - this.#signer - ) - const wrappedProxyFactoryContract = new GnosisSafeProxyFactoryEthersV5Contract( - proxyFactoryContract - ) - return wrappedProxyFactoryContract + const proxyFactoryContract = ProxyFactory__factory.connect(contractAddress, this.#signer) + return new GnosisSafeProxyFactoryEthersV5Contract(proxyFactoryContract) } getContract(address: string, abi: AbiItem[]): Contract { diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index 58f6e09f6..6784fa089 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -1,12 +1,14 @@ import { BigNumber } from '@ethersproject/bignumber' -import { GnosisSafe } from '../../typechain/src/web3-v1/GnosisSafe' -import { GnosisSafeProxyFactory } from '../../typechain/src/web3-v1/GnosisSafeProxyFactory' -import { MultiSend } from '../../typechain/src/web3-v1/MultiSend' +import { + getMultiSendDeployment, + getProxyFactoryDeployment, + getSafeSingletonDeployment +} from '@gnosis.pm/safe-deployments' +import { MultiSend } from '../../typechain/src/web3-v1/v1.1.1/multi_send' +import { ProxyFactory } from '../../typechain/src/web3-v1/v1.1.1/proxy_factory' +import { GnosisSafe } from '../../typechain/src/web3-v1/v1.2.0/gnosis_safe' import GnosisSafeWeb3Contract from '../contracts/GnosisSafe/GnosisSafeWeb3Contract' -import SafeAbiV120 from '../contracts/GnosisSafe/SafeAbiV1-2-0.json' -import GnosisSafeProxyFactoryAbiV120 from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryAbiV1-2-0.json' import GnosisSafeProxyFactoryWeb3Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract' -import MultiSendAbi from '../contracts/MultiSend/MultiSendAbi.json' import MultiSendWeb3Contract from '../contracts/MultiSend/MultiSendWeb3Contract' import { AbiItem } from '../types' import EthAdapter, { EthAdapterTransaction } from './EthAdapter' @@ -42,43 +44,68 @@ class Web3Adapter implements EthAdapter { return this.#web3.eth.getChainId() } - async getContract(address: string, abi: AbiItem[]): Promise { - return new this.#web3.eth.Contract(abi, address) - } - - async getSafeContract(safeAddress: string): Promise { - const safeContractCode = await this.getContractCode(safeAddress) - if (safeContractCode === '0x') { + async getSafeContract(chainId: number, customContractAddress?: string): Promise { + const safeSingletonDeployment = getSafeSingletonDeployment({ + network: chainId.toString(), + released: true + }) + const contractAddress = + customContractAddress ?? + safeSingletonDeployment?.networkAddresses[chainId] ?? + safeSingletonDeployment?.defaultAddress + if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { throw new Error('Safe Proxy contract is not deployed in the current network') } - const safeContract = (await this.getContract(safeAddress, SafeAbiV120)) as GnosisSafe - const wrapperSafeContract = new GnosisSafeWeb3Contract(safeContract) - return wrapperSafeContract + const safeContract = this.getContract( + contractAddress, + safeSingletonDeployment?.abi as AbiItem[] + ) as GnosisSafe + return new GnosisSafeWeb3Contract(safeContract) } - async getMultiSendContract(multiSendAddress: string): Promise { - const multiSendContractCode = await this.getContractCode(multiSendAddress) - if (multiSendContractCode === '0x') { - throw new Error('MultiSend contract is not deployed in the current network') + async getMultiSendContract(chainId: number, customContractAddress?: string): Promise { + const multiSendDeployment = getMultiSendDeployment({ + network: chainId.toString(), + released: true + }) + const contractAddress = + customContractAddress ?? + multiSendDeployment?.networkAddresses[chainId] ?? + multiSendDeployment?.defaultAddress + if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { + throw new Error('Safe Proxy contract is not deployed in the current network') } - const multiSendContract = (await this.getContract(multiSendAddress, MultiSendAbi)) as MultiSend - const wrappedMultiSendContract = new MultiSendWeb3Contract(multiSendContract) - return wrappedMultiSendContract + const multiSendContract = this.getContract( + contractAddress, + multiSendDeployment?.abi as AbiItem[] + ) as MultiSend + return new MultiSendWeb3Contract(multiSendContract) } async getGnosisSafeProxyFactoryContract( - proxyFactoryAddress: string + chainId: number, + customContractAddress?: string ): Promise { - const proxyFactoryContractCode = await this.getContractCode(proxyFactoryAddress) - if (proxyFactoryContractCode === '0x') { - throw new Error('Safe Proxy Factory contract is not deployed in the current network') + const proxyFactoryDeployment = getProxyFactoryDeployment({ + network: chainId.toString(), + released: true + }) + const contractAddress = + customContractAddress ?? + proxyFactoryDeployment?.networkAddresses[chainId] ?? + proxyFactoryDeployment?.defaultAddress + if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { + throw new Error('Safe Proxy contract is not deployed in the current network') } - const proxyFactoryContract = (await this.getContract( - proxyFactoryAddress, - GnosisSafeProxyFactoryAbiV120 - )) as GnosisSafeProxyFactory - const wrappedProxyFactoryContract = new GnosisSafeProxyFactoryWeb3Contract(proxyFactoryContract) - return wrappedProxyFactoryContract + const proxyFactoryContract = this.getContract( + contractAddress, + proxyFactoryDeployment?.abi as AbiItem[] + ) as ProxyFactory + return new GnosisSafeProxyFactoryWeb3Contract(proxyFactoryContract) + } + + getContract(address: string, abi: AbiItem[]): any { + return new this.#web3.eth.Contract(abi, address) } async getContractCode(address: string): Promise { diff --git a/packages/safe-core-sdk/src/index.ts b/packages/safe-core-sdk/src/index.ts index 65260ceba..4e90233be 100644 --- a/packages/safe-core-sdk/src/index.ts +++ b/packages/safe-core-sdk/src/index.ts @@ -1,4 +1,3 @@ -import { ContractNetworksConfig } from './configuration/contracts' import EthAdapter, { EthAdapterTransaction } from './ethereumLibs/EthAdapter' import EthersAdapter, { EthersAdapterConfig } from './ethereumLibs/EthersAdapter' import Web3Adapter, { Web3AdapterConfig } from './ethereumLibs/Web3Adapter' @@ -14,6 +13,7 @@ import SafeFactory, { SafeDeploymentConfig, SafeFactoryConfig } from './safeFactory' +import { ContractNetworksConfig } from './types' import { SafeTransactionOptionalProps, TransactionOptions, diff --git a/packages/safe-core-sdk/src/managers/contractManager.ts b/packages/safe-core-sdk/src/managers/contractManager.ts index 20bf4e2e8..5afab2b22 100644 --- a/packages/safe-core-sdk/src/managers/contractManager.ts +++ b/packages/safe-core-sdk/src/managers/contractManager.ts @@ -1,10 +1,10 @@ -import { ContractNetworksConfig, defaultContractNetworks } from '../configuration/contracts' import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import MultiSendContract from '../contracts/MultiSend/MultiSendContract' import EthAdapter from '../ethereumLibs/EthAdapter' +import { ContractNetworksConfig } from '../types' class ContractManager { - #contractNetworks!: ContractNetworksConfig + #contractNetworks?: ContractNetworksConfig #safeContract!: GnosisSafeContract #multiSendContract!: MultiSendContract @@ -24,17 +24,16 @@ class ContractManager { contractNetworks?: ContractNetworksConfig ): Promise { const chainId = await ethAdapter.getChainId() - const contractNetworksConfig = { ...defaultContractNetworks, ...contractNetworks } - const contracts = contractNetworksConfig[chainId] - if (!contracts) { - throw new Error('Safe contracts not found in the current network') - } - this.#contractNetworks = contractNetworksConfig - this.#safeContract = await ethAdapter.getSafeContract(safeAddress) - this.#multiSendContract = await ethAdapter.getMultiSendContract(contracts.multiSendAddress) + const customContracts = contractNetworks?.[chainId] + this.#contractNetworks = contractNetworks + this.#safeContract = await ethAdapter.getSafeContract(chainId, safeAddress) + this.#multiSendContract = await ethAdapter.getMultiSendContract( + chainId, + customContracts?.multiSendAddress + ) } - get contractNetworks(): ContractNetworksConfig { + get contractNetworks(): ContractNetworksConfig | undefined { return this.#contractNetworks } From 535f35481ba51961b67b8e82df2af013e4ee2bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 15:47:42 +0200 Subject: [PATCH 06/35] Use new contract types in SafeFactory --- .../safe-core-sdk/src/safeFactory/index.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index f713528e8..e6cc29523 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -1,8 +1,8 @@ -import { ContractNetworksConfig, defaultContractNetworks } from '../configuration/contracts' import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' import EthAdapter from '../ethereumLibs/EthAdapter' import Safe from '../Safe' +import { ContractNetworksConfig } from '../types' import { EMPTY_DATA, ZERO_ADDRESS } from '../utils/constants' import { validateSafeAccountConfig } from './utils' @@ -29,7 +29,7 @@ export interface SafeFactoryConfig { } class SafeFactory { - #contractNetworks!: ContractNetworksConfig + #contractNetworks?: ContractNetworksConfig #ethAdapter!: EthAdapter #safeProxyFactoryContract!: GnosisSafeProxyFactoryContract #gnosisSafeContract!: GnosisSafeContract @@ -42,17 +42,16 @@ class SafeFactory { private async init({ ethAdapter, contractNetworks }: SafeFactoryConfig): Promise { this.#ethAdapter = ethAdapter - this.#contractNetworks = { ...defaultContractNetworks, ...contractNetworks } + this.#contractNetworks = contractNetworks const chainId = await this.#ethAdapter.getChainId() - const contractNetworksConfig = this.#contractNetworks[chainId] - if (!contractNetworksConfig) { - throw new Error('Safe contracts not found in the current network') - } + const customContracts = contractNetworks?.[chainId] this.#safeProxyFactoryContract = await ethAdapter.getGnosisSafeProxyFactoryContract( - this.#contractNetworks[chainId].safeProxyFactoryAddress + chainId, + customContracts?.safeProxyFactoryAddress ) this.#gnosisSafeContract = await ethAdapter.getSafeContract( - contractNetworksConfig.safeMasterCopyAddress + chainId, + customContracts?.safeMasterCopyAddress ) } @@ -95,6 +94,7 @@ class SafeFactory { safeDeploymentConfig?: SafeDeploymentConfig ): Promise { validateSafeAccountConfig(safeAccountConfig) + const chainId = await this.#ethAdapter.getChainId() const signerAddress = await this.#ethAdapter.getSignerAddress() const initializer = await this.encodeSetupCallData(safeAccountConfig) const safeAddress = await this.#safeProxyFactoryContract.createProxy({ @@ -103,7 +103,7 @@ class SafeFactory { saltNonce: safeDeploymentConfig?.saltNonce, options: { from: signerAddress } }) - const safeContract = await this.#ethAdapter.getSafeContract(safeAddress) + const safeContract = await this.#ethAdapter.getSafeContract(chainId, safeAddress) const safe = Safe.create({ ethAdapter: this.#ethAdapter, safeAddress: safeContract.getAddress(), From 58554fc7b5bbb6dea8be78bef1d50f40bd9eb40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 15 Oct 2021 15:48:57 +0200 Subject: [PATCH 07/35] Update contract types in tests --- packages/safe-core-sdk/tests/contractManager.test.ts | 6 +++--- packages/safe-core-sdk/tests/safeFactory.test.ts | 2 +- packages/safe-core-sdk/tests/utils/setupContracts.ts | 9 +++------ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/safe-core-sdk/tests/contractManager.test.ts b/packages/safe-core-sdk/tests/contractManager.test.ts index cf1a7fb02..5fa505df8 100644 --- a/packages/safe-core-sdk/tests/contractManager.test.ts +++ b/packages/safe-core-sdk/tests/contractManager.test.ts @@ -46,7 +46,7 @@ describe('Safe contracts manager', () => { safeAddress: safe.address }) ) - .to.be.rejectedWith('Safe contracts not found in the current network') + .to.be.rejectedWith('Safe Proxy contract is not deployed in the current network') }) it('should fail if Safe Proxy contract is not deployed in the current network', async () => { @@ -65,7 +65,7 @@ describe('Safe contracts manager', () => { }) it('should fail if MultiSend contract is specified in contractNetworks but not deployed', async () => { - const { safe, accounts, chainId, contractNetworks } = await setupTests() + const { safe, accounts, chainId } = await setupTests() const customContractNetworks: ContractNetworksConfig = { [chainId]: { multiSendAddress: ZERO_ADDRESS, @@ -83,7 +83,7 @@ describe('Safe contracts manager', () => { contractNetworks: customContractNetworks }) ) - .to.be.rejectedWith('MultiSend contract is not deployed in the current network') + .to.be.rejectedWith('Safe Proxy contract is not deployed in the current network') }) it('should set the MultiSend contract available in the current network', async () => { diff --git a/packages/safe-core-sdk/tests/safeFactory.test.ts b/packages/safe-core-sdk/tests/safeFactory.test.ts index 091f9b9f6..40b353d64 100644 --- a/packages/safe-core-sdk/tests/safeFactory.test.ts +++ b/packages/safe-core-sdk/tests/safeFactory.test.ts @@ -39,7 +39,7 @@ describe('Safe Proxy Factory', () => { const ethAdapter = await getEthAdapter(account1.signer) chai .expect(SafeFactory.create({ ethAdapter })) - .rejectedWith('Safe contracts not found in the current network') + .rejectedWith('Safe Proxy contract is not deployed in the current network') }) it('should instantiate the Safe Proxy Factory', async () => { diff --git a/packages/safe-core-sdk/tests/utils/setupContracts.ts b/packages/safe-core-sdk/tests/utils/setupContracts.ts index 460a7253e..3bc1c0678 100644 --- a/packages/safe-core-sdk/tests/utils/setupContracts.ts +++ b/packages/safe-core-sdk/tests/utils/setupContracts.ts @@ -1,11 +1,8 @@ import { AddressZero } from '@ethersproject/constants' import { deployments, ethers } from 'hardhat' -import { GnosisSafe, MultiSend } from '../../typechain/src/ethers-v5' -import { - DailyLimitModule, - ERC20Mintable, - SocialRecoveryModule -} from '../../typechain/tests/ethers-v5' +import { MultiSend } from '../../typechain/src/ethers-v5/v1.1.1/MultiSend' +import { GnosisSafe } from '../../typechain/src/ethers-v5/v1.2.0/GnosisSafe' +import { DailyLimitModule, ERC20Mintable, SocialRecoveryModule } from '../../typechain/tests/ethers-v5' export const getSafeSingleton = async () => { const SafeDeployment = await deployments.get('GnosisSafe') From 33872c1639e918e068c318f9ad04863beef7c2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 28 Oct 2021 00:29:36 +0200 Subject: [PATCH 08/35] handle different Safe versions in EthAdapters --- .../src/contracts/safeDeploymentContracts.ts | 50 +++++++++++++ .../src/ethereumLibs/EthAdapter.ts | 16 ++++- .../src/ethereumLibs/EthersAdapter.ts | 71 ++++++++++--------- .../src/ethereumLibs/Web3Adapter.ts | 59 +++++++-------- packages/safe-core-sdk/src/index.ts | 1 - .../src/managers/contractManager.ts | 8 ++- 6 files changed, 138 insertions(+), 67 deletions(-) create mode 100644 packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts diff --git a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts new file mode 100644 index 000000000..734fdeb64 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts @@ -0,0 +1,50 @@ +import { + getMultiSendDeployment, + getProxyFactoryDeployment, + getSafeSingletonDeployment, + SingletonDeployment +} from '@gnosis.pm/safe-deployments' + +export type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' + +const safeDeploymentsVersions = { + '1.3.0': { + safeMasterCopyVersion: '1.3.0', + safeProxyFactoryVersion: '1.3.0', + multiSendVersion: '1.3.0' + }, + '1.2.0': { + safeMasterCopyVersion: '1.2.0', + safeProxyFactoryVersion: '1.1.1', + multiSendVersion: '1.1.1' + }, + '1.1.1': { + safeMasterCopyVersion: '1.1.1', + safeProxyFactoryVersion: '1.1.1', + multiSendVersion: '1.1.1' + } +} + +export function getSafeContractDeployment( + safeVersion: SafeVersion, + chainId: number +): SingletonDeployment | undefined { + const version = safeDeploymentsVersions[safeVersion].safeMasterCopyVersion + return getSafeSingletonDeployment({ version, network: chainId.toString(), released: true }) +} + +export function getMultiSendContractDeployment( + safeVersion: SafeVersion, + chainId: number +): SingletonDeployment | undefined { + const version = safeDeploymentsVersions[safeVersion].multiSendVersion + return getMultiSendDeployment({ version, network: chainId.toString(), released: true }) +} + +export function getSafeProxyFactoryContractDeployment( + safeVersion: SafeVersion, + chainId: number +): SingletonDeployment | undefined { + const version = safeDeploymentsVersions[safeVersion].safeProxyFactoryVersion + return getProxyFactoryDeployment({ version, network: chainId.toString(), released: true }) +} diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts index 6e580d267..0e9fc1873 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts @@ -2,6 +2,7 @@ import { BigNumber } from '@ethersproject/bignumber' import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' import MultiSendContract from '../contracts/MultiSend/MultiSendContract' +import { SafeVersion } from '../contracts/safeDeploymentContracts' import { AbiItem } from '../types' export interface EthAdapterTransaction { @@ -23,9 +24,18 @@ interface EthAdapter { getBalance(address: string): Promise getChainId(): Promise getContract(address: string, abi: AbiItem[]): any - getSafeContract(chainId: number, customContractAddress?: string): Promise - getMultiSendContract(chainId: number, customContractAddress?: string): Promise - getGnosisSafeProxyFactoryContract( + getSafeContract( + safeVersion: SafeVersion, + chainId: number, + customContractAddress?: string + ): Promise + getMultiSendContract( + safeVersion: SafeVersion, + chainId: number, + customContractAddress?: string + ): Promise + getSafeProxyFactoryContract( + safeVersion: SafeVersion, chainId: number, customContractAddress?: string ): Promise diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index 42266620d..f0cd49674 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -3,17 +3,18 @@ import { Signer } from '@ethersproject/abstract-signer' import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' import { Provider } from '@ethersproject/providers' -import { - getMultiSendDeployment, - getProxyFactoryDeployment, - getSafeSingletonDeployment -} from '@gnosis.pm/safe-deployments' -import { MultiSend__factory } from '../../typechain/src/ethers-v5/v1.1.1/factories/MultiSend__factory' -import { ProxyFactory__factory } from '../../typechain/src/ethers-v5/v1.1.1/factories/ProxyFactory__factory' -import { GnosisSafe__factory } from '../../typechain/src/ethers-v5/v1.2.0/factories/GnosisSafe__factory' -import GnosisSafeEthersV5Contract from '../contracts/GnosisSafe/GnosisSafeEthersV5Contract' +import { GnosisSafe__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/GnosisSafe__factory' +import { MultiSend__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/MultiSend__factory' +import { ProxyFactory__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/ProxyFactory__factory' +import GnosisSafeEthersV5Contract from '../contracts/GnosisSafe/GnosisSafeContractEthersV5' import GnosisSafeProxyFactoryEthersV5Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract' import MultiSendEthersV5Contract from '../contracts/MultiSend/MultiSendEthersV5Contract' +import { + getMultiSendContractDeployment, + getSafeContractDeployment, + getSafeProxyFactoryContractDeployment, + SafeVersion +} from '../contracts/safeDeploymentContracts' import { AbiItem } from '../types' import EthAdapter, { EthAdapterTransaction } from './EthAdapter' @@ -61,47 +62,53 @@ class EthersAdapter implements EthAdapter { return (await this.#provider.getNetwork()).chainId } - async getSafeContract(chainId: number, customContractAddress?: string): Promise { + async getSafeContract( + safeVersion: SafeVersion, + chainId: number, + customContractAddress?: string + ): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress } else { - const safeSingletonDeployment = getSafeSingletonDeployment({ - network: chainId.toString(), - released: true - }) + const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) + console.log({ safeSingletonDeployment }) contractAddress = safeSingletonDeployment?.networkAddresses[chainId] ?? safeSingletonDeployment?.defaultAddress + console.log({ contractAddress }) } - if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { + if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy contract is not deployed in the current network') } const safeContract = GnosisSafe__factory.connect(contractAddress, this.#signer) return new GnosisSafeEthersV5Contract(safeContract) } - async getMultiSendContract(chainId: number, customContractAddress?: string): Promise { + async getMultiSendContract( + safeVersion: SafeVersion, + chainId: number, + customContractAddress?: string + ): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress } else { - const multiSendDeployment = getMultiSendDeployment({ - network: chainId.toString(), - released: true - }) + const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) + console.log({ multiSendDeployment }) contractAddress = - multiSendDeployment?.networkAddresses[chainId] ?? - multiSendDeployment?.defaultAddress + multiSendDeployment?.networkAddresses[chainId] ?? multiSendDeployment?.defaultAddress + console.log({ contractAddress }) } - if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { - throw new Error('Safe Proxy contract is not deployed in the current network') + if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { + throw new Error('Multi Send contract is not deployed in the current network') } const multiSendContract = MultiSend__factory.connect(contractAddress, this.#signer) return new MultiSendEthersV5Contract(multiSendContract) } - async getGnosisSafeProxyFactoryContract( + async getSafeProxyFactoryContract( + safeVersion: SafeVersion, chainId: number, customContractAddress?: string ): Promise { @@ -109,16 +116,14 @@ class EthersAdapter implements EthAdapter { if (customContractAddress) { contractAddress = customContractAddress } else { - const proxyFactoryDeployment = getProxyFactoryDeployment({ - network: chainId.toString(), - released: true - }) + const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) + console.log({ proxyFactoryDeployment }) contractAddress = - proxyFactoryDeployment?.networkAddresses[chainId] ?? - proxyFactoryDeployment?.defaultAddress + proxyFactoryDeployment?.networkAddresses[chainId] ?? proxyFactoryDeployment?.defaultAddress + console.log({ contractAddress }) } - if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { - throw new Error('Safe Proxy contract is not deployed in the current network') + if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { + throw new Error('Safe Proxy Factory contract is not deployed in the current network') } const proxyFactoryContract = ProxyFactory__factory.connect(contractAddress, this.#signer) return new GnosisSafeProxyFactoryEthersV5Contract(proxyFactoryContract) diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index 6784fa089..68837360a 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -1,15 +1,16 @@ import { BigNumber } from '@ethersproject/bignumber' -import { - getMultiSendDeployment, - getProxyFactoryDeployment, - getSafeSingletonDeployment -} from '@gnosis.pm/safe-deployments' -import { MultiSend } from '../../typechain/src/web3-v1/v1.1.1/multi_send' -import { ProxyFactory } from '../../typechain/src/web3-v1/v1.1.1/proxy_factory' -import { GnosisSafe } from '../../typechain/src/web3-v1/v1.2.0/gnosis_safe' -import GnosisSafeWeb3Contract from '../contracts/GnosisSafe/GnosisSafeWeb3Contract' +import { GnosisSafe } from '../../typechain/src/web3-v1/v1.3.0/gnosis_safe' +import { MultiSend } from '../../typechain/src/web3-v1/v1.3.0/multi_send' +import { ProxyFactory } from '../../typechain/src/web3-v1/v1.3.0/proxy_factory' +import GnosisSafeWeb3Contract from '../contracts/GnosisSafe/GnosisSafeContractWeb3' import GnosisSafeProxyFactoryWeb3Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract' import MultiSendWeb3Contract from '../contracts/MultiSend/MultiSendWeb3Contract' +import { + getMultiSendContractDeployment, + getSafeContractDeployment, + getSafeProxyFactoryContractDeployment, + SafeVersion +} from '../contracts/safeDeploymentContracts' import { AbiItem } from '../types' import EthAdapter, { EthAdapterTransaction } from './EthAdapter' @@ -44,16 +45,17 @@ class Web3Adapter implements EthAdapter { return this.#web3.eth.getChainId() } - async getSafeContract(chainId: number, customContractAddress?: string): Promise { - const safeSingletonDeployment = getSafeSingletonDeployment({ - network: chainId.toString(), - released: true - }) + async getSafeContract( + safeVersion: SafeVersion, + chainId: number, + customContractAddress?: string + ): Promise { + const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) const contractAddress = customContractAddress ?? safeSingletonDeployment?.networkAddresses[chainId] ?? safeSingletonDeployment?.defaultAddress - if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { + if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy contract is not deployed in the current network') } const safeContract = this.getContract( @@ -63,17 +65,18 @@ class Web3Adapter implements EthAdapter { return new GnosisSafeWeb3Contract(safeContract) } - async getMultiSendContract(chainId: number, customContractAddress?: string): Promise { - const multiSendDeployment = getMultiSendDeployment({ - network: chainId.toString(), - released: true - }) + async getMultiSendContract( + safeVersion: SafeVersion, + chainId: number, + customContractAddress?: string + ): Promise { + const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) const contractAddress = customContractAddress ?? multiSendDeployment?.networkAddresses[chainId] ?? multiSendDeployment?.defaultAddress - if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { - throw new Error('Safe Proxy contract is not deployed in the current network') + if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { + throw new Error('Multi Send contract is not deployed in the current network') } const multiSendContract = this.getContract( contractAddress, @@ -82,20 +85,18 @@ class Web3Adapter implements EthAdapter { return new MultiSendWeb3Contract(multiSendContract) } - async getGnosisSafeProxyFactoryContract( + async getSafeProxyFactoryContract( + safeVersion: SafeVersion, chainId: number, customContractAddress?: string ): Promise { - const proxyFactoryDeployment = getProxyFactoryDeployment({ - network: chainId.toString(), - released: true - }) + const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) const contractAddress = customContractAddress ?? proxyFactoryDeployment?.networkAddresses[chainId] ?? proxyFactoryDeployment?.defaultAddress - if (!contractAddress || (await this.getContractCode(contractAddress) === '0x')) { - throw new Error('Safe Proxy contract is not deployed in the current network') + if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { + throw new Error('Safe Proxy Factory contract is not deployed in the current network') } const proxyFactoryContract = this.getContract( contractAddress, diff --git a/packages/safe-core-sdk/src/index.ts b/packages/safe-core-sdk/src/index.ts index f08651f10..978dde6a4 100644 --- a/packages/safe-core-sdk/src/index.ts +++ b/packages/safe-core-sdk/src/index.ts @@ -44,4 +44,3 @@ export { SwapOwnerTxParams, EthSignSignature } - diff --git a/packages/safe-core-sdk/src/managers/contractManager.ts b/packages/safe-core-sdk/src/managers/contractManager.ts index 5afab2b22..6ba8de9f3 100644 --- a/packages/safe-core-sdk/src/managers/contractManager.ts +++ b/packages/safe-core-sdk/src/managers/contractManager.ts @@ -1,5 +1,6 @@ import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import MultiSendContract from '../contracts/MultiSend/MultiSendContract' +import { SafeVersion } from '../contracts/safeDeploymentContracts' import EthAdapter from '../ethereumLibs/EthAdapter' import { ContractNetworksConfig } from '../types' @@ -24,10 +25,15 @@ class ContractManager { contractNetworks?: ContractNetworksConfig ): Promise { const chainId = await ethAdapter.getChainId() + const baseSafeVersion: SafeVersion = '1.1.1' + const temporarySafeContract = await ethAdapter.getSafeContract(baseSafeVersion, chainId, safeAddress) + const safeVersion = (await temporarySafeContract.getVersion()) as SafeVersion + const customContracts = contractNetworks?.[chainId] this.#contractNetworks = contractNetworks - this.#safeContract = await ethAdapter.getSafeContract(chainId, safeAddress) + this.#safeContract = await ethAdapter.getSafeContract(safeVersion, chainId, safeAddress) this.#multiSendContract = await ethAdapter.getMultiSendContract( + safeVersion, chainId, customContracts?.multiSendAddress ) From ef70053134142d0276d693495b87761815be90a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 28 Oct 2021 00:30:42 +0200 Subject: [PATCH 09/35] Use types from last version of the Safe contracts (backwards compatible) --- .../GnosisSafeProxyFactoryEthersV5Contract.ts | 2 +- .../GnosisSafeProxyFactoryWeb3Contract.ts | 2 +- .../contracts/MultiSend/MultiSendEthersV5Contract.ts | 2 +- .../src/contracts/MultiSend/MultiSendWeb3Contract.ts | 2 +- packages/safe-core-sdk/tests/utils/setupContracts.ts | 10 +++++++--- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts index 9785bba8f..579a6b93a 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts @@ -1,5 +1,5 @@ import { ContractTransaction, Event } from '@ethersproject/contracts' -import { ProxyFactory } from '../../../typechain/src/ethers-v5/v1.1.1/ProxyFactory' +import { ProxyFactory } from '../../../typechain/src/ethers-v5/v1.3.0/ProxyFactory' import GnosisSafeProxyFactoryContract, { CreateProxyProps } from './GnosisSafeProxyFactoryContract' class GnosisSafeProxyFactoryEthersV5Contract implements GnosisSafeProxyFactoryContract { diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts index 20f8cde1a..ea70bed8f 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts @@ -1,5 +1,5 @@ import { PromiEvent, TransactionReceipt } from 'web3-core/types' -import { ProxyFactory } from '../../../typechain/src/web3-v1/v1.1.1/proxy_factory' +import { ProxyFactory } from '../../../typechain/src/web3-v1/v1.3.0/proxy_factory' import GnosisSafeProxyFactoryContract, { CreateProxyProps } from './GnosisSafeProxyFactoryContract' class GnosisSafeProxyFactoryWeb3Contract implements GnosisSafeProxyFactoryContract { diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts index c0be63f85..406a412d1 100644 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts @@ -1,4 +1,4 @@ -import { MultiSend, MultiSendInterface } from '../../../typechain/src/ethers-v5/v1.1.1/MultiSend' +import { MultiSend, MultiSendInterface } from '../../../typechain/src/ethers-v5/v1.3.0/MultiSend' import MultiSendContract from './MultiSendContract' class MultiSendEthersV5Contract implements MultiSendContract { diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts index 6b4a14aa7..4d11d9290 100644 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts @@ -1,4 +1,4 @@ -import { MultiSend } from '../../../typechain/src/web3-v1/v1.1.1/multi_send' +import { MultiSend } from '../../../typechain/src/web3-v1/v1.3.0/multi_send' import MultiSendContract from './MultiSendContract' class MultiSendWeb3Contract implements MultiSendContract { diff --git a/packages/safe-core-sdk/tests/utils/setupContracts.ts b/packages/safe-core-sdk/tests/utils/setupContracts.ts index 3bc1c0678..bc42036db 100644 --- a/packages/safe-core-sdk/tests/utils/setupContracts.ts +++ b/packages/safe-core-sdk/tests/utils/setupContracts.ts @@ -1,8 +1,12 @@ import { AddressZero } from '@ethersproject/constants' import { deployments, ethers } from 'hardhat' -import { MultiSend } from '../../typechain/src/ethers-v5/v1.1.1/MultiSend' -import { GnosisSafe } from '../../typechain/src/ethers-v5/v1.2.0/GnosisSafe' -import { DailyLimitModule, ERC20Mintable, SocialRecoveryModule } from '../../typechain/tests/ethers-v5' +import { GnosisSafe } from '../../typechain/src/ethers-v5/v1.3.0/GnosisSafe' +import { MultiSend } from '../../typechain/src/ethers-v5/v1.3.0/MultiSend' +import { + DailyLimitModule, + ERC20Mintable, + SocialRecoveryModule +} from '../../typechain/tests/ethers-v5' export const getSafeSingleton = async () => { const SafeDeployment = await deployments.get('GnosisSafe') From 5cbb203294cc6c30d776ea1c56efafa7ffc5c38e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 28 Oct 2021 00:37:29 +0200 Subject: [PATCH 10/35] Allow deployment of multiple Safe versions --- .../safe-core-sdk/src/safeFactory/index.ts | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index e6cc29523..4d219ef19 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -1,5 +1,6 @@ import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' +import { SafeVersion } from '../contracts/safeDeploymentContracts' import EthAdapter from '../ethereumLibs/EthAdapter' import Safe from '../Safe' import { ContractNetworksConfig } from '../types' @@ -24,32 +25,55 @@ export interface SafeDeploymentConfig { export interface SafeFactoryConfig { /** ethAdapter - Ethereum adapter */ ethAdapter: EthAdapter + /** safeVersion - Versions of the Safe deployed by this Factory contract */ + safeVersion?: SafeVersion + /** contractNetworks - Contract network configuration */ + contractNetworks?: ContractNetworksConfig +} + +interface SafeFactoryInitConfig { + /** ethAdapter - Ethereum adapter */ + ethAdapter: EthAdapter + /** safeVersion - Versions of the Safe deployed by this Factory contract */ + safeVersion: SafeVersion /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig } class SafeFactory { #contractNetworks?: ContractNetworksConfig + #safeVersion!: SafeVersion #ethAdapter!: EthAdapter #safeProxyFactoryContract!: GnosisSafeProxyFactoryContract #gnosisSafeContract!: GnosisSafeContract - static async create({ ethAdapter, contractNetworks }: SafeFactoryConfig): Promise { + static async create({ + ethAdapter, + safeVersion = '1.3.0', + contractNetworks + }: SafeFactoryConfig): Promise { const safeFactorySdk = new SafeFactory() - await safeFactorySdk.init({ ethAdapter, contractNetworks }) + await safeFactorySdk.init({ ethAdapter, safeVersion, contractNetworks }) return safeFactorySdk } - private async init({ ethAdapter, contractNetworks }: SafeFactoryConfig): Promise { + private async init({ + ethAdapter, + safeVersion, + contractNetworks + }: SafeFactoryInitConfig): Promise { this.#ethAdapter = ethAdapter + this.#safeVersion = safeVersion this.#contractNetworks = contractNetworks const chainId = await this.#ethAdapter.getChainId() const customContracts = contractNetworks?.[chainId] - this.#safeProxyFactoryContract = await ethAdapter.getGnosisSafeProxyFactoryContract( + this.#safeProxyFactoryContract = await ethAdapter.getSafeProxyFactoryContract( + this.#safeVersion, chainId, customContracts?.safeProxyFactoryAddress ) this.#gnosisSafeContract = await ethAdapter.getSafeContract( + this.#safeVersion, chainId, customContracts?.safeMasterCopyAddress ) @@ -59,6 +83,10 @@ class SafeFactory { return this.#ethAdapter } + getSafeVersion(): SafeVersion { + return this.#safeVersion + } + async getChainId(): Promise { return this.#ethAdapter.getChainId() } @@ -103,7 +131,11 @@ class SafeFactory { saltNonce: safeDeploymentConfig?.saltNonce, options: { from: signerAddress } }) - const safeContract = await this.#ethAdapter.getSafeContract(chainId, safeAddress) + const safeContract = await this.#ethAdapter.getSafeContract( + this.#safeVersion, + chainId, + safeAddress + ) const safe = Safe.create({ ethAdapter: this.#ethAdapter, safeAddress: safeContract.getAddress(), From 32c25911f42addfb1cd3a40f09dbef0be295b357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 28 Oct 2021 00:42:55 +0200 Subject: [PATCH 11/35] Rename SafeContract classes --- ...afeEthersV5Contract.ts => GnosisSafeContractEthersV5.ts} | 6 +++--- ...{GnosisSafeWeb3Contract.ts => GnosisSafeContractWeb3.ts} | 6 +++--- packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts | 6 +++--- packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename packages/safe-core-sdk/src/contracts/GnosisSafe/{GnosisSafeEthersV5Contract.ts => GnosisSafeContractEthersV5.ts} (95%) rename packages/safe-core-sdk/src/contracts/GnosisSafe/{GnosisSafeWeb3Contract.ts => GnosisSafeContractWeb3.ts} (95%) diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthersV5.ts similarity index 95% rename from packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts rename to packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthersV5.ts index 86eb678cf..593a3e4e9 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthersV5.ts @@ -1,7 +1,7 @@ import { BigNumber } from '@ethersproject/bignumber' import { ContractTransaction } from '@ethersproject/contracts' import { SafeTransaction, SafeTransactionData } from '@gnosis.pm/safe-core-sdk-types' -import { GnosisSafe, GnosisSafeInterface } from '../../../typechain/src/ethers-v5/v1.2.0/GnosisSafe' +import { GnosisSafe, GnosisSafeInterface } from '../../../typechain/src/ethers-v5/v1.3.0/GnosisSafe' import { EthersTransactionResult, TransactionOptions } from '../../utils/transactions/types' import GnosisSafeContract from './GnosisSafeContract' @@ -16,7 +16,7 @@ function toTxResult( } } -class GnosisSafeEthersV5Contract implements GnosisSafeContract { +class GnosisSafeContractEthersV5 implements GnosisSafeContract { constructor(public contract: GnosisSafe) {} async getVersion(): Promise { @@ -108,4 +108,4 @@ class GnosisSafeEthersV5Contract implements GnosisSafeContract { } } -export default GnosisSafeEthersV5Contract +export default GnosisSafeContractEthersV5 diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts similarity index 95% rename from packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts rename to packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts index 2d6fe868b..1601c9cb9 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts @@ -1,7 +1,7 @@ import { BigNumber } from '@ethersproject/bignumber' import { SafeTransaction, SafeTransactionData } from '@gnosis.pm/safe-core-sdk-types' import { PromiEvent, TransactionReceipt } from 'web3-core/types' -import { GnosisSafe } from '../../../typechain/src/web3-v1/v1.2.0/gnosis_safe' +import { GnosisSafe } from '../../../typechain/src/web3-v1/v1.3.0/gnosis_safe' import { TransactionOptions, Web3TransactionResult } from '../../utils/transactions/types' import GnosisSafeContract from './GnosisSafeContract' @@ -16,7 +16,7 @@ function toTxResult( ) } -class GnosisSafeWeb3Contract implements GnosisSafeContract { +class GnosisSafeContractWeb3 implements GnosisSafeContract { constructor(public contract: GnosisSafe) {} async getVersion(): Promise { @@ -111,4 +111,4 @@ class GnosisSafeWeb3Contract implements GnosisSafeContract { } } -export default GnosisSafeWeb3Contract +export default GnosisSafeContractWeb3 diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index f0cd49674..4f3895648 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -6,7 +6,7 @@ import { Provider } from '@ethersproject/providers' import { GnosisSafe__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/GnosisSafe__factory' import { MultiSend__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/MultiSend__factory' import { ProxyFactory__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/ProxyFactory__factory' -import GnosisSafeEthersV5Contract from '../contracts/GnosisSafe/GnosisSafeContractEthersV5' +import GnosisSafeContractEthersV5 from '../contracts/GnosisSafe/GnosisSafeContractEthersV5' import GnosisSafeProxyFactoryEthersV5Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract' import MultiSendEthersV5Contract from '../contracts/MultiSend/MultiSendEthersV5Contract' import { @@ -66,7 +66,7 @@ class EthersAdapter implements EthAdapter { safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress @@ -82,7 +82,7 @@ class EthersAdapter implements EthAdapter { throw new Error('Safe Proxy contract is not deployed in the current network') } const safeContract = GnosisSafe__factory.connect(contractAddress, this.#signer) - return new GnosisSafeEthersV5Contract(safeContract) + return new GnosisSafeContractEthersV5(safeContract) } async getMultiSendContract( diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index 68837360a..2ebe67b0f 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -2,7 +2,7 @@ import { BigNumber } from '@ethersproject/bignumber' import { GnosisSafe } from '../../typechain/src/web3-v1/v1.3.0/gnosis_safe' import { MultiSend } from '../../typechain/src/web3-v1/v1.3.0/multi_send' import { ProxyFactory } from '../../typechain/src/web3-v1/v1.3.0/proxy_factory' -import GnosisSafeWeb3Contract from '../contracts/GnosisSafe/GnosisSafeContractWeb3' +import GnosisSafeContractWeb3 from '../contracts/GnosisSafe/GnosisSafeContractWeb3' import GnosisSafeProxyFactoryWeb3Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract' import MultiSendWeb3Contract from '../contracts/MultiSend/MultiSendWeb3Contract' import { @@ -49,7 +49,7 @@ class Web3Adapter implements EthAdapter { safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): Promise { const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) const contractAddress = customContractAddress ?? @@ -62,7 +62,7 @@ class Web3Adapter implements EthAdapter { contractAddress, safeSingletonDeployment?.abi as AbiItem[] ) as GnosisSafe - return new GnosisSafeWeb3Contract(safeContract) + return new GnosisSafeContractWeb3(safeContract) } async getMultiSendContract( From 69363c966bf9012ed16d7d389b63e724f5867a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 28 Oct 2021 00:59:28 +0200 Subject: [PATCH 12/35] Update properties of SafeFactory in README file --- packages/safe-core-sdk/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/safe-core-sdk/README.md b/packages/safe-core-sdk/README.md index 701230c50..389a8e642 100644 --- a/packages/safe-core-sdk/README.md +++ b/packages/safe-core-sdk/README.md @@ -75,6 +75,25 @@ const safeSdk: Safe = await safeFactory.deploySafe(safeAccountConfig) The method `deploySafe` executes a transaction from `owner1` account, deploys a new Safe and returns an instance of the Safe Core SDK connected to the new Safe. +The `SafeFactory` will deploy by default the last version of the Safe contracts available (currently `v1.3.0`). To deploy an older version of the Safe contracts instantiate the `SafeFactory` adding the property `safeVersion` with the desired version number. + +```js +const safeFactoryV1_1_1 = await SafeFactory.create({ ethAdapter, safeVersion: '1.1.1' }) +``` + +The property `contractNetworks` can also be used to provide the Safe contract addresses in case the SDK is used in a network where the Safe contracts are not deployed. + +```js +const contractNetworks: ContractNetworksConfig = { + [chainId]: { + multiSendAddress: '0x', + safeMasterCopyAddress: '0x', + safeProxyFactoryAddress: '0x' + } +} +const safeFactory = await SafeFactory.create({ ethAdapter, contractNetworks }) +``` + Call the method `getAddress`, for example, to check the address of the newly deployed Safe. ```js From 7a55d376e4cd31a20710e6e4489b695656e69abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 28 Oct 2021 01:03:32 +0200 Subject: [PATCH 13/35] Set default Safe contracts version --- .../safe-core-sdk/src/contracts/safeDeploymentContracts.ts | 2 ++ packages/safe-core-sdk/src/safeFactory/index.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts index 734fdeb64..40b0308a7 100644 --- a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts +++ b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts @@ -7,6 +7,8 @@ import { export type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' +export const DEFAULT_SAFE_VERSION: SafeVersion = '1.3.0' + const safeDeploymentsVersions = { '1.3.0': { safeMasterCopyVersion: '1.3.0', diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index 4d219ef19..d813725ea 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -1,6 +1,6 @@ import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' -import { SafeVersion } from '../contracts/safeDeploymentContracts' +import { DEFAULT_SAFE_VERSION, SafeVersion } from '../contracts/safeDeploymentContracts' import EthAdapter from '../ethereumLibs/EthAdapter' import Safe from '../Safe' import { ContractNetworksConfig } from '../types' @@ -49,7 +49,7 @@ class SafeFactory { static async create({ ethAdapter, - safeVersion = '1.3.0', + safeVersion = DEFAULT_SAFE_VERSION, contractNetworks }: SafeFactoryConfig): Promise { const safeFactorySdk = new SafeFactory() From 23b42eb1640f53a68c5059a90549b9af778cb2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:14:45 +0100 Subject: [PATCH 14/35] Remove unused ABI files --- .../contracts/GnosisSafe/SafeAbiV1-2-0.json | 474 ------------------ .../GnosisSafeProxyFactoryAbiV1-2-0.json | 156 ------ .../src/contracts/MultiSend/MultiSendAbi.json | 17 - 3 files changed, 647 deletions(-) delete mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/SafeAbiV1-2-0.json delete mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryAbiV1-2-0.json delete mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/MultiSendAbi.json diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/SafeAbiV1-2-0.json b/packages/safe-core-sdk/src/contracts/GnosisSafe/SafeAbiV1-2-0.json deleted file mode 100644 index 245c5fd3d..000000000 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/SafeAbiV1-2-0.json +++ /dev/null @@ -1,474 +0,0 @@ -[ - { - "constant": true, - "inputs": [], - "name": "nonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getOwners", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getModules", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "contract Module", - "name": "module", - "type": "address" - } - ], - "name": "isModuleEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owners", - "type": "address[]" - }, - { - "name": "_threshold", - "type": "uint256" - }, - { - "name": "to", - "type": "address" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "fallbackHandler", - "type": "address" - }, - { - "name": "paymentToken", - "type": "address" - }, - { - "name": "payment", - "type": "uint256" - }, - { - "name": "paymentReceiver", - "type": "address" - } - ], - "name": "setup", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "to", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "operation", - "type": "uint8" - }, - { - "name": "safeTxGas", - "type": "uint256" - }, - { - "name": "baseGas", - "type": "uint256" - }, - { - "name": "gasPrice", - "type": "uint256" - }, - { - "name": "gasToken", - "type": "address" - }, - { - "name": "refundReceiver", - "type": "address" - }, - { - "name": "signatures", - "type": "bytes" - } - ], - "name": "execTransaction", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "enum Enum.Operation", - "name": "operation", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "safeTxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "gasToken", - "type": "address" - }, - { - "internalType": "address", - "name": "refundReceiver", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - } - ], - "name": "getTransactionHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "bytes32", - "name": "hashToApprove", - "type": "bytes32" - } - ], - "name": "approveHash", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "approvedHashes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "to", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "operation", - "type": "uint8" - } - ], - "name": "requiredTxGas", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "contract Module", - "name": "module", - "type": "address" - } - ], - "name": "enableModule", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "contract Module", - "name": "prevModule", - "type": "address" - }, - { - "internalType": "contract Module", - "name": "module", - "type": "address" - } - ], - "name": "disableModule", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" - } - ], - "name": "addOwnerWithThreshold", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "prevOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" - } - ], - "name": "removeOwner", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "prevOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "oldOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "swapOwner", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" - } - ], - "name": "changeThreshold", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryAbiV1-2-0.json b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryAbiV1-2-0.json deleted file mode 100644 index 17201aafd..000000000 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryAbiV1-2-0.json +++ /dev/null @@ -1,156 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "masterCopy", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "createProxy", - "outputs": [ - { - "internalType": "contract GnosisSafeProxy", - "name": "proxy", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "proxyRuntimeCode", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "proxyCreationCode", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_mastercopy", - "type": "address" - }, - { - "internalType": "bytes", - "name": "initializer", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "name": "createProxyWithNonce", - "outputs": [ - { - "internalType": "contract GnosisSafeProxy", - "name": "proxy", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_mastercopy", - "type": "address" - }, - { - "internalType": "bytes", - "name": "initializer", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - }, - { - "internalType": "contract IProxyCreationCallback", - "name": "callback", - "type": "address" - } - ], - "name": "createProxyWithCallback", - "outputs": [ - { - "internalType": "contract GnosisSafeProxy", - "name": "proxy", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_mastercopy", - "type": "address" - }, - { - "internalType": "bytes", - "name": "initializer", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "saltNonce", - "type": "uint256" - } - ], - "name": "calculateCreateProxyWithNonceAddress", - "outputs": [ - { - "internalType": "contract GnosisSafeProxy", - "name": "proxy", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendAbi.json b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendAbi.json deleted file mode 100644 index d47e79d3f..000000000 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendAbi.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "internalType": "bytes", - "name": "transactions", - "type": "bytes" - } - ], - "name": "multiSend", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file From 8ee4765afc12b855fe84c167619229c64c7610c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:15:21 +0100 Subject: [PATCH 15/35] Add more properties to SafeAccountConfig in README --- packages/safe-core-sdk/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/safe-core-sdk/README.md b/packages/safe-core-sdk/README.md index 389a8e642..9fc1b8706 100644 --- a/packages/safe-core-sdk/README.md +++ b/packages/safe-core-sdk/README.md @@ -68,7 +68,11 @@ const safeFactory = await SafeFactory.create({ ethAdapter }) const owners = ['0x
', '0x
', '0x
'] const threshold = 3 -const safeAccountConfig: SafeAccountConfig = { owners, threshold } +const safeAccountConfig: SafeAccountConfig = { + owners, + threshold, + // ... +} const safeSdk: Safe = await safeFactory.deploySafe(safeAccountConfig) ``` From 530333d6109f0e734e1e5381ee9c741178cb5979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:20:00 +0100 Subject: [PATCH 16/35] Add all GnosisSafeContract classes depending on the version --- ...thersV5.ts => GnosisSafeContractEthers.ts} | 21 +++++++++-------- .../GnosisSafe/GnosisSafeContractWeb3.ts | 16 ++++++------- .../GnosisSafeContract_V1_1_1_Ethers.ts | 23 +++++++++++++++++++ .../v1.1.1/GnosisSafeContract_V1_1_1_Web3.ts | 23 +++++++++++++++++++ .../GnosisSafeContract_V1_2_0_Ethers.ts | 18 +++++++++++++++ .../v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts | 18 +++++++++++++++ .../GnosisSafeContract_V1_3_0_Ethers.ts | 21 +++++++++++++++++ .../v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts | 23 +++++++++++++++++++ 8 files changed, 144 insertions(+), 19 deletions(-) rename packages/safe-core-sdk/src/contracts/GnosisSafe/{GnosisSafeContractEthersV5.ts => GnosisSafeContractEthers.ts} (82%) create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Web3.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthersV5.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthers.ts similarity index 82% rename from packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthersV5.ts rename to packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthers.ts index 593a3e4e9..b19cc629a 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthersV5.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractEthers.ts @@ -1,7 +1,12 @@ import { BigNumber } from '@ethersproject/bignumber' import { ContractTransaction } from '@ethersproject/contracts' import { SafeTransaction, SafeTransactionData } from '@gnosis.pm/safe-core-sdk-types' -import { GnosisSafe, GnosisSafeInterface } from '../../../typechain/src/ethers-v5/v1.3.0/GnosisSafe' +import { GnosisSafe as GnosisSafe_V1_1_1 } from '../../../typechain/src/ethers-v5/v1.1.1/GnosisSafe' +import { GnosisSafe as GnosisSafe_V1_2_0 } from '../../../typechain/src/ethers-v5/v1.2.0/GnosisSafe' +import { + GnosisSafe as GnosisSafe_V1_3_0, + GnosisSafeInterface +} from '../../../typechain/src/ethers-v5/v1.3.0/GnosisSafe' import { EthersTransactionResult, TransactionOptions } from '../../utils/transactions/types' import GnosisSafeContract from './GnosisSafeContract' @@ -16,8 +21,8 @@ function toTxResult( } } -class GnosisSafeContractEthersV5 implements GnosisSafeContract { - constructor(public contract: GnosisSafe) {} +abstract class GnosisSafeContractEthers implements GnosisSafeContract { + constructor(public contract: GnosisSafe_V1_1_1 | GnosisSafe_V1_2_0 | GnosisSafe_V1_3_0) {} async getVersion(): Promise { return this.contract.VERSION() @@ -67,13 +72,9 @@ class GnosisSafeContractEthersV5 implements GnosisSafeContract { return toTxResult(txResponse, options) } - async getModules(): Promise { - return this.contract.getModules() - } + abstract getModules(): Promise - async isModuleEnabled(moduleAddress: string): Promise { - return this.contract.isModuleEnabled(moduleAddress) - } + abstract isModuleEnabled(moduleAddress: string): Promise async execTransaction( safeTransaction: SafeTransaction, @@ -108,4 +109,4 @@ class GnosisSafeContractEthersV5 implements GnosisSafeContract { } } -export default GnosisSafeContractEthersV5 +export default GnosisSafeContractEthers diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts index 1601c9cb9..b08e1a104 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/GnosisSafeContractWeb3.ts @@ -1,7 +1,9 @@ import { BigNumber } from '@ethersproject/bignumber' import { SafeTransaction, SafeTransactionData } from '@gnosis.pm/safe-core-sdk-types' import { PromiEvent, TransactionReceipt } from 'web3-core/types' -import { GnosisSafe } from '../../../typechain/src/web3-v1/v1.3.0/gnosis_safe' +import { GnosisSafe as GnosisSafe_V1_1_1 } from '../../../typechain/src/web3-v1/v1.1.1/gnosis_safe' +import { GnosisSafe as GnosisSafe_V1_2_0 } from '../../../typechain/src/web3-v1/v1.2.0/gnosis_safe' +import { GnosisSafe as GnosisSafe_V1_3_0 } from '../../../typechain/src/web3-v1/v1.3.0/gnosis_safe' import { TransactionOptions, Web3TransactionResult } from '../../utils/transactions/types' import GnosisSafeContract from './GnosisSafeContract' @@ -16,8 +18,8 @@ function toTxResult( ) } -class GnosisSafeContractWeb3 implements GnosisSafeContract { - constructor(public contract: GnosisSafe) {} +abstract class GnosisSafeContractWeb3 implements GnosisSafeContract { + constructor(public contract: GnosisSafe_V1_1_1 | GnosisSafe_V1_2_0 | GnosisSafe_V1_3_0) {} async getVersion(): Promise { return this.contract.methods.VERSION().call() @@ -69,13 +71,9 @@ class GnosisSafeContractWeb3 implements GnosisSafeContract { return toTxResult(txResponse, options) } - async getModules(): Promise { - return this.contract.methods.getModules().call() - } + abstract getModules(): Promise - async isModuleEnabled(moduleAddress: string): Promise { - return this.contract.methods.isModuleEnabled(moduleAddress).call() - } + abstract isModuleEnabled(moduleAddress: string): Promise async execTransaction( safeTransaction: SafeTransaction, diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Ethers.ts new file mode 100644 index 000000000..213cf18f4 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Ethers.ts @@ -0,0 +1,23 @@ +import { GnosisSafe } from '../../../../typechain/src/ethers-v5/v1.1.1/GnosisSafe' +import { sameString } from '../../../utils' +import GnosisSafeContractEthers from '../GnosisSafeContractEthers' + +class GnosisSafeContract_V1_1_1_Ethers extends GnosisSafeContractEthers { + constructor(public contract: GnosisSafe) { + super(contract) + } + + async getModules(): Promise { + return (super.contract as GnosisSafe).getModules() + } + + async isModuleEnabled(moduleAddress: string): Promise { + const modules = await this.getModules() + const isModuleEnabled = modules.some((enabledModuleAddress: string) => + sameString(enabledModuleAddress, moduleAddress) + ) + return isModuleEnabled + } +} + +export default GnosisSafeContract_V1_1_1_Ethers diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Web3.ts new file mode 100644 index 000000000..34191adaf --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Web3.ts @@ -0,0 +1,23 @@ +import { GnosisSafe } from '../../../../typechain/src/web3-v1/v1.1.1/gnosis_safe' +import { sameString } from '../../../utils' +import GnosisSafeContractWeb3 from '../GnosisSafeContractWeb3' + +class GnosisSafeContract_V1_1_1_Web3 extends GnosisSafeContractWeb3 { + constructor(public contract: GnosisSafe) { + super(contract) + } + + async getModules(): Promise { + return (super.contract as GnosisSafe).methods.getModules().call() + } + + async isModuleEnabled(moduleAddress: string): Promise { + const modules = await this.getModules() + const isModuleEnabled = modules.some((enabledModuleAddress: string) => + sameString(enabledModuleAddress, moduleAddress) + ) + return isModuleEnabled + } +} + +export default GnosisSafeContract_V1_1_1_Web3 diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts new file mode 100644 index 000000000..abf64f42c --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts @@ -0,0 +1,18 @@ +import { GnosisSafe } from '../../../../typechain/src/ethers-v5/v1.2.0/GnosisSafe' +import GnosisSafeContractEthers from '../GnosisSafeContractEthers' + +class GnosisSafeContract_V1_2_0_Ethers extends GnosisSafeContractEthers { + constructor(public contract: GnosisSafe) { + super(contract) + } + + async getModules(): Promise { + return (super.contract as GnosisSafe).getModules() + } + + async isModuleEnabled(moduleAddress: string): Promise { + return (super.contract as GnosisSafe).isModuleEnabled(moduleAddress) + } +} + +export default GnosisSafeContract_V1_2_0_Ethers diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts new file mode 100644 index 000000000..26b697673 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts @@ -0,0 +1,18 @@ +import { GnosisSafe } from '../../../../typechain/src/web3-v1/v1.2.0/gnosis_safe' +import GnosisSafeContractWeb3 from '../GnosisSafeContractWeb3' + +class GnosisSafeContract_V1_2_0_Web3 extends GnosisSafeContractWeb3 { + constructor(public contract: GnosisSafe) { + super(contract) + } + + async getModules(): Promise { + return (super.contract as GnosisSafe).methods.getModules().call() + } + + async isModuleEnabled(moduleAddress: string): Promise { + return (super.contract as GnosisSafe).methods.isModuleEnabled(moduleAddress).call() + } +} + +export default GnosisSafeContract_V1_2_0_Web3 diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts new file mode 100644 index 000000000..bc0477332 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts @@ -0,0 +1,21 @@ +import { GnosisSafe } from '../../../../typechain/src/ethers-v5/v1.3.0/GnosisSafe' +import { SENTINEL_ADDRESS } from '../../../utils/constants' +import GnosisSafeContractEthers from '../GnosisSafeContractEthers' + +class GnosisSafeContract_V1_3_0_Ethers extends GnosisSafeContractEthers { + constructor(public contract: GnosisSafe) { + super(contract) + } + + async getModules(): Promise { + const asdf = (super.contract as GnosisSafe).getModulesPaginated(SENTINEL_ADDRESS, 10) + console.log({ asdf }) + return [''] + } + + async isModuleEnabled(moduleAddress: string): Promise { + return (super.contract as GnosisSafe).isModuleEnabled(moduleAddress) + } +} + +export default GnosisSafeContract_V1_3_0_Ethers diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts new file mode 100644 index 000000000..9095664ca --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts @@ -0,0 +1,23 @@ +import { GnosisSafe } from '../../../../typechain/src/web3-v1/v1.3.0/gnosis_safe' +import { SENTINEL_ADDRESS } from '../../../utils/constants' +import GnosisSafeContractWeb3 from '../GnosisSafeContractWeb3' + +class GnosisSafeContract_V1_3_0_Web3 extends GnosisSafeContractWeb3 { + constructor(public contract: GnosisSafe) { + super(contract) + } + + async getModules(): Promise { + const asdf = (super.contract as GnosisSafe).methods + .getModulesPaginated(SENTINEL_ADDRESS, 10) + .call() + console.log({ asdf }) + return [''] + } + + async isModuleEnabled(moduleAddress: string): Promise { + return (super.contract as GnosisSafe).methods.isModuleEnabled(moduleAddress).call() + } +} + +export default GnosisSafeContract_V1_3_0_Web3 From 6f8ce4abcca14dc2248398c24a9785c60bf2a140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:23:39 +0100 Subject: [PATCH 17/35] Add all SafeProxyFactory classes depending on the version --- ...ract.ts => GnosisSafeProxyFactoryEthersContract.ts} | 9 +++++---- .../GnosisSafeProxyFactoryWeb3Contract.ts | 5 +++-- .../GnosisSafeProxyFactoryContract_V1_1_1_Ethers.ts | 10 ++++++++++ .../GnosisSafeProxyFactoryContract_V1_1_1_Web3.ts | 10 ++++++++++ .../GnosisSafeProxyFactoryContract_V1_3_0_Ethers.ts | 10 ++++++++++ .../GnosisSafeProxyFactoryContract_V1_3_0_Web3.ts | 10 ++++++++++ 6 files changed, 48 insertions(+), 6 deletions(-) rename packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/{GnosisSafeProxyFactoryEthersV5Contract.ts => GnosisSafeProxyFactoryEthersContract.ts} (74%) create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Web3.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Web3.ts diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersContract.ts similarity index 74% rename from packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts rename to packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersContract.ts index 579a6b93a..0f14e16ed 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersContract.ts @@ -1,9 +1,10 @@ import { ContractTransaction, Event } from '@ethersproject/contracts' -import { ProxyFactory } from '../../../typechain/src/ethers-v5/v1.3.0/ProxyFactory' +import { ProxyFactory as ProxyFactory_V1_1_1 } from '../../../typechain/src/ethers-v5/v1.1.1/ProxyFactory' +import { ProxyFactory as ProxyFactory_V1_3_0 } from '../../../typechain/src/ethers-v5/v1.3.0/ProxyFactory' import GnosisSafeProxyFactoryContract, { CreateProxyProps } from './GnosisSafeProxyFactoryContract' -class GnosisSafeProxyFactoryEthersV5Contract implements GnosisSafeProxyFactoryContract { - constructor(public contract: ProxyFactory) {} +class GnosisSafeProxyFactoryEthersContract implements GnosisSafeProxyFactoryContract { + constructor(public contract: ProxyFactory_V1_3_0 | ProxyFactory_V1_1_1) {} getAddress(): string { return this.contract.address @@ -42,4 +43,4 @@ class GnosisSafeProxyFactoryEthersV5Contract implements GnosisSafeProxyFactoryCo } } -export default GnosisSafeProxyFactoryEthersV5Contract +export default GnosisSafeProxyFactoryEthersContract diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts index ea70bed8f..2de5b629e 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract.ts @@ -1,9 +1,10 @@ import { PromiEvent, TransactionReceipt } from 'web3-core/types' -import { ProxyFactory } from '../../../typechain/src/web3-v1/v1.3.0/proxy_factory' +import { ProxyFactory as ProxyFactory_V1_1_1 } from '../../../typechain/src/web3-v1/v1.1.1/proxy_factory' +import { ProxyFactory as ProxyFactory_V1_3_0 } from '../../../typechain/src/web3-v1/v1.3.0/proxy_factory' import GnosisSafeProxyFactoryContract, { CreateProxyProps } from './GnosisSafeProxyFactoryContract' class GnosisSafeProxyFactoryWeb3Contract implements GnosisSafeProxyFactoryContract { - constructor(public contract: ProxyFactory) {} + constructor(public contract: ProxyFactory_V1_3_0 | ProxyFactory_V1_1_1) {} getAddress(): string { return this.contract.options.address diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Ethers.ts new file mode 100644 index 000000000..6a822ce09 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Ethers.ts @@ -0,0 +1,10 @@ +import { ProxyFactory } from '../../../../typechain/src/ethers-v5/v1.1.1/ProxyFactory' +import GnosisSafeProxyFactoryEthersContract from '../GnosisSafeProxyFactoryEthersContract' + +class GnosisSafeProxyFactoryContract_V1_1_1_Ethers extends GnosisSafeProxyFactoryEthersContract { + constructor(public contract: ProxyFactory) { + super(contract) + } +} + +export default GnosisSafeProxyFactoryContract_V1_1_1_Ethers diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Web3.ts new file mode 100644 index 000000000..0bbcf5b03 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Web3.ts @@ -0,0 +1,10 @@ +import { ProxyFactory } from '../../../../typechain/src/web3-v1/v1.1.1/proxy_factory' +import GnosisSafeProxyFactoryWeb3Contract from '../GnosisSafeProxyFactoryWeb3Contract' + +class GnosisSafeProxyFactoryContract_V1_1_1_Web3 extends GnosisSafeProxyFactoryWeb3Contract { + constructor(public contract: ProxyFactory) { + super(contract) + } +} + +export default GnosisSafeProxyFactoryContract_V1_1_1_Web3 diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Ethers.ts new file mode 100644 index 000000000..d66447ad3 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Ethers.ts @@ -0,0 +1,10 @@ +import { ProxyFactory } from '../../../../typechain/src/ethers-v5/v1.3.0/ProxyFactory' +import GnosisSafeProxyFactoryEthersContract from '../GnosisSafeProxyFactoryEthersContract' + +class GnosisSafeProxyFactoryContract_V1_3_0_Ethers extends GnosisSafeProxyFactoryEthersContract { + constructor(public contract: ProxyFactory) { + super(contract) + } +} + +export default GnosisSafeProxyFactoryContract_V1_3_0_Ethers diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Web3.ts new file mode 100644 index 000000000..31c559cce --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Web3.ts @@ -0,0 +1,10 @@ +import { ProxyFactory } from '../../../../typechain/src/web3-v1/v1.3.0/proxy_factory' +import GnosisSafeProxyFactoryWeb3Contract from '../GnosisSafeProxyFactoryWeb3Contract' + +class GnosisSafeProxyFactoryContract_V1_3_0_Web3 extends GnosisSafeProxyFactoryWeb3Contract { + constructor(public contract: ProxyFactory) { + super(contract) + } +} + +export default GnosisSafeProxyFactoryContract_V1_3_0_Web3 From 975fefeca6557d4db940b2c84d47ff14386a8128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:25:20 +0100 Subject: [PATCH 18/35] Add all MultiSendContract classes depending on the version --- .../MultiSend/MultiSendEthersContract.ts | 20 +++++++++++++++++++ .../MultiSend/MultiSendEthersV5Contract.ts | 16 --------------- .../MultiSend/MultiSendWeb3Contract.ts | 7 ++++--- .../v1.1.1/MultiSendContract_V1_1_1_Ethers.ts | 10 ++++++++++ .../v1.1.1/MultiSendContract_V1_1_1_Web3.ts | 10 ++++++++++ .../v1.3.0/MultiSendContract_V1_3_0_Ethers.ts | 10 ++++++++++ .../v1.3.0/MultiSendContract_V1_3_0_Web3.ts | 10 ++++++++++ 7 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersContract.ts delete mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts create mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Web3.ts create mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Ethers.ts create mode 100644 packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Web3.ts diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersContract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersContract.ts new file mode 100644 index 000000000..ac5542919 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersContract.ts @@ -0,0 +1,20 @@ +import { MultiSend as MultiSend_V1_1_1 } from '../../../typechain/src/ethers-v5/v1.1.1/MultiSend' +import { + MultiSend as MultiSend_V1_3_0, + MultiSendInterface +} from '../../../typechain/src/ethers-v5/v1.3.0/MultiSend' +import MultiSendContract from './MultiSendContract' + +abstract class MultiSendEthersContract implements MultiSendContract { + constructor(public contract: MultiSend_V1_1_1 | MultiSend_V1_3_0) {} + + getAddress(): string { + return this.contract.address + } + + encode: MultiSendInterface['encodeFunctionData'] = (methodName: any, params: any): string => { + return this.contract.interface.encodeFunctionData(methodName, params) + } +} + +export default MultiSendEthersContract diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts deleted file mode 100644 index 406a412d1..000000000 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendEthersV5Contract.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { MultiSend, MultiSendInterface } from '../../../typechain/src/ethers-v5/v1.3.0/MultiSend' -import MultiSendContract from './MultiSendContract' - -class MultiSendEthersV5Contract implements MultiSendContract { - constructor(public contract: MultiSend) {} - - getAddress(): string { - return this.contract.address - } - - encode: MultiSendInterface['encodeFunctionData'] = (methodName: any, params: any): string => { - return this.contract.interface.encodeFunctionData(methodName, params) - } -} - -export default MultiSendEthersV5Contract diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts index 4d11d9290..db1f5201b 100644 --- a/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts +++ b/packages/safe-core-sdk/src/contracts/MultiSend/MultiSendWeb3Contract.ts @@ -1,8 +1,9 @@ -import { MultiSend } from '../../../typechain/src/web3-v1/v1.3.0/multi_send' +import { MultiSend as MultiSend_V1_1_1 } from '../../../typechain/src/web3-v1/v1.1.1/multi_send' +import { MultiSend as MultiSend_V1_3_0 } from '../../../typechain/src/web3-v1/v1.3.0/multi_send' import MultiSendContract from './MultiSendContract' -class MultiSendWeb3Contract implements MultiSendContract { - constructor(public contract: MultiSend) {} +abstract class MultiSendWeb3Contract implements MultiSendContract { + constructor(public contract: MultiSend_V1_3_0 | MultiSend_V1_1_1) {} getAddress(): string { return this.contract.options.address diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Ethers.ts b/packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Ethers.ts new file mode 100644 index 000000000..c280443ef --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Ethers.ts @@ -0,0 +1,10 @@ +import { MultiSend } from '../../../../typechain/src/ethers-v5/v1.1.1/MultiSend' +import MultiSendEthersContract from '../MultiSendEthersContract' + +class MultiSendContract_V1_1_1_Ethers extends MultiSendEthersContract { + constructor(public contract: MultiSend) { + super(contract) + } +} + +export default MultiSendContract_V1_1_1_Ethers diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Web3.ts b/packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Web3.ts new file mode 100644 index 000000000..6bfb026d6 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/MultiSend/v1.1.1/MultiSendContract_V1_1_1_Web3.ts @@ -0,0 +1,10 @@ +import { MultiSend } from '../../../../typechain/src/web3-v1/v1.1.1/multi_send' +import MultiSendWeb3Contract from '../MultiSendWeb3Contract' + +class MultiSendContract_V1_1_1_Web3 extends MultiSendWeb3Contract { + constructor(public contract: MultiSend) { + super(contract) + } +} + +export default MultiSendContract_V1_1_1_Web3 diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Ethers.ts b/packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Ethers.ts new file mode 100644 index 000000000..685542fbe --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Ethers.ts @@ -0,0 +1,10 @@ +import { MultiSend } from '../../../../typechain/src/ethers-v5/v1.3.0/MultiSend' +import MultiSendEthersContract from '../MultiSendEthersContract' + +class MultiSendContract_V1_3_0_Ethers extends MultiSendEthersContract { + constructor(public contract: MultiSend) { + super(contract) + } +} + +export default MultiSendContract_V1_3_0_Ethers diff --git a/packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Web3.ts b/packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Web3.ts new file mode 100644 index 000000000..abdcd4a70 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/MultiSend/v1.3.0/MultiSendContract_V1_3_0_Web3.ts @@ -0,0 +1,10 @@ +import { MultiSend } from '../../../../typechain/src/web3-v1/v1.3.0/multi_send' +import MultiSendWeb3Contract from '../MultiSendWeb3Contract' + +class MultiSendContract_V1_3_0_Web3 extends MultiSendWeb3Contract { + constructor(public contract: MultiSend) { + super(contract) + } +} + +export default MultiSendContract_V1_3_0_Web3 From 68cffd3d7822fc20f0957e28267ec3df5d638e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:26:34 +0100 Subject: [PATCH 19/35] Remove typechain files generation for v1.0.0 --- packages/safe-core-sdk/scripts/generateTypechainFiles.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts index 92dc2d416..11d4081d5 100644 --- a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts +++ b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts @@ -68,14 +68,12 @@ const web3V1 = 'web3-v1' const ethersV5 = 'ethers-v5' // Src: Web3 V1 types -generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.0.0'`, getSafeDeploymentsContracts('v1.0.0')) generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.1.1'`, getSafeDeploymentsContracts('v1.1.1')) generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.2.0'`, getSafeDeploymentsContracts('v1.2.0')) generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.3.0'`, getSafeDeploymentsContracts('v1.3.0')) moveTypechainFiles(web3V1, typeChainDirectorySrcPath, typeChainDirectoryBuildPath) // Src: Ethers V5 types -generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.0.0'`, getSafeDeploymentsContracts('v1.0.0')) generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.1.1'`, getSafeDeploymentsContracts('v1.1.1')) generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.2.0'`, getSafeDeploymentsContracts('v1.2.0')) generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.3.0'`, getSafeDeploymentsContracts('v1.3.0')) From 57ccb4246fb65c9c839843ea34411d9f5b02e70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:27:36 +0100 Subject: [PATCH 20/35] Rename SAFE_LAST_VERSION constant --- .../safe-core-sdk/src/contracts/safeDeploymentContracts.ts | 2 +- packages/safe-core-sdk/src/safeFactory/index.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts index 40b0308a7..e0e05f975 100644 --- a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts +++ b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts @@ -7,7 +7,7 @@ import { export type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' -export const DEFAULT_SAFE_VERSION: SafeVersion = '1.3.0' +export const SAFE_LAST_VERSION: SafeVersion = '1.3.0' const safeDeploymentsVersions = { '1.3.0': { diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index d813725ea..0f251023d 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -1,6 +1,6 @@ import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' -import { DEFAULT_SAFE_VERSION, SafeVersion } from '../contracts/safeDeploymentContracts' +import { SafeVersion, SAFE_LAST_VERSION } from '../contracts/safeDeploymentContracts' import EthAdapter from '../ethereumLibs/EthAdapter' import Safe from '../Safe' import { ContractNetworksConfig } from '../types' @@ -49,7 +49,7 @@ class SafeFactory { static async create({ ethAdapter, - safeVersion = DEFAULT_SAFE_VERSION, + safeVersion = SAFE_LAST_VERSION, contractNetworks }: SafeFactoryConfig): Promise { const safeFactorySdk = new SafeFactory() @@ -136,7 +136,7 @@ class SafeFactory { chainId, safeAddress ) - const safe = Safe.create({ + const safe = await Safe.create({ ethAdapter: this.#ethAdapter, safeAddress: safeContract.getAddress(), contractNetworks: this.#contractNetworks From 005318490d92ee60400af6b3f6da202fd877f730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:31:16 +0100 Subject: [PATCH 21/35] Get Safe contracts typed instances depending on the version --- .../src/contracts/contractInstancesEthers.ts | 69 +++++++++++++++++++ .../src/contracts/contractInstancesWeb3.ts | 59 ++++++++++++++++ .../src/ethereumLibs/EthersAdapter.ts | 35 ++++------ .../src/ethereumLibs/Web3Adapter.ts | 20 +++--- .../src/managers/contractManager.ts | 6 +- 5 files changed, 158 insertions(+), 31 deletions(-) create mode 100644 packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts create mode 100644 packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts diff --git a/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts b/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts new file mode 100644 index 000000000..aa309a4b0 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts @@ -0,0 +1,69 @@ +import { Signer } from '@ethersproject/abstract-signer' +import { GnosisSafe__factory as SafeMasterCopy_V1_1_1 } from '../../typechain/src/ethers-v5/v1.1.1/factories/GnosisSafe__factory' +import { MultiSend__factory as MultiSend_V1_1_1 } from '../../typechain/src/ethers-v5/v1.1.1/factories/MultiSend__factory' +import { ProxyFactory__factory as SafeProxyFactory_V1_1_1 } from '../../typechain/src/ethers-v5/v1.1.1/factories/ProxyFactory__factory' +import { GnosisSafe__factory as SafeMasterCopy_V1_2_0 } from '../../typechain/src/ethers-v5/v1.2.0/factories/GnosisSafe__factory' +import { GnosisSafe__factory as SafeMasterCopy_V1_3_0 } from '../../typechain/src/ethers-v5/v1.3.0/factories/GnosisSafe__factory' +import { MultiSend__factory as MultiSend_V1_3_0 } from '../../typechain/src/ethers-v5/v1.3.0/factories/MultiSend__factory' +import { ProxyFactory__factory as SafeProxyFactory_V1_3_0 } from '../../typechain/src/ethers-v5/v1.3.0/factories/ProxyFactory__factory' +import GnosisSafeContract_V1_1_1_Ethers from './GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Ethers' +import GnosisSafeContract_V1_2_0_Ethers from './GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers' +import GnosisSafeContract_V1_3_0_Ethers from './GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers' +import GnosisSafeProxyFactoryContract_V1_1_1_Ethers from './GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Ethers' +import GnosisSafeProxyFactoryContract_V1_3_0_Ethers from './GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Ethers' +import MultiSendContract_V1_1_1_Ethers from './MultiSend/v1.1.1/MultiSendContract_V1_1_1_Ethers' +import MultiSendContract_V1_3_0_Ethers from './MultiSend/v1.3.0/MultiSendContract_V1_3_0_Ethers' +import { SafeVersion } from './safeDeploymentContracts' + +export function getSafeContractInstance( + safeVersion: SafeVersion, + contractAddress: string, + signer: Signer +) { + let safeContract + switch (safeVersion) { + case '1.3.0': + safeContract = SafeMasterCopy_V1_3_0.connect(contractAddress, signer) + return new GnosisSafeContract_V1_3_0_Ethers(safeContract) + case '1.2.0': + safeContract = SafeMasterCopy_V1_2_0.connect(contractAddress, signer) + return new GnosisSafeContract_V1_2_0_Ethers(safeContract) + case '1.1.1': + safeContract = SafeMasterCopy_V1_1_1.connect(contractAddress, signer) + return new GnosisSafeContract_V1_1_1_Ethers(safeContract) + } +} + +export function getMultiSendContractInstance( + safeVersion: SafeVersion, + contractAddress: string, + signer: Signer +) { + let multiSendContract + switch (safeVersion) { + case '1.3.0': + multiSendContract = MultiSend_V1_3_0.connect(contractAddress, signer) + return new MultiSendContract_V1_3_0_Ethers(multiSendContract) + case '1.2.0': + case '1.1.1': + multiSendContract = MultiSend_V1_1_1.connect(contractAddress, signer) + return new MultiSendContract_V1_1_1_Ethers(multiSendContract) + } +} + +export function getSafeProxyFactoryContractInstance( + safeVersion: SafeVersion, + contractAddress: string, + signer: Signer +) { + let gnosisSafeProxyFactoryContract + switch (safeVersion) { + case '1.3.0': + gnosisSafeProxyFactoryContract = SafeProxyFactory_V1_3_0.connect(contractAddress, signer) + return new GnosisSafeProxyFactoryContract_V1_3_0_Ethers(gnosisSafeProxyFactoryContract) + case '1.2.0': + case '1.1.1': + gnosisSafeProxyFactoryContract = SafeProxyFactory_V1_1_1.connect(contractAddress, signer) + return new GnosisSafeProxyFactoryContract_V1_1_1_Ethers(gnosisSafeProxyFactoryContract) + } +} diff --git a/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts b/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts new file mode 100644 index 000000000..4a9a4f320 --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts @@ -0,0 +1,59 @@ +import { GnosisSafe as SafeMasterCopy_V1_1_1 } from '../../typechain/src/web3-v1/v1.1.1/gnosis_safe' +import { MultiSend as MultiSend_V1_1_1 } from '../../typechain/src/web3-v1/v1.1.1/multi_send' +import { ProxyFactory as GnosisSafeProxyFactory_V1_1_1 } from '../../typechain/src/web3-v1/v1.1.1/proxy_factory' +import { GnosisSafe as SafeMasterCopy_V1_2_0 } from '../../typechain/src/web3-v1/v1.2.0/gnosis_safe' +import { GnosisSafe as SafeMasterCopy_V1_3_0 } from '../../typechain/src/web3-v1/v1.3.0/gnosis_safe' +import { MultiSend as MultiSend_V1_3_0 } from '../../typechain/src/web3-v1/v1.3.0/multi_send' +import { ProxyFactory as GnosisSafeProxyFactory_V1_3_0 } from '../../typechain/src/web3-v1/v1.3.0/proxy_factory' +import GnosisSafeContract_V1_1_1_Web3 from './GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Web3' +import GnosisSafeContract_V1_2_0_Web3 from './GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3' +import GnosisSafeContract_V1_3_0_Web3 from './GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3' +import GnosisSafeProxyFactoryContract_V1_1_1_Web3 from './GnosisSafeProxyFactory/v1.1.1/GnosisSafeProxyFactoryContract_V1_1_1_Web3' +import GnosisSafeProxyFactoryContract_V1_3_0_Web3 from './GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Web3' +import MultiSendContract_V1_1_1_Web3 from './MultiSend/v1.1.1/MultiSendContract_V1_1_1_Web3' +import MultiSendContract_V1_3_0_Web3 from './MultiSend/v1.3.0/MultiSendContract_V1_3_0_Web3' +import { SafeVersion } from './safeDeploymentContracts' + +export function getSafeContractInstance( + safeVersion: SafeVersion, + safeContract: SafeMasterCopy_V1_3_0 | SafeMasterCopy_V1_2_0 | SafeMasterCopy_V1_1_1 +) { + switch (safeVersion) { + case '1.3.0': + return new GnosisSafeContract_V1_3_0_Web3(safeContract as SafeMasterCopy_V1_3_0) + case '1.2.0': + return new GnosisSafeContract_V1_2_0_Web3(safeContract as SafeMasterCopy_V1_2_0) + case '1.1.1': + return new GnosisSafeContract_V1_1_1_Web3(safeContract as SafeMasterCopy_V1_1_1) + } +} + +export function getMultiSendContractInstance( + safeVersion: SafeVersion, + multiSendContract: MultiSend_V1_3_0 | MultiSend_V1_1_1 +) { + switch (safeVersion) { + case '1.3.0': + return new MultiSendContract_V1_3_0_Web3(multiSendContract as MultiSend_V1_3_0) + case '1.2.0': + case '1.1.1': + return new MultiSendContract_V1_1_1_Web3(multiSendContract as MultiSend_V1_1_1) + } +} + +export function getGnosisSafeProxyFactoryContractInstance( + safeVersion: SafeVersion, + gnosisSafeProxyFactoryContract: GnosisSafeProxyFactory_V1_3_0 | GnosisSafeProxyFactory_V1_1_1 +) { + switch (safeVersion) { + case '1.3.0': + return new GnosisSafeProxyFactoryContract_V1_3_0_Web3( + gnosisSafeProxyFactoryContract as GnosisSafeProxyFactory_V1_3_0 + ) + case '1.2.0': + case '1.1.1': + return new GnosisSafeProxyFactoryContract_V1_1_1_Web3( + gnosisSafeProxyFactoryContract as GnosisSafeProxyFactory_V1_1_1 + ) + } +} diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index 4f3895648..f529a7b29 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -3,12 +3,14 @@ import { Signer } from '@ethersproject/abstract-signer' import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' import { Provider } from '@ethersproject/providers' -import { GnosisSafe__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/GnosisSafe__factory' -import { MultiSend__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/MultiSend__factory' -import { ProxyFactory__factory } from '../../typechain/src/ethers-v5/v1.3.0/factories/ProxyFactory__factory' -import GnosisSafeContractEthersV5 from '../contracts/GnosisSafe/GnosisSafeContractEthersV5' -import GnosisSafeProxyFactoryEthersV5Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersV5Contract' -import MultiSendEthersV5Contract from '../contracts/MultiSend/MultiSendEthersV5Contract' +import { + getMultiSendContractInstance, + getSafeContractInstance, + getSafeProxyFactoryContractInstance +} from '../contracts/contractInstancesEthers' +import GnosisSafeContractEthers from '../contracts/GnosisSafe/GnosisSafeContractEthers' +import GnosisSafeProxyFactoryEthersContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryEthersContract' +import MultiSendEthersContract from '../contracts/MultiSend/MultiSendEthersContract' import { getMultiSendContractDeployment, getSafeContractDeployment, @@ -66,67 +68,58 @@ class EthersAdapter implements EthAdapter { safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress } else { const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) - console.log({ safeSingletonDeployment }) contractAddress = safeSingletonDeployment?.networkAddresses[chainId] ?? safeSingletonDeployment?.defaultAddress - console.log({ contractAddress }) } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy contract is not deployed in the current network') } - const safeContract = GnosisSafe__factory.connect(contractAddress, this.#signer) - return new GnosisSafeContractEthersV5(safeContract) + return getSafeContractInstance(safeVersion, contractAddress, this.#signer) } async getMultiSendContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress } else { const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) - console.log({ multiSendDeployment }) contractAddress = multiSendDeployment?.networkAddresses[chainId] ?? multiSendDeployment?.defaultAddress - console.log({ contractAddress }) } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Multi Send contract is not deployed in the current network') } - const multiSendContract = MultiSend__factory.connect(contractAddress, this.#signer) - return new MultiSendEthersV5Contract(multiSendContract) + return getMultiSendContractInstance(safeVersion, contractAddress, this.#signer) } async getSafeProxyFactoryContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress } else { const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) - console.log({ proxyFactoryDeployment }) contractAddress = proxyFactoryDeployment?.networkAddresses[chainId] ?? proxyFactoryDeployment?.defaultAddress - console.log({ contractAddress }) } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy Factory contract is not deployed in the current network') } - const proxyFactoryContract = ProxyFactory__factory.connect(contractAddress, this.#signer) - return new GnosisSafeProxyFactoryEthersV5Contract(proxyFactoryContract) + return getSafeProxyFactoryContractInstance(safeVersion, contractAddress, this.#signer) } getContract(address: string, abi: AbiItem[]): Contract { diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index 2ebe67b0f..676f852e0 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -1,7 +1,9 @@ import { BigNumber } from '@ethersproject/bignumber' -import { GnosisSafe } from '../../typechain/src/web3-v1/v1.3.0/gnosis_safe' -import { MultiSend } from '../../typechain/src/web3-v1/v1.3.0/multi_send' -import { ProxyFactory } from '../../typechain/src/web3-v1/v1.3.0/proxy_factory' +import { + getGnosisSafeProxyFactoryContractInstance, + getMultiSendContractInstance, + getSafeContractInstance +} from '../contracts/contractInstancesWeb3' import GnosisSafeContractWeb3 from '../contracts/GnosisSafe/GnosisSafeContractWeb3' import GnosisSafeProxyFactoryWeb3Contract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryWeb3Contract' import MultiSendWeb3Contract from '../contracts/MultiSend/MultiSendWeb3Contract' @@ -61,8 +63,8 @@ class Web3Adapter implements EthAdapter { const safeContract = this.getContract( contractAddress, safeSingletonDeployment?.abi as AbiItem[] - ) as GnosisSafe - return new GnosisSafeContractWeb3(safeContract) + ) + return getSafeContractInstance(safeVersion, safeContract) } async getMultiSendContract( @@ -81,8 +83,8 @@ class Web3Adapter implements EthAdapter { const multiSendContract = this.getContract( contractAddress, multiSendDeployment?.abi as AbiItem[] - ) as MultiSend - return new MultiSendWeb3Contract(multiSendContract) + ) + return getMultiSendContractInstance(safeVersion, multiSendContract) } async getSafeProxyFactoryContract( @@ -101,8 +103,8 @@ class Web3Adapter implements EthAdapter { const proxyFactoryContract = this.getContract( contractAddress, proxyFactoryDeployment?.abi as AbiItem[] - ) as ProxyFactory - return new GnosisSafeProxyFactoryWeb3Contract(proxyFactoryContract) + ) + return getGnosisSafeProxyFactoryContractInstance(safeVersion, proxyFactoryContract) } getContract(address: string, abi: AbiItem[]): any { diff --git a/packages/safe-core-sdk/src/managers/contractManager.ts b/packages/safe-core-sdk/src/managers/contractManager.ts index 6ba8de9f3..e3b9d7c41 100644 --- a/packages/safe-core-sdk/src/managers/contractManager.ts +++ b/packages/safe-core-sdk/src/managers/contractManager.ts @@ -26,7 +26,11 @@ class ContractManager { ): Promise { const chainId = await ethAdapter.getChainId() const baseSafeVersion: SafeVersion = '1.1.1' - const temporarySafeContract = await ethAdapter.getSafeContract(baseSafeVersion, chainId, safeAddress) + const temporarySafeContract = await ethAdapter.getSafeContract( + baseSafeVersion, + chainId, + safeAddress + ) const safeVersion = (await temporarySafeContract.getVersion()) as SafeVersion const customContracts = contractNetworks?.[chainId] From 3f54e61e870e7bf4c784f7fee4d3061d66c2ace5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 2 Nov 2021 00:35:49 +0100 Subject: [PATCH 22/35] Stop using defaultAddress from safe-deployments --- .../src/ethereumLibs/EthersAdapter.ts | 10 +++------- .../safe-core-sdk/src/ethereumLibs/Web3Adapter.ts | 15 +++------------ 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index f529a7b29..581c93fcc 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -74,9 +74,7 @@ class EthersAdapter implements EthAdapter { contractAddress = customContractAddress } else { const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) - contractAddress = - safeSingletonDeployment?.networkAddresses[chainId] ?? - safeSingletonDeployment?.defaultAddress + contractAddress = safeSingletonDeployment?.networkAddresses[chainId] } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy contract is not deployed in the current network') @@ -94,8 +92,7 @@ class EthersAdapter implements EthAdapter { contractAddress = customContractAddress } else { const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) - contractAddress = - multiSendDeployment?.networkAddresses[chainId] ?? multiSendDeployment?.defaultAddress + contractAddress = multiSendDeployment?.networkAddresses[chainId] } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Multi Send contract is not deployed in the current network') @@ -113,8 +110,7 @@ class EthersAdapter implements EthAdapter { contractAddress = customContractAddress } else { const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) - contractAddress = - proxyFactoryDeployment?.networkAddresses[chainId] ?? proxyFactoryDeployment?.defaultAddress + contractAddress = proxyFactoryDeployment?.networkAddresses[chainId] } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy Factory contract is not deployed in the current network') diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index 676f852e0..a40bc52a0 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -53,10 +53,7 @@ class Web3Adapter implements EthAdapter { customContractAddress?: string ): Promise { const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) - const contractAddress = - customContractAddress ?? - safeSingletonDeployment?.networkAddresses[chainId] ?? - safeSingletonDeployment?.defaultAddress + const contractAddress = customContractAddress ?? safeSingletonDeployment?.networkAddresses[chainId] if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy contract is not deployed in the current network') } @@ -73,10 +70,7 @@ class Web3Adapter implements EthAdapter { customContractAddress?: string ): Promise { const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) - const contractAddress = - customContractAddress ?? - multiSendDeployment?.networkAddresses[chainId] ?? - multiSendDeployment?.defaultAddress + const contractAddress = customContractAddress ?? multiSendDeployment?.networkAddresses[chainId] if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Multi Send contract is not deployed in the current network') } @@ -93,10 +87,7 @@ class Web3Adapter implements EthAdapter { customContractAddress?: string ): Promise { const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) - const contractAddress = - customContractAddress ?? - proxyFactoryDeployment?.networkAddresses[chainId] ?? - proxyFactoryDeployment?.defaultAddress + const contractAddress = customContractAddress ?? proxyFactoryDeployment?.networkAddresses[chainId] if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy Factory contract is not deployed in the current network') } From d9da697c7931fcb51c7659d33d4c5b7c94df0b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Wed, 3 Nov 2021 20:18:12 +0100 Subject: [PATCH 23/35] Compile and generate types for Safe versions --- packages/safe-core-sdk/hardhat.config.ts | 4 +- packages/safe-core-sdk/package.json | 3 +- .../scripts/generateTypechainFiles.ts | 60 ++++++++++++------- yarn.lock | 7 ++- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/packages/safe-core-sdk/hardhat.config.ts b/packages/safe-core-sdk/hardhat.config.ts index b721b0b31..f3071bcb2 100644 --- a/packages/safe-core-sdk/hardhat.config.ts +++ b/packages/safe-core-sdk/hardhat.config.ts @@ -37,7 +37,9 @@ const config: HardhatUserConfig = { defaultNetwork: "hardhat", solidity: { compilers: [ - { version: '0.5.17' } + { version: '0.5.17' }, + { version: '0.5.3' }, + { version: '0.8.0' }, ] }, paths: { diff --git a/packages/safe-core-sdk/package.json b/packages/safe-core-sdk/package.json index 3e56d470c..0de73714d 100644 --- a/packages/safe-core-sdk/package.json +++ b/packages/safe-core-sdk/package.json @@ -38,7 +38,8 @@ ], "homepage": "https://github.com/gnosis/safe-core-sdk#readme", "devDependencies": { - "@gnosis.pm/safe-contracts": "1.2.0", + "@gnosis.pm/safe-contracts-v1.2.0": "npm:@gnosis.pm/safe-contracts@1.2.0", + "@gnosis.pm/safe-contracts-v1.3.0": "npm:@gnosis.pm/safe-contracts@1.3.0", "@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", diff --git a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts index 11d4081d5..11583f900 100644 --- a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts +++ b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts @@ -14,12 +14,28 @@ const typeChainDirectoryBuildPath = path.join(__dirname, `../${outDirBuild}`) // Contract list for which the Typechain files will be generated // Will be included in dist/ folder -const safeContractsPath = '../../node_modules/@gnosis.pm/safe-contracts/build/contracts' -const openZeppelinContractsPath = '../../node_modules/openzeppelin-solidity/build/contracts' +const safeContractsPath = '../../node_modules/@gnosis.pm/safe-deployments/dist/assets' + +const safeContracts_V1_3_0 = [ + `${safeContractsPath}/v1.3.0/gnosis_safe.json`, + `${safeContractsPath}/v1.3.0/proxy_factory.json`, + `${safeContractsPath}/v1.3.0/multi_send.json`, +].join(' ') +const safeContracts_V1_2_0 = [ + `${safeContractsPath}/v1.2.0/gnosis_safe.json`, +].join(' ') +const safeContracts_V1_1_1 = [ + `${safeContractsPath}/v1.1.1/gnosis_safe.json`, + `${safeContractsPath}/v1.1.1/proxy_factory.json`, + `${safeContractsPath}/v1.1.1/multi_send.json`, +].join(' ') + // Won't be included in dist/ folder +const safeContractsTestPath = '../../node_modules/@gnosis.pm/safe-contracts-v1.2.0/contracts' +const openZeppelinContractsPath = '../../node_modules/openzeppelin-solidity/build/contracts' const testContracts = [ - `${safeContractsPath}/DailyLimitModule.json`, - `${safeContractsPath}/SocialRecoveryModule.json`, + `${safeContractsTestPath}/DailyLimitModule.json`, + `${safeContractsTestPath}/SocialRecoveryModule.json`, `${openZeppelinContractsPath}/ERC20Mintable.json` ].join(' ') @@ -42,42 +58,42 @@ function generateTypechainFiles(typechainVersion, outDir, contractList) { } // Copy Typechain files with the right extension (.d.ts -> .ts) allows them to be included in the build folder -function moveTypechainFiles(typechainVersion, inDir, outDir) { - readdir(`${inDir}${typechainVersion}`, (error, files) => { +function moveTypechainFiles(inDir, outDir) { + readdir(`${inDir}`, (error, files) => { if (error) { console.log(error) } - if (!existsSync(`${outDir}${typechainVersion}`)) { - mkdirSync(`${outDir}${typechainVersion}`, { recursive: true }) + if (!existsSync(`${outDir}`)) { + mkdirSync(`${outDir}`, { recursive: true }) } files.forEach(file => { const pattern = /.d.ts/ if (!file.match(pattern)) { return } - execSync(`cp ${inDir}${typechainVersion}/${file} ${outDir}${typechainVersion}/${file}`) + execSync(`cp ${inDir}/${file} ${outDir}/${file}`) }) }) } -function getSafeDeploymentsContracts(contractVersion) { - return `../../node_modules/@gnosis.pm/safe-deployments/dist/assets/${contractVersion}/*.json` -} - const web3V1 = 'web3-v1' const ethersV5 = 'ethers-v5' // Src: Web3 V1 types -generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.1.1'`, getSafeDeploymentsContracts('v1.1.1')) -generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.2.0'`, getSafeDeploymentsContracts('v1.2.0')) -generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/'v1.3.0'`, getSafeDeploymentsContracts('v1.3.0')) -moveTypechainFiles(web3V1, typeChainDirectorySrcPath, typeChainDirectoryBuildPath) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/v1.3.0`, safeContracts_V1_3_0) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/v1.2.0`, safeContracts_V1_2_0) +generateTypechainFiles(web3V1, `${outDirSrc}${web3V1}/v1.1.1`, safeContracts_V1_1_1) +moveTypechainFiles(`${typeChainDirectorySrcPath}${web3V1}/v1.3.0`, `${typeChainDirectoryBuildPath}${web3V1}/v1.3.0`) +moveTypechainFiles(`${typeChainDirectorySrcPath}${web3V1}/v1.2.0`, `${typeChainDirectoryBuildPath}${web3V1}/v1.2.0`) +moveTypechainFiles(`${typeChainDirectorySrcPath}${web3V1}/v1.1.1`, `${typeChainDirectoryBuildPath}${web3V1}/v1.1.1`) // Src: Ethers V5 types -generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.1.1'`, getSafeDeploymentsContracts('v1.1.1')) -generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.2.0'`, getSafeDeploymentsContracts('v1.2.0')) -generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/'v1.3.0'`, getSafeDeploymentsContracts('v1.3.0')) -moveTypechainFiles(ethersV5, typeChainDirectorySrcPath, typeChainDirectoryBuildPath) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/v1.3.0`, safeContracts_V1_3_0) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/v1.2.0`, safeContracts_V1_2_0) +generateTypechainFiles(ethersV5, `${outDirSrc}${ethersV5}/v1.1.1`, safeContracts_V1_1_1) +moveTypechainFiles(`${typeChainDirectorySrcPath}${ethersV5}/v1.3.0`, `${typeChainDirectoryBuildPath}${ethersV5}/v1.3.0`) +moveTypechainFiles(`${typeChainDirectorySrcPath}${ethersV5}/v1.2.0`, `${typeChainDirectoryBuildPath}${ethersV5}/v1.2.0`) +moveTypechainFiles(`${typeChainDirectorySrcPath}${ethersV5}/v1.1.1`, `${typeChainDirectoryBuildPath}${ethersV5}/v1.1.1`) // Tests: Ethers V5 types -generateTypechainFiles(ethersV5, `${outDirTests}${ethersV5}`, testContracts) +generateTypechainFiles(ethersV5, outDirTests, testContracts) diff --git a/yarn.lock b/yarn.lock index 611d68c19..d34ca8d56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,7 +1126,7 @@ "@ethersproject/properties" "^5.4.0" "@ethersproject/strings" "^5.4.0" -"@gnosis.pm/safe-contracts@1.2.0": +"@gnosis.pm/safe-contracts-v1.2.0@npm:@gnosis.pm/safe-contracts@1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.2.0.tgz#33e8332e09c19e8822fccb06c7d3eff806d091f6" integrity sha512-lcpZodqztDgMICB0kAc8aJdQePwCaLJnbeNjgVTfLAo3fBckVRV06VHXg5IsZ26qLA4JfZ690Cb7TsDVE9ZF3w== @@ -1138,6 +1138,11 @@ solc "0.5.17" truffle "^5.1.21" +"@gnosis.pm/safe-contracts-v1.3.0@npm:@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/safe-core-sdk@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-core-sdk/-/safe-core-sdk-0.3.1.tgz#15171657490a90ac3773b6965c2af4b873af136f" From 8cdde74ad9cf1f58fb8e42ca00a8a50850eec718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 4 Nov 2021 01:10:32 +0100 Subject: [PATCH 24/35] Fix typechain script for contracts in tests --- packages/safe-core-sdk/scripts/generateTypechainFiles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts index 11583f900..e62be815f 100644 --- a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts +++ b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts @@ -31,7 +31,7 @@ const safeContracts_V1_1_1 = [ ].join(' ') // Won't be included in dist/ folder -const safeContractsTestPath = '../../node_modules/@gnosis.pm/safe-contracts-v1.2.0/contracts' +const safeContractsTestPath = '../../node_modules/@gnosis.pm/safe-contracts-v1.2.0/build/contracts' const openZeppelinContractsPath = '../../node_modules/openzeppelin-solidity/build/contracts' const testContracts = [ `${safeContractsTestPath}/DailyLimitModule.json`, @@ -96,4 +96,4 @@ moveTypechainFiles(`${typeChainDirectorySrcPath}${ethersV5}/v1.2.0`, `${typeChai moveTypechainFiles(`${typeChainDirectorySrcPath}${ethersV5}/v1.1.1`, `${typeChainDirectoryBuildPath}${ethersV5}/v1.1.1`) // Tests: Ethers V5 types -generateTypechainFiles(ethersV5, outDirTests, testContracts) +generateTypechainFiles(ethersV5, `${outDirTests}${ethersV5}`, testContracts) From 60ed6a1a81f1e34dba748088bf6a0a83688b5ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 4 Nov 2021 01:12:34 +0100 Subject: [PATCH 25/35] Setup contracts deployment in tests --- packages/safe-core-sdk/contracts/Deps.sol | 8 ---- .../safe-core-sdk/contracts/Deps_V1_2_0.sol | 13 +++++++ .../safe-core-sdk/contracts/Deps_V1_3_0.sol | 10 +++++ .../hardhat/deploy/deploy-contracts.ts | 34 +++++++++++++++-- .../tests/utils/setupContracts.ts | 38 +++++++++---------- 5 files changed, 73 insertions(+), 30 deletions(-) delete mode 100644 packages/safe-core-sdk/contracts/Deps.sol create mode 100644 packages/safe-core-sdk/contracts/Deps_V1_2_0.sol create mode 100644 packages/safe-core-sdk/contracts/Deps_V1_3_0.sol diff --git a/packages/safe-core-sdk/contracts/Deps.sol b/packages/safe-core-sdk/contracts/Deps.sol deleted file mode 100644 index 29f702a84..000000000 --- a/packages/safe-core-sdk/contracts/Deps.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma solidity >=0.5.0 <0.7.0; - -import { GnosisSafeProxyFactory } from "@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol"; -import { GnosisSafe } from "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol"; -import { MultiSend } from "@gnosis.pm/safe-contracts/contracts/libraries/MultiSend.sol"; -import { DailyLimitModule } from "@gnosis.pm/safe-contracts/contracts/modules/DailyLimitModule.sol"; -import { SocialRecoveryModule } from "@gnosis.pm/safe-contracts/contracts/modules/SocialRecoveryModule.sol"; -import { ERC20Mintable } from "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; diff --git a/packages/safe-core-sdk/contracts/Deps_V1_2_0.sol b/packages/safe-core-sdk/contracts/Deps_V1_2_0.sol new file mode 100644 index 000000000..a365e9702 --- /dev/null +++ b/packages/safe-core-sdk/contracts/Deps_V1_2_0.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.5.0 <0.9.0; + +import { GnosisSafeProxyFactory } from "@gnosis.pm/safe-contracts-v1.2.0/contracts/proxies/GnosisSafeProxyFactory.sol"; +import { GnosisSafe } from "@gnosis.pm/safe-contracts-v1.2.0/contracts/GnosisSafe.sol"; +import { MultiSend } from "@gnosis.pm/safe-contracts-v1.2.0/contracts/libraries/MultiSend.sol"; +import { DailyLimitModule } from "@gnosis.pm/safe-contracts-v1.2.0/contracts/modules/DailyLimitModule.sol"; +import { SocialRecoveryModule } from "@gnosis.pm/safe-contracts-v1.2.0/contracts/modules/SocialRecoveryModule.sol"; +import { ERC20Mintable } from "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; + +contract ProxyFactory_SV1_2_0 is GnosisSafeProxyFactory {} +contract GnosisSafe_SV1_2_0 is GnosisSafe {} +contract MultiSend_SV1_2_0 is MultiSend {} diff --git a/packages/safe-core-sdk/contracts/Deps_V1_3_0.sol b/packages/safe-core-sdk/contracts/Deps_V1_3_0.sol new file mode 100644 index 000000000..122460b1e --- /dev/null +++ b/packages/safe-core-sdk/contracts/Deps_V1_3_0.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.7.0 <0.9.0; + +import { GnosisSafeProxyFactory } from "@gnosis.pm/safe-contracts-v1.3.0/contracts/proxies/GnosisSafeProxyFactory.sol"; +import { GnosisSafe } from "@gnosis.pm/safe-contracts-v1.3.0/contracts/GnosisSafe.sol"; +import { MultiSend } from "@gnosis.pm/safe-contracts-v1.3.0/contracts/libraries/MultiSend.sol"; + +contract ProxyFactory_SV1_3_0 is GnosisSafeProxyFactory {} +contract GnosisSafe_SV1_3_0 is GnosisSafe {} +contract MultiSend_SV1_3_0 is MultiSend {} diff --git a/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts b/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts index f016a79f4..460ff3c37 100644 --- a/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts +++ b/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts @@ -1,26 +1,54 @@ import { DeployFunction } from 'hardhat-deploy/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' +type SafeVersion = 'v1.3.0' | 'v1.2.0' | 'v1.1.1' + +export const safeVersion = process.env.SAFE_VERSION as SafeVersion + +const gnosisSafeContracts = { + 'v1.3.0': { name: 'GnosisSafe_SV1_3_0' }, + 'v1.2.0': { name: 'GnosisSafe_SV1_2_0' }, + 'v1.1.1': { name: 'GnosisSafe_SV1_1_1' } +} + +const proxyFactoryContracts = { + 'v1.3.0': { name: 'ProxyFactory_SV1_3_0' }, + 'v1.2.0': { name: 'ProxyFactory_SV1_2_0' }, + 'v1.1.1': { name: 'ProxyFactory_SV1_1_1' } +} + +const multiSendContracts = { + 'v1.3.0': { name: 'MultiSend_SV1_3_0' }, + 'v1.2.0': { name: 'MultiSend_SV1_2_0' }, + 'v1.1.1': { name: 'MultiSend_SV1_1_1' } +} + +export const gnosisSafeDeployed = gnosisSafeContracts[safeVersion] +export const proxyFactoryDeployed = proxyFactoryContracts[safeVersion] +export const multiSendDeployed = multiSendContracts[safeVersion] + const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { deployments, getNamedAccounts } = hre const { deployer } = await getNamedAccounts() const { deploy } = deployments - await deploy('GnosisSafe', { + console.log(`Deploying Safe contracts ${safeVersion}`) + + await deploy(gnosisSafeDeployed.name, { from: deployer, args: [], log: true, deterministicDeployment: true }) - await deploy('GnosisSafeProxyFactory', { + await deploy(proxyFactoryDeployed.name, { from: deployer, args: [], log: true, deterministicDeployment: true }) - await deploy('MultiSend', { + await deploy(multiSendDeployed.name, { from: deployer, args: [], log: true, diff --git a/packages/safe-core-sdk/tests/utils/setupContracts.ts b/packages/safe-core-sdk/tests/utils/setupContracts.ts index bc42036db..89b208fbb 100644 --- a/packages/safe-core-sdk/tests/utils/setupContracts.ts +++ b/packages/safe-core-sdk/tests/utils/setupContracts.ts @@ -1,38 +1,38 @@ import { AddressZero } from '@ethersproject/constants' import { deployments, ethers } from 'hardhat' -import { GnosisSafe } from '../../typechain/src/ethers-v5/v1.3.0/GnosisSafe' -import { MultiSend } from '../../typechain/src/ethers-v5/v1.3.0/MultiSend' +import { + gnosisSafeDeployed, + multiSendDeployed, + proxyFactoryDeployed +} from '../../hardhat/deploy/deploy-contracts' import { DailyLimitModule, ERC20Mintable, SocialRecoveryModule } from '../../typechain/tests/ethers-v5' -export const getSafeSingleton = async () => { - const SafeDeployment = await deployments.get('GnosisSafe') - const Safe = await ethers.getContractFactory('GnosisSafe') +export const getSafeSingleton = async (): Promise => { + const SafeDeployment = await deployments.get(gnosisSafeDeployed.name) + const Safe = await ethers.getContractFactory(gnosisSafeDeployed.name) return Safe.attach(SafeDeployment.address) } -export const getFactory = async () => { - const FactoryDeployment = await deployments.get('GnosisSafeProxyFactory') - const Factory = await ethers.getContractFactory('GnosisSafeProxyFactory') +export const getFactory = async (): Promise => { + const FactoryDeployment = await deployments.get(proxyFactoryDeployed.name) + const Factory = await ethers.getContractFactory(proxyFactoryDeployed.name) return Factory.attach(FactoryDeployment.address) } -export const getSafeTemplate = async (): Promise => { +export const getSafeTemplate = async (): Promise => { const singleton = await getSafeSingleton() const factory = await getFactory() const template = await factory.callStatic.createProxy(singleton.address, '0x') await factory.createProxy(singleton.address, '0x').then((tx: any) => tx.wait()) - const Safe = await ethers.getContractFactory('GnosisSafe') - return Safe.attach(template) as GnosisSafe + const Safe = await ethers.getContractFactory(gnosisSafeDeployed.name) + return Safe.attach(template) } -export const getSafeWithOwners = async ( - owners: string[], - threshold?: number -): Promise => { +export const getSafeWithOwners = async (owners: string[], threshold?: number): Promise => { const template = await getSafeTemplate() await template.setup( owners, @@ -47,10 +47,10 @@ export const getSafeWithOwners = async ( return template } -export const getMultiSend = async (): Promise => { - const MultiSendDeployment = await deployments.get('MultiSend') - const MultiSend = await ethers.getContractFactory('MultiSend') - return MultiSend.attach(MultiSendDeployment.address) as MultiSend +export const getMultiSend = async (): Promise => { + const MultiSendDeployment = await deployments.get(multiSendDeployed.name) + const MultiSend = await ethers.getContractFactory(multiSendDeployed.name) + return MultiSend.attach(MultiSendDeployment.address) } export const getDailyLimitModule = async (): Promise => { From 4f0f05ff5c36727a2b0ad93d1e4c7202e1e0fcd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Thu, 4 Nov 2021 01:35:50 +0100 Subject: [PATCH 26/35] Fix implementation of GnosisSafeContract classes --- .../v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts | 4 ++-- .../GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts | 4 ++-- .../v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts | 7 +++---- .../GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts | 9 +++------ 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts index abf64f42c..10131c451 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers.ts @@ -7,11 +7,11 @@ class GnosisSafeContract_V1_2_0_Ethers extends GnosisSafeContractEthers { } async getModules(): Promise { - return (super.contract as GnosisSafe).getModules() + return this.contract.getModules() } async isModuleEnabled(moduleAddress: string): Promise { - return (super.contract as GnosisSafe).isModuleEnabled(moduleAddress) + return this.contract.isModuleEnabled(moduleAddress) } } diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts index 26b697673..075ff93fd 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3.ts @@ -7,11 +7,11 @@ class GnosisSafeContract_V1_2_0_Web3 extends GnosisSafeContractWeb3 { } async getModules(): Promise { - return (super.contract as GnosisSafe).methods.getModules().call() + return this.contract.methods.getModules().call() } async isModuleEnabled(moduleAddress: string): Promise { - return (super.contract as GnosisSafe).methods.isModuleEnabled(moduleAddress).call() + return this.contract.methods.isModuleEnabled(moduleAddress).call() } } diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts index bc0477332..56db6ccfe 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers.ts @@ -8,13 +8,12 @@ class GnosisSafeContract_V1_3_0_Ethers extends GnosisSafeContractEthers { } async getModules(): Promise { - const asdf = (super.contract as GnosisSafe).getModulesPaginated(SENTINEL_ADDRESS, 10) - console.log({ asdf }) - return [''] + const { array } = await this.contract.getModulesPaginated(SENTINEL_ADDRESS, 10) + return array } async isModuleEnabled(moduleAddress: string): Promise { - return (super.contract as GnosisSafe).isModuleEnabled(moduleAddress) + return this.contract.isModuleEnabled(moduleAddress) } } diff --git a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts index 9095664ca..5ecd81220 100644 --- a/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts +++ b/packages/safe-core-sdk/src/contracts/GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3.ts @@ -8,15 +8,12 @@ class GnosisSafeContract_V1_3_0_Web3 extends GnosisSafeContractWeb3 { } async getModules(): Promise { - const asdf = (super.contract as GnosisSafe).methods - .getModulesPaginated(SENTINEL_ADDRESS, 10) - .call() - console.log({ asdf }) - return [''] + const { array } = await this.contract.methods.getModulesPaginated(SENTINEL_ADDRESS, 10).call() + return array } async isModuleEnabled(moduleAddress: string): Promise { - return (super.contract as GnosisSafe).methods.isModuleEnabled(moduleAddress).call() + return this.contract.methods.isModuleEnabled(moduleAddress).call() } } From 853ffa90c3e51f52b215915942f4ea93469cbb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 5 Nov 2021 18:04:38 +0100 Subject: [PATCH 27/35] Remove "v" from Safe version numbers --- .../hardhat/deploy/deploy-contracts.ts | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts b/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts index 460ff3c37..dc705c3d7 100644 --- a/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts +++ b/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts @@ -1,39 +1,37 @@ import { DeployFunction } from 'hardhat-deploy/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' -type SafeVersion = 'v1.3.0' | 'v1.2.0' | 'v1.1.1' +type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' -export const safeVersion = process.env.SAFE_VERSION as SafeVersion +export const safeVersionDeployed = process.env.SAFE_VERSION as SafeVersion const gnosisSafeContracts = { - 'v1.3.0': { name: 'GnosisSafe_SV1_3_0' }, - 'v1.2.0': { name: 'GnosisSafe_SV1_2_0' }, - 'v1.1.1': { name: 'GnosisSafe_SV1_1_1' } + '1.3.0': { name: 'GnosisSafe_SV1_3_0' }, + '1.2.0': { name: 'GnosisSafe_SV1_2_0' }, + '1.1.1': { name: 'GnosisSafe_SV1_1_1' } } const proxyFactoryContracts = { - 'v1.3.0': { name: 'ProxyFactory_SV1_3_0' }, - 'v1.2.0': { name: 'ProxyFactory_SV1_2_0' }, - 'v1.1.1': { name: 'ProxyFactory_SV1_1_1' } + '1.3.0': { name: 'ProxyFactory_SV1_3_0' }, + '1.2.0': { name: 'ProxyFactory_SV1_2_0' }, + '1.1.1': { name: 'ProxyFactory_SV1_1_1' } } const multiSendContracts = { - 'v1.3.0': { name: 'MultiSend_SV1_3_0' }, - 'v1.2.0': { name: 'MultiSend_SV1_2_0' }, - 'v1.1.1': { name: 'MultiSend_SV1_1_1' } + '1.3.0': { name: 'MultiSend_SV1_3_0' }, + '1.2.0': { name: 'MultiSend_SV1_2_0' }, + '1.1.1': { name: 'MultiSend_SV1_1_1' } } -export const gnosisSafeDeployed = gnosisSafeContracts[safeVersion] -export const proxyFactoryDeployed = proxyFactoryContracts[safeVersion] -export const multiSendDeployed = multiSendContracts[safeVersion] +export const gnosisSafeDeployed = gnosisSafeContracts[safeVersionDeployed] +export const proxyFactoryDeployed = proxyFactoryContracts[safeVersionDeployed] +export const multiSendDeployed = multiSendContracts[safeVersionDeployed] const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { deployments, getNamedAccounts } = hre const { deployer } = await getNamedAccounts() const { deploy } = deployments - console.log(`Deploying Safe contracts ${safeVersion}`) - await deploy(gnosisSafeDeployed.name, { from: deployer, args: [], From e3d7deca8f81be8ee54f27176cfc8a3cfff70e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 5 Nov 2021 18:06:01 +0100 Subject: [PATCH 28/35] Add support to L2 Safe contracts --- .../src/contracts/safeDeploymentContracts.ts | 37 ++++++++++++++++++- .../src/ethereumLibs/Web3Adapter.ts | 6 ++- .../safe-core-sdk/src/safeFactory/index.ts | 8 ++-- .../safe-core-sdk/tests/execution.test.ts | 3 +- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts index e0e05f975..bcf2ccbb2 100644 --- a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts +++ b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts @@ -1,6 +1,8 @@ import { + DeploymentFilter, getMultiSendDeployment, getProxyFactoryDeployment, + getSafeL2SingletonDeployment, getSafeSingletonDeployment, SingletonDeployment } from '@gnosis.pm/safe-deployments' @@ -12,27 +14,60 @@ export const SAFE_LAST_VERSION: SafeVersion = '1.3.0' const safeDeploymentsVersions = { '1.3.0': { safeMasterCopyVersion: '1.3.0', + safeMasterCopyL2Version: '1.3.0', safeProxyFactoryVersion: '1.3.0', multiSendVersion: '1.3.0' }, '1.2.0': { safeMasterCopyVersion: '1.2.0', + safeMasterCopyL2Version: undefined, safeProxyFactoryVersion: '1.1.1', multiSendVersion: '1.1.1' }, '1.1.1': { safeMasterCopyVersion: '1.1.1', + safeMasterCopyL2Version: undefined, safeProxyFactoryVersion: '1.1.1', multiSendVersion: '1.1.1' } } +const safeDeploymentsL1ChainIds = [ + 1, // Ethereum Mainnet + 4, // Ethereum Testnet Rinkeby + 5, // Ethereum Testnet Goerli + 42 // Ethereum Testnet Kovan +] + +/* +const safeDeploymentsL2ChainIds = [ + 56, // Binance Smart Chain Mainnet + 100, // xDAI Chain + 137, // Polygon Mainnet + 246, // Energy Web Chain + 42161, // Arbitrum One + 73799, // Energy Web Volta Testnet + + 69, // Optimistic Ethereum Network + 1285, // Moonriver + 1287, // Moonbase Alpha + 4002, // Fantom Testnet + 42220, // Celo Mainnet + 43114, // Avalanche Mainnet + 333999 // Polis Mainnet +] +*/ + export function getSafeContractDeployment( safeVersion: SafeVersion, chainId: number ): SingletonDeployment | undefined { const version = safeDeploymentsVersions[safeVersion].safeMasterCopyVersion - return getSafeSingletonDeployment({ version, network: chainId.toString(), released: true }) + const filters: DeploymentFilter = { version, network: chainId.toString(), released: true } + if (safeDeploymentsL1ChainIds.includes(chainId)) { + return getSafeSingletonDeployment(filters) + } + return getSafeL2SingletonDeployment(filters) } export function getMultiSendContractDeployment( diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index a40bc52a0..b8d5a3030 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -53,7 +53,8 @@ class Web3Adapter implements EthAdapter { customContractAddress?: string ): Promise { const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) - const contractAddress = customContractAddress ?? safeSingletonDeployment?.networkAddresses[chainId] + const contractAddress = + customContractAddress ?? safeSingletonDeployment?.networkAddresses[chainId] if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy contract is not deployed in the current network') } @@ -87,7 +88,8 @@ class Web3Adapter implements EthAdapter { customContractAddress?: string ): Promise { const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) - const contractAddress = customContractAddress ?? proxyFactoryDeployment?.networkAddresses[chainId] + const contractAddress = + customContractAddress ?? proxyFactoryDeployment?.networkAddresses[chainId] if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { throw new Error('Safe Proxy Factory contract is not deployed in the current network') } diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index 0f251023d..cea1250c9 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -87,6 +87,10 @@ class SafeFactory { return this.#safeVersion } + getAddress() { + return this.#safeProxyFactoryContract.getAddress() + } + async getChainId(): Promise { return this.#ethAdapter.getChainId() } @@ -113,10 +117,6 @@ class SafeFactory { ]) } - getAddress() { - return this.#safeProxyFactoryContract.getAddress() - } - async deploySafe( safeAccountConfig: SafeAccountConfig, safeDeploymentConfig?: SafeDeploymentConfig diff --git a/packages/safe-core-sdk/tests/execution.test.ts b/packages/safe-core-sdk/tests/execution.test.ts index dc6067980..a48396119 100644 --- a/packages/safe-core-sdk/tests/execution.test.ts +++ b/packages/safe-core-sdk/tests/execution.test.ts @@ -3,6 +3,7 @@ import { MetaTransactionData, SafeTransactionDataPartial } from '@gnosis.pm/safe import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import { deployments, waffle } from 'hardhat' +import { safeVersionDeployed } from '../hardhat/deploy/deploy-contracts' import Safe, { ContractNetworksConfig, TransactionOptions } from '../src' import { getERC20Mintable, @@ -141,7 +142,7 @@ describe('Transactions execution', () => { await safeSdk1.signTransaction(tx) await chai .expect(safeSdk2.executeTransaction(tx)) - .to.be.rejectedWith('Invalid owner provided') + .to.be.rejectedWith(safeVersionDeployed === '1.3.0' ? 'GS026' : 'Invalid owner provided') }) it('should execute a transaction with threshold 1', async () => { From 8194cc366f785e233026f09963fe9e8f0125cfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 5 Nov 2021 18:29:33 +0100 Subject: [PATCH 29/35] Fix tests when handling multiple versions --- .../tests/contractManager.test.ts | 4 +- packages/safe-core-sdk/tests/core.test.ts | 5 +- .../safe-core-sdk/tests/safeFactory.test.ts | 54 ++++++++++++++++--- packages/safe-core-sdk/tests/utils/helpers.ts | 1 + 4 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 packages/safe-core-sdk/tests/utils/helpers.ts diff --git a/packages/safe-core-sdk/tests/contractManager.test.ts b/packages/safe-core-sdk/tests/contractManager.test.ts index 5fa505df8..6bac9c08c 100644 --- a/packages/safe-core-sdk/tests/contractManager.test.ts +++ b/packages/safe-core-sdk/tests/contractManager.test.ts @@ -46,7 +46,7 @@ describe('Safe contracts manager', () => { safeAddress: safe.address }) ) - .to.be.rejectedWith('Safe Proxy contract is not deployed in the current network') + .to.be.rejectedWith('Multi Send contract is not deployed in the current network') }) it('should fail if Safe Proxy contract is not deployed in the current network', async () => { @@ -83,7 +83,7 @@ describe('Safe contracts manager', () => { contractNetworks: customContractNetworks }) ) - .to.be.rejectedWith('Safe Proxy contract is not deployed in the current network') + .to.be.rejectedWith('Multi Send contract is not deployed in the current network') }) it('should set the MultiSend contract available in the current network', async () => { diff --git a/packages/safe-core-sdk/tests/core.test.ts b/packages/safe-core-sdk/tests/core.test.ts index 880329b5e..264ffa63d 100644 --- a/packages/safe-core-sdk/tests/core.test.ts +++ b/packages/safe-core-sdk/tests/core.test.ts @@ -3,6 +3,7 @@ import { SafeTransactionDataPartial } from '@gnosis.pm/safe-core-sdk-types' import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import { deployments, waffle } from 'hardhat' +import { safeVersionDeployed } from '../hardhat/deploy/deploy-contracts' import Safe, { ContractNetworksConfig } from '../src' import { getFactory, @@ -16,7 +17,7 @@ import { waitSafeTxReceipt } from './utils/transactions' chai.use(chaiAsPromised) -describe('Safe Core SDK', () => { +describe('Safe Info', () => { const setupTests = deployments.createFixture(async ({ deployments }) => { await deployments.fixture() const accounts = await getAccounts() @@ -78,7 +79,7 @@ describe('Safe Core SDK', () => { contractNetworks }) const contractVersion = await safeSdk.getContractVersion() - chai.expect(contractVersion).to.be.eq('1.2.0') + chai.expect(contractVersion).to.be.eq(safeVersionDeployed) }) }) diff --git a/packages/safe-core-sdk/tests/safeFactory.test.ts b/packages/safe-core-sdk/tests/safeFactory.test.ts index 40b353d64..2959d84c7 100644 --- a/packages/safe-core-sdk/tests/safeFactory.test.ts +++ b/packages/safe-core-sdk/tests/safeFactory.test.ts @@ -1,12 +1,15 @@ import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import { deployments, waffle } from 'hardhat' +import { safeVersionDeployed } from '../hardhat/deploy/deploy-contracts' import { ContractNetworksConfig, SafeAccountConfig, SafeDeploymentConfig, SafeFactory } from '../src' +import { SAFE_LAST_VERSION } from '../src/contracts/safeDeploymentContracts' +import { itif } from './utils/helpers' import { getFactory, getMultiSend, getSafeSingleton } from './utils/setupContracts' import { getEthAdapter } from './utils/setupEthAdapter' import { getAccounts } from './utils/setupTestNetwork' @@ -39,7 +42,7 @@ describe('Safe Proxy Factory', () => { const ethAdapter = await getEthAdapter(account1.signer) chai .expect(SafeFactory.create({ ethAdapter })) - .rejectedWith('Safe Proxy contract is not deployed in the current network') + .rejectedWith('Safe Proxy Factory contract is not deployed in the current network') }) it('should instantiate the Safe Proxy Factory', async () => { @@ -120,13 +123,15 @@ describe('Safe Proxy Factory', () => { const { accounts, contractNetworks } = await setupTests() const [account1, account2] = accounts const ethAdapter = await getEthAdapter(account1.signer) - const safeFactory = await SafeFactory.create({ ethAdapter, contractNetworks }) + const safeFactory = await SafeFactory.create({ + ethAdapter, + safeVersion: safeVersionDeployed, + contractNetworks + }) const owners = [account1.address, account2.address] const threshold = 2 const safeAccountConfig: SafeAccountConfig = { owners, threshold } const safe = await safeFactory.deploySafe(safeAccountConfig) - const contractCodeFinal = ethAdapter.getContractCode(safe.getAddress()) - chai.expect(contractCodeFinal).to.not.be.eq('0x') const deployedSafeOwners = await safe.getOwners() chai.expect(deployedSafeOwners.toString()).to.be.eq(owners.toString()) const deployedSafeThreshold = await safe.getThreshold() @@ -137,18 +142,53 @@ describe('Safe Proxy Factory', () => { const { accounts, contractNetworks } = await setupTests() const [account1, account2] = accounts const ethAdapter = await getEthAdapter(account1.signer) - const safeFactory = await SafeFactory.create({ ethAdapter, contractNetworks }) + const safeFactory = await SafeFactory.create({ + ethAdapter, + safeVersion: safeVersionDeployed, + contractNetworks + }) const owners = [account1.address, account2.address] const threshold = 2 const safeAccountConfig: SafeAccountConfig = { owners, threshold } const safeDeploymentConfig: SafeDeploymentConfig = { saltNonce: 1 } const safe = await safeFactory.deploySafe(safeAccountConfig, safeDeploymentConfig) - const contractCodeFinal = ethAdapter.getContractCode(safe.getAddress()) - chai.expect(contractCodeFinal).to.not.be.eq('0x') const deployedSafeOwners = await safe.getOwners() chai.expect(deployedSafeOwners.toString()).to.be.eq(owners.toString()) const deployedSafeThreshold = await safe.getThreshold() chai.expect(deployedSafeThreshold).to.be.eq(threshold) }) + + itif(safeVersionDeployed === SAFE_LAST_VERSION)( + 'should deploy last Safe version by default', + async () => { + const { accounts, contractNetworks } = await setupTests() + const [account1, account2] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeFactory = await SafeFactory.create({ ethAdapter, contractNetworks }) + const owners = [account1.address, account2.address] + const threshold = 2 + const safeAccountConfig: SafeAccountConfig = { owners, threshold } + const safe = await safeFactory.deploySafe(safeAccountConfig) + const safeInstanceVersion = await safe.getContractVersion() + chai.expect(safeInstanceVersion).to.be.eq(safeVersionDeployed) + } + ) + + it('should deploy a specific Safe version', async () => { + const { accounts, contractNetworks } = await setupTests() + const [account1, account2] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeFactory = await SafeFactory.create({ + ethAdapter, + safeVersion: safeVersionDeployed, + contractNetworks + }) + const owners = [account1.address, account2.address] + const threshold = 2 + const safeAccountConfig: SafeAccountConfig = { owners, threshold } + const safe = await safeFactory.deploySafe(safeAccountConfig) + const safeInstanceVersion = await safe.getContractVersion() + chai.expect(safeInstanceVersion).to.be.eq(safeVersionDeployed) + }) }) }) diff --git a/packages/safe-core-sdk/tests/utils/helpers.ts b/packages/safe-core-sdk/tests/utils/helpers.ts new file mode 100644 index 000000000..c3e7a1264 --- /dev/null +++ b/packages/safe-core-sdk/tests/utils/helpers.ts @@ -0,0 +1 @@ +export const itif = (condition: boolean) => (condition ? it : it.skip) From 3f52d51cbfedeb09d7099f6685f40d03ac4d2f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Fri, 5 Nov 2021 21:24:12 +0100 Subject: [PATCH 30/35] Update CI tests --- .../workflows/{test.yml => test_V1_2_0.yml} | 2 +- .github/workflows/test_V1_3_0.yml | 20 +++++++++++++++++++ packages/safe-core-sdk/package.json | 14 ++++++++----- 3 files changed, 30 insertions(+), 6 deletions(-) rename .github/workflows/{test.yml => test_V1_2_0.yml} (91%) create mode 100644 .github/workflows/test_V1_3_0.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test_V1_2_0.yml similarity index 91% rename from .github/workflows/test.yml rename to .github/workflows/test_V1_2_0.yml index 2f3d4b0b0..2b78c11c1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test_V1_2_0.yml @@ -17,4 +17,4 @@ jobs: - run: | yarn install yarn build - yarn test + yarn test:hardhat:ethers:v1.2.0 diff --git a/.github/workflows/test_V1_3_0.yml b/.github/workflows/test_V1_3_0.yml new file mode 100644 index 000000000..6f0cef56d --- /dev/null +++ b/.github/workflows/test_V1_3_0.yml @@ -0,0 +1,20 @@ +name: Hardhat Test +on: [push, pull_request] +env: + INFURA_KEY: ${{ secrets.INFURA_KEY }} +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [14.x] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: | + yarn install + yarn build + yarn test:hardhat:ethers:v1.3.0 diff --git a/packages/safe-core-sdk/package.json b/packages/safe-core-sdk/package.json index 0de73714d..c4c91f8da 100644 --- a/packages/safe-core-sdk/package.json +++ b/packages/safe-core-sdk/package.json @@ -14,11 +14,15 @@ "typechain": "node scripts/generateTypechainFiles.ts", "unbuild": "rimraf dist artifacts cache .nyc_output typechain", "build": "hardhat compile && yarn typechain && tsc", - "test:ganache:web3": "export TEST_NETWORK=ganache && export ETH_LIB=web3 && hardhat --network localhost deploy && nyc hardhat --network localhost test", - "test:ganache:ethers": "export TEST_NETWORK=ganache && export ETH_LIB=ethers && hardhat --network localhost deploy && nyc hardhat --network localhost test", - "test:hardhat:web3": "export TEST_NETWORK=hardhat && export ETH_LIB=web3 && hardhat deploy && nyc hardhat test", - "test:hardhat:ethers": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && hardhat deploy && nyc hardhat test", - "test": "yarn test:hardhat:ethers", + "test:ganache:web3:v1.2.0": "export TEST_NETWORK=ganache && export ETH_LIB=web3 && export SAFE_VERSION=1.2.0 && hardhat --network localhost deploy && nyc hardhat --network localhost test", + "test:ganache:web3:v1.3.0": "export TEST_NETWORK=ganache && export ETH_LIB=web3 && export SAFE_VERSION=1.3.0 && hardhat --network localhost deploy && nyc hardhat --network localhost test", + "test:ganache:ethers:v1.2.0": "export TEST_NETWORK=ganache && export ETH_LIB=ethers && export SAFE_VERSION=1.2.0 && hardhat --network localhost deploy && nyc hardhat --network localhost test", + "test:ganache:ethers:v1.3.0": "export TEST_NETWORK=ganache && export ETH_LIB=ethers && export SAFE_VERSION=1.3.0 && hardhat --network localhost deploy && nyc hardhat --network localhost test", + "test:hardhat:web3:v1.2.0": "export TEST_NETWORK=hardhat && export ETH_LIB=web3 && export SAFE_VERSION=1.2.0 && hardhat deploy && nyc hardhat test", + "test:hardhat:web3:v1.3.0": "export TEST_NETWORK=hardhat && export ETH_LIB=web3 && export SAFE_VERSION=1.3.0 && hardhat deploy && nyc hardhat test", + "test:hardhat:ethers:v1.2.0": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && export SAFE_VERSION=1.2.0 && hardhat deploy && nyc hardhat test", + "test:hardhat:ethers:v1.3.0": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && export SAFE_VERSION=1.3.0 && hardhat deploy && nyc hardhat test", + "test": "yarn test:hardhat:ethers:v1.3.0", "coverage": "nyc report --reporter=text-lcov | coveralls", "format": "prettier --write \"{src,tests,hardhat}/**/*.ts\"", "lint": "tslint -p tsconfig.json" From 59dcb93544608d2402519888794a561769cb92e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 8 Nov 2021 11:13:22 +0100 Subject: [PATCH 31/35] Adjust test scripts --- .github/workflows/test.yml | 20 ++++++++++++++++++++ .github/workflows/test_V1_2_0.yml | 3 ++- .github/workflows/test_V1_3_0.yml | 3 ++- packages/safe-core-sdk/package.json | 1 - 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..2387e4a15 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,20 @@ +name: Monorepo Test +on: [push, pull_request] +env: + INFURA_KEY: ${{ secrets.INFURA_KEY }} +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [14.x] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: | + yarn install + yarn build + yarn test diff --git a/.github/workflows/test_V1_2_0.yml b/.github/workflows/test_V1_2_0.yml index 2b78c11c1..8005161d2 100644 --- a/.github/workflows/test_V1_2_0.yml +++ b/.github/workflows/test_V1_2_0.yml @@ -1,4 +1,4 @@ -name: Hardhat Test +name: Safe Core SDK Test (Safe v1.2.0) on: [push, pull_request] env: INFURA_KEY: ${{ secrets.INFURA_KEY }} @@ -17,4 +17,5 @@ jobs: - run: | yarn install yarn build + cd packages/safe-core-sdk yarn test:hardhat:ethers:v1.2.0 diff --git a/.github/workflows/test_V1_3_0.yml b/.github/workflows/test_V1_3_0.yml index 6f0cef56d..9a2056b79 100644 --- a/.github/workflows/test_V1_3_0.yml +++ b/.github/workflows/test_V1_3_0.yml @@ -1,4 +1,4 @@ -name: Hardhat Test +name: Safe Core SDK Test (Safe v1.3.0) on: [push, pull_request] env: INFURA_KEY: ${{ secrets.INFURA_KEY }} @@ -17,4 +17,5 @@ jobs: - run: | yarn install yarn build + cd packages/safe-core-sdk yarn test:hardhat:ethers:v1.3.0 diff --git a/packages/safe-core-sdk/package.json b/packages/safe-core-sdk/package.json index c4c91f8da..fa195ec99 100644 --- a/packages/safe-core-sdk/package.json +++ b/packages/safe-core-sdk/package.json @@ -22,7 +22,6 @@ "test:hardhat:web3:v1.3.0": "export TEST_NETWORK=hardhat && export ETH_LIB=web3 && export SAFE_VERSION=1.3.0 && hardhat deploy && nyc hardhat test", "test:hardhat:ethers:v1.2.0": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && export SAFE_VERSION=1.2.0 && hardhat deploy && nyc hardhat test", "test:hardhat:ethers:v1.3.0": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && export SAFE_VERSION=1.3.0 && hardhat deploy && nyc hardhat test", - "test": "yarn test:hardhat:ethers:v1.3.0", "coverage": "nyc report --reporter=text-lcov | coveralls", "format": "prettier --write \"{src,tests,hardhat}/**/*.ts\"", "lint": "tslint -p tsconfig.json" From 688d29e2b648f46fdbbdf6ca428814d6a72c5969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Mon, 8 Nov 2021 13:28:20 +0100 Subject: [PATCH 32/35] Small fixes regarding types --- packages/safe-core-sdk/README.md | 2 +- .../hardhat/deploy/deploy-contracts.ts | 2 +- .../scripts/generateTypechainFiles.ts | 4 +- .../src/contracts/contractInstancesEthers.ts | 15 +++++-- .../src/contracts/contractInstancesWeb3.ts | 15 +++++-- .../src/contracts/safeDeploymentContracts.ts | 12 +++++- .../src/managers/contractManager.ts | 5 +-- .../safe-core-sdk/src/safeFactory/index.ts | 2 +- .../tests/utils/setupContracts.ts | 41 ++++++++++++++----- 9 files changed, 73 insertions(+), 25 deletions(-) diff --git a/packages/safe-core-sdk/README.md b/packages/safe-core-sdk/README.md index 9fc1b8706..4b82bc7d3 100644 --- a/packages/safe-core-sdk/README.md +++ b/packages/safe-core-sdk/README.md @@ -79,7 +79,7 @@ const safeSdk: Safe = await safeFactory.deploySafe(safeAccountConfig) The method `deploySafe` executes a transaction from `owner1` account, deploys a new Safe and returns an instance of the Safe Core SDK connected to the new Safe. -The `SafeFactory` will deploy by default the last version of the Safe contracts available (currently `v1.3.0`). To deploy an older version of the Safe contracts instantiate the `SafeFactory` adding the property `safeVersion` with the desired version number. +The `SafeFactory` will deploy the last version of the Safe contracts available by default (currently `v1.3.0`). To deploy an older version of the Safe contracts instantiate the `SafeFactory` adding the property `safeVersion` with the desired version number. ```js const safeFactoryV1_1_1 = await SafeFactory.create({ ethAdapter, safeVersion: '1.1.1' }) diff --git a/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts b/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts index dc705c3d7..8916a56d7 100644 --- a/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts +++ b/packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts @@ -27,7 +27,7 @@ export const gnosisSafeDeployed = gnosisSafeContracts[safeVersionDeployed] export const proxyFactoryDeployed = proxyFactoryContracts[safeVersionDeployed] export const multiSendDeployed = multiSendContracts[safeVersionDeployed] -const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { +const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment): Promise => { const { deployments, getNamedAccounts } = hre const { deployer } = await getNamedAccounts() const { deploy } = deployments diff --git a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts index e62be815f..15f056e53 100644 --- a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts +++ b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts @@ -48,7 +48,7 @@ execSync(`rimraf ${outDirSrc} ${outDirTests}`, (error) => { }) // Generate Typechain files -function generateTypechainFiles(typechainVersion, outDir, contractList) { +function generateTypechainFiles(typechainVersion, outDir, contractList): void { execSync(`typechain --target ${typechainVersion} --out-dir ${outDir} ${contractList}`, (error) => { if (error) { console.log(error.message) @@ -58,7 +58,7 @@ function generateTypechainFiles(typechainVersion, outDir, contractList) { } // Copy Typechain files with the right extension (.d.ts -> .ts) allows them to be included in the build folder -function moveTypechainFiles(inDir, outDir) { +function moveTypechainFiles(inDir, outDir): void { readdir(`${inDir}`, (error, files) => { if (error) { console.log(error) diff --git a/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts b/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts index aa309a4b0..d34ffcc59 100644 --- a/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts +++ b/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts @@ -19,7 +19,10 @@ export function getSafeContractInstance( safeVersion: SafeVersion, contractAddress: string, signer: Signer -) { +): + | GnosisSafeContract_V1_3_0_Ethers + | GnosisSafeContract_V1_2_0_Ethers + | GnosisSafeContract_V1_1_1_Ethers { let safeContract switch (safeVersion) { case '1.3.0': @@ -31,6 +34,8 @@ export function getSafeContractInstance( case '1.1.1': safeContract = SafeMasterCopy_V1_1_1.connect(contractAddress, signer) return new GnosisSafeContract_V1_1_1_Ethers(safeContract) + default: + throw new Error('Invalid Safe version') } } @@ -38,7 +43,7 @@ export function getMultiSendContractInstance( safeVersion: SafeVersion, contractAddress: string, signer: Signer -) { +): MultiSendContract_V1_3_0_Ethers | MultiSendContract_V1_1_1_Ethers { let multiSendContract switch (safeVersion) { case '1.3.0': @@ -48,6 +53,8 @@ export function getMultiSendContractInstance( case '1.1.1': multiSendContract = MultiSend_V1_1_1.connect(contractAddress, signer) return new MultiSendContract_V1_1_1_Ethers(multiSendContract) + default: + throw new Error('Invalid Safe version') } } @@ -55,7 +62,7 @@ export function getSafeProxyFactoryContractInstance( safeVersion: SafeVersion, contractAddress: string, signer: Signer -) { +): GnosisSafeProxyFactoryContract_V1_3_0_Ethers | GnosisSafeProxyFactoryContract_V1_1_1_Ethers { let gnosisSafeProxyFactoryContract switch (safeVersion) { case '1.3.0': @@ -65,5 +72,7 @@ export function getSafeProxyFactoryContractInstance( case '1.1.1': gnosisSafeProxyFactoryContract = SafeProxyFactory_V1_1_1.connect(contractAddress, signer) return new GnosisSafeProxyFactoryContract_V1_1_1_Ethers(gnosisSafeProxyFactoryContract) + default: + throw new Error('Invalid Safe version') } } diff --git a/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts b/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts index 4a9a4f320..b2a861343 100644 --- a/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts +++ b/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts @@ -17,7 +17,10 @@ import { SafeVersion } from './safeDeploymentContracts' export function getSafeContractInstance( safeVersion: SafeVersion, safeContract: SafeMasterCopy_V1_3_0 | SafeMasterCopy_V1_2_0 | SafeMasterCopy_V1_1_1 -) { +): + | GnosisSafeContract_V1_3_0_Web3 + | GnosisSafeContract_V1_2_0_Web3 + | GnosisSafeContract_V1_1_1_Web3 { switch (safeVersion) { case '1.3.0': return new GnosisSafeContract_V1_3_0_Web3(safeContract as SafeMasterCopy_V1_3_0) @@ -25,26 +28,30 @@ export function getSafeContractInstance( return new GnosisSafeContract_V1_2_0_Web3(safeContract as SafeMasterCopy_V1_2_0) case '1.1.1': return new GnosisSafeContract_V1_1_1_Web3(safeContract as SafeMasterCopy_V1_1_1) + default: + throw new Error('Invalid Safe version') } } export function getMultiSendContractInstance( safeVersion: SafeVersion, multiSendContract: MultiSend_V1_3_0 | MultiSend_V1_1_1 -) { +): MultiSendContract_V1_3_0_Web3 | MultiSendContract_V1_1_1_Web3 { switch (safeVersion) { case '1.3.0': return new MultiSendContract_V1_3_0_Web3(multiSendContract as MultiSend_V1_3_0) case '1.2.0': case '1.1.1': return new MultiSendContract_V1_1_1_Web3(multiSendContract as MultiSend_V1_1_1) + default: + throw new Error('Invalid Safe version') } } export function getGnosisSafeProxyFactoryContractInstance( safeVersion: SafeVersion, gnosisSafeProxyFactoryContract: GnosisSafeProxyFactory_V1_3_0 | GnosisSafeProxyFactory_V1_1_1 -) { +): GnosisSafeProxyFactoryContract_V1_3_0_Web3 | GnosisSafeProxyFactoryContract_V1_1_1_Web3 { switch (safeVersion) { case '1.3.0': return new GnosisSafeProxyFactoryContract_V1_3_0_Web3( @@ -55,5 +62,7 @@ export function getGnosisSafeProxyFactoryContractInstance( return new GnosisSafeProxyFactoryContract_V1_1_1_Web3( gnosisSafeProxyFactoryContract as GnosisSafeProxyFactory_V1_1_1 ) + default: + throw new Error('Invalid Safe version') } } diff --git a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts index bcf2ccbb2..68db35b21 100644 --- a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts +++ b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts @@ -10,8 +10,18 @@ import { export type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' export const SAFE_LAST_VERSION: SafeVersion = '1.3.0' +export const SAFE_BASE_VERSION: SafeVersion = '1.1.1' -const safeDeploymentsVersions = { +type SafeDeploymentsVersions = { + [version: string]: { + safeMasterCopyVersion: string + safeMasterCopyL2Version: string | undefined + safeProxyFactoryVersion: string + multiSendVersion: string + } +} + +const safeDeploymentsVersions: SafeDeploymentsVersions = { '1.3.0': { safeMasterCopyVersion: '1.3.0', safeMasterCopyL2Version: '1.3.0', diff --git a/packages/safe-core-sdk/src/managers/contractManager.ts b/packages/safe-core-sdk/src/managers/contractManager.ts index e3b9d7c41..df5baeab1 100644 --- a/packages/safe-core-sdk/src/managers/contractManager.ts +++ b/packages/safe-core-sdk/src/managers/contractManager.ts @@ -1,6 +1,6 @@ import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import MultiSendContract from '../contracts/MultiSend/MultiSendContract' -import { SafeVersion } from '../contracts/safeDeploymentContracts' +import { SafeVersion, SAFE_BASE_VERSION } from '../contracts/safeDeploymentContracts' import EthAdapter from '../ethereumLibs/EthAdapter' import { ContractNetworksConfig } from '../types' @@ -25,9 +25,8 @@ class ContractManager { contractNetworks?: ContractNetworksConfig ): Promise { const chainId = await ethAdapter.getChainId() - const baseSafeVersion: SafeVersion = '1.1.1' const temporarySafeContract = await ethAdapter.getSafeContract( - baseSafeVersion, + SAFE_BASE_VERSION, chainId, safeAddress ) diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index cea1250c9..e3e68f629 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -87,7 +87,7 @@ class SafeFactory { return this.#safeVersion } - getAddress() { + getAddress(): string { return this.#safeProxyFactoryContract.getAddress() } diff --git a/packages/safe-core-sdk/tests/utils/setupContracts.ts b/packages/safe-core-sdk/tests/utils/setupContracts.ts index 89b208fbb..f2d5f3a4e 100644 --- a/packages/safe-core-sdk/tests/utils/setupContracts.ts +++ b/packages/safe-core-sdk/tests/utils/setupContracts.ts @@ -5,34 +5,55 @@ import { multiSendDeployed, proxyFactoryDeployed } from '../../hardhat/deploy/deploy-contracts' +import { + GnosisSafe as GnosisSafe_V1_1_1, + MultiSend as MultiSend_V1_1_1, + ProxyFactory as ProxyFactory_V1_1_1 +} from '../../typechain/src/ethers-v5/v1.1.1' +import { GnosisSafe as GnosisSafe_V1_2_0 } from '../../typechain/src/ethers-v5/v1.2.0/' +import { + GnosisSafe as GnosisSafe_V1_3_0, + MultiSend as MultiSend_V1_3_0, + ProxyFactory as ProxyFactory_V1_3_0 +} from '../../typechain/src/ethers-v5/v1.3.0/' import { DailyLimitModule, ERC20Mintable, SocialRecoveryModule } from '../../typechain/tests/ethers-v5' -export const getSafeSingleton = async (): Promise => { +export const getSafeSingleton = async (): Promise< + GnosisSafe_V1_3_0 | GnosisSafe_V1_2_0 | GnosisSafe_V1_1_1 +> => { const SafeDeployment = await deployments.get(gnosisSafeDeployed.name) const Safe = await ethers.getContractFactory(gnosisSafeDeployed.name) - return Safe.attach(SafeDeployment.address) + return Safe.attach(SafeDeployment.address) as + | GnosisSafe_V1_3_0 + | GnosisSafe_V1_2_0 + | GnosisSafe_V1_1_1 } -export const getFactory = async (): Promise => { +export const getFactory = async (): Promise => { const FactoryDeployment = await deployments.get(proxyFactoryDeployed.name) const Factory = await ethers.getContractFactory(proxyFactoryDeployed.name) - return Factory.attach(FactoryDeployment.address) + return Factory.attach(FactoryDeployment.address) as ProxyFactory_V1_3_0 | ProxyFactory_V1_1_1 } -export const getSafeTemplate = async (): Promise => { +export const getSafeTemplate = async (): Promise< + GnosisSafe_V1_3_0 | GnosisSafe_V1_2_0 | GnosisSafe_V1_1_1 +> => { const singleton = await getSafeSingleton() const factory = await getFactory() const template = await factory.callStatic.createProxy(singleton.address, '0x') await factory.createProxy(singleton.address, '0x').then((tx: any) => tx.wait()) const Safe = await ethers.getContractFactory(gnosisSafeDeployed.name) - return Safe.attach(template) + return Safe.attach(template) as GnosisSafe_V1_3_0 | GnosisSafe_V1_2_0 | GnosisSafe_V1_1_1 } -export const getSafeWithOwners = async (owners: string[], threshold?: number): Promise => { +export const getSafeWithOwners = async ( + owners: string[], + threshold?: number +): Promise => { const template = await getSafeTemplate() await template.setup( owners, @@ -44,13 +65,13 @@ export const getSafeWithOwners = async (owners: string[], threshold?: number): P 0, AddressZero ) - return template + return template as GnosisSafe_V1_3_0 | GnosisSafe_V1_2_0 | GnosisSafe_V1_1_1 } -export const getMultiSend = async (): Promise => { +export const getMultiSend = async (): Promise => { const MultiSendDeployment = await deployments.get(multiSendDeployed.name) const MultiSend = await ethers.getContractFactory(multiSendDeployed.name) - return MultiSend.attach(MultiSendDeployment.address) + return MultiSend.attach(MultiSendDeployment.address) as MultiSend_V1_3_0 | MultiSend_V1_1_1 } export const getDailyLimitModule = async (): Promise => { From 4bbea3b68e345d528c98cfb4b85e2773ab47385a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 Nov 2021 04:00:40 +0100 Subject: [PATCH 33/35] Add isL1SafeMasterCopy flag --- packages/safe-core-sdk/src/Safe.ts | 35 ++++++++-- .../safe-core-sdk/src/contracts/config.ts | 38 +++++++++++ .../src/contracts/contractInstancesEthers.ts | 2 +- .../src/contracts/contractInstancesWeb3.ts | 2 +- .../src/contracts/safeDeploymentContracts.ts | 67 ++----------------- .../src/ethereumLibs/EthAdapter.ts | 21 +++--- .../src/ethereumLibs/EthersAdapter.ts | 23 ++++--- .../src/ethereumLibs/Web3Adapter.ts | 23 ++++--- .../src/managers/contractManager.ts | 50 +++++++++----- .../safe-core-sdk/src/safeFactory/index.ts | 31 ++++++--- .../safe-core-sdk/tests/safeFactory.test.ts | 2 +- 11 files changed, 166 insertions(+), 128 deletions(-) create mode 100644 packages/safe-core-sdk/src/contracts/config.ts diff --git a/packages/safe-core-sdk/src/Safe.ts b/packages/safe-core-sdk/src/Safe.ts index 52ad4ea4a..cf927f7c7 100644 --- a/packages/safe-core-sdk/src/Safe.ts +++ b/packages/safe-core-sdk/src/Safe.ts @@ -31,6 +31,8 @@ export interface SafeConfig { ethAdapter: EthAdapter /** safeAddress - The address of the Safe account to use */ safeAddress: string + /** isL1SafeMasterCopy - Forces to use the Gnosis Safe L1 version of the contract instead of the L2 version */ + isL1SafeMasterCopy?: boolean /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig } @@ -40,6 +42,8 @@ export interface ConnectSafeConfig { ethAdapter?: EthAdapter /** safeAddress - The address of the Safe account to use */ safeAddress?: string + /** isL1SafeMasterCopy - Forces to use the Gnosis Safe L1 version of the contract instead of the L2 version */ + isL1SafeMasterCopy?: boolean /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig } @@ -78,9 +82,14 @@ class Safe { * @throws "Safe Proxy contract is not deployed in the current network" * @throws "MultiSend contract is not deployed in the current network" */ - static async create({ ethAdapter, safeAddress, contractNetworks }: SafeConfig): Promise { + static async create({ + ethAdapter, + safeAddress, + isL1SafeMasterCopy, + contractNetworks + }: SafeConfig): Promise { const safeSdk = new Safe() - await safeSdk.init({ ethAdapter, safeAddress, contractNetworks }) + await safeSdk.init({ ethAdapter, safeAddress, isL1SafeMasterCopy, contractNetworks }) return safeSdk } @@ -91,13 +100,19 @@ class Safe { * @throws "Safe Proxy contract is not deployed in the current network" * @throws "MultiSend contract is not deployed in the current network" */ - private async init({ ethAdapter, safeAddress, contractNetworks }: SafeConfig): Promise { + private async init({ + ethAdapter, + safeAddress, + isL1SafeMasterCopy, + contractNetworks + }: SafeConfig): Promise { this.#ethAdapter = ethAdapter - this.#contractManager = await ContractManager.create( - this.#ethAdapter, + this.#contractManager = await ContractManager.create({ + ethAdapter: this.#ethAdapter, safeAddress, + isL1SafeMasterCopy, contractNetworks - ) + }) this.#ownerManager = new OwnerManager(this.#ethAdapter, this.#contractManager.safeContract) this.#moduleManager = new ModuleManager(this.#ethAdapter, this.#contractManager.safeContract) } @@ -108,10 +123,16 @@ class Safe { * @throws "Safe Proxy contract is not deployed in the current network" * @throws "MultiSend contract is not deployed in the current network" */ - async connect({ ethAdapter, safeAddress, contractNetworks }: ConnectSafeConfig): Promise { + async connect({ + ethAdapter, + safeAddress, + isL1SafeMasterCopy, + contractNetworks + }: ConnectSafeConfig): Promise { return await Safe.create({ ethAdapter: ethAdapter || this.#ethAdapter, safeAddress: safeAddress || this.getAddress(), + isL1SafeMasterCopy: isL1SafeMasterCopy || this.#contractManager.isL1SafeMasterCopy, contractNetworks: contractNetworks || this.#contractManager.contractNetworks }) } diff --git a/packages/safe-core-sdk/src/contracts/config.ts b/packages/safe-core-sdk/src/contracts/config.ts new file mode 100644 index 000000000..6470cbbfd --- /dev/null +++ b/packages/safe-core-sdk/src/contracts/config.ts @@ -0,0 +1,38 @@ +export type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' + +export const SAFE_LAST_VERSION: SafeVersion = '1.3.0' +export const SAFE_BASE_VERSION: SafeVersion = '1.1.1' + +type SafeDeploymentsVersions = { + [version: string]: { + safeMasterCopyVersion: string + safeMasterCopyL2Version: string | undefined + safeProxyFactoryVersion: string + multiSendVersion: string + } +} + +export const safeDeploymentsVersions: SafeDeploymentsVersions = { + '1.3.0': { + safeMasterCopyVersion: '1.3.0', + safeMasterCopyL2Version: '1.3.0', + safeProxyFactoryVersion: '1.3.0', + multiSendVersion: '1.3.0' + }, + '1.2.0': { + safeMasterCopyVersion: '1.2.0', + safeMasterCopyL2Version: undefined, + safeProxyFactoryVersion: '1.1.1', + multiSendVersion: '1.1.1' + }, + '1.1.1': { + safeMasterCopyVersion: '1.1.1', + safeMasterCopyL2Version: undefined, + safeProxyFactoryVersion: '1.1.1', + multiSendVersion: '1.1.1' + } +} + +export const safeDeploymentsL1ChainIds = [ + 1 // Ethereum Mainnet +] diff --git a/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts b/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts index d34ffcc59..305616468 100644 --- a/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts +++ b/packages/safe-core-sdk/src/contracts/contractInstancesEthers.ts @@ -6,6 +6,7 @@ import { GnosisSafe__factory as SafeMasterCopy_V1_2_0 } from '../../typechain/sr import { GnosisSafe__factory as SafeMasterCopy_V1_3_0 } from '../../typechain/src/ethers-v5/v1.3.0/factories/GnosisSafe__factory' import { MultiSend__factory as MultiSend_V1_3_0 } from '../../typechain/src/ethers-v5/v1.3.0/factories/MultiSend__factory' import { ProxyFactory__factory as SafeProxyFactory_V1_3_0 } from '../../typechain/src/ethers-v5/v1.3.0/factories/ProxyFactory__factory' +import { SafeVersion } from './config' import GnosisSafeContract_V1_1_1_Ethers from './GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Ethers' import GnosisSafeContract_V1_2_0_Ethers from './GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Ethers' import GnosisSafeContract_V1_3_0_Ethers from './GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Ethers' @@ -13,7 +14,6 @@ import GnosisSafeProxyFactoryContract_V1_1_1_Ethers from './GnosisSafeProxyFacto import GnosisSafeProxyFactoryContract_V1_3_0_Ethers from './GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Ethers' import MultiSendContract_V1_1_1_Ethers from './MultiSend/v1.1.1/MultiSendContract_V1_1_1_Ethers' import MultiSendContract_V1_3_0_Ethers from './MultiSend/v1.3.0/MultiSendContract_V1_3_0_Ethers' -import { SafeVersion } from './safeDeploymentContracts' export function getSafeContractInstance( safeVersion: SafeVersion, diff --git a/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts b/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts index b2a861343..a5fd4009d 100644 --- a/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts +++ b/packages/safe-core-sdk/src/contracts/contractInstancesWeb3.ts @@ -5,6 +5,7 @@ import { GnosisSafe as SafeMasterCopy_V1_2_0 } from '../../typechain/src/web3-v1 import { GnosisSafe as SafeMasterCopy_V1_3_0 } from '../../typechain/src/web3-v1/v1.3.0/gnosis_safe' import { MultiSend as MultiSend_V1_3_0 } from '../../typechain/src/web3-v1/v1.3.0/multi_send' import { ProxyFactory as GnosisSafeProxyFactory_V1_3_0 } from '../../typechain/src/web3-v1/v1.3.0/proxy_factory' +import { SafeVersion } from './config' import GnosisSafeContract_V1_1_1_Web3 from './GnosisSafe/v1.1.1/GnosisSafeContract_V1_1_1_Web3' import GnosisSafeContract_V1_2_0_Web3 from './GnosisSafe/v1.2.0/GnosisSafeContract_V1_2_0_Web3' import GnosisSafeContract_V1_3_0_Web3 from './GnosisSafe/v1.3.0/GnosisSafeContract_V1_3_0_Web3' @@ -12,7 +13,6 @@ import GnosisSafeProxyFactoryContract_V1_1_1_Web3 from './GnosisSafeProxyFactory import GnosisSafeProxyFactoryContract_V1_3_0_Web3 from './GnosisSafeProxyFactory/v1.3.0/GnosisSafeProxyFactoryContract_V1_3_0_Web3' import MultiSendContract_V1_1_1_Web3 from './MultiSend/v1.1.1/MultiSendContract_V1_1_1_Web3' import MultiSendContract_V1_3_0_Web3 from './MultiSend/v1.3.0/MultiSendContract_V1_3_0_Web3' -import { SafeVersion } from './safeDeploymentContracts' export function getSafeContractInstance( safeVersion: SafeVersion, diff --git a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts index 68db35b21..3d93f7417 100644 --- a/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts +++ b/packages/safe-core-sdk/src/contracts/safeDeploymentContracts.ts @@ -6,75 +6,16 @@ import { getSafeSingletonDeployment, SingletonDeployment } from '@gnosis.pm/safe-deployments' - -export type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1' - -export const SAFE_LAST_VERSION: SafeVersion = '1.3.0' -export const SAFE_BASE_VERSION: SafeVersion = '1.1.1' - -type SafeDeploymentsVersions = { - [version: string]: { - safeMasterCopyVersion: string - safeMasterCopyL2Version: string | undefined - safeProxyFactoryVersion: string - multiSendVersion: string - } -} - -const safeDeploymentsVersions: SafeDeploymentsVersions = { - '1.3.0': { - safeMasterCopyVersion: '1.3.0', - safeMasterCopyL2Version: '1.3.0', - safeProxyFactoryVersion: '1.3.0', - multiSendVersion: '1.3.0' - }, - '1.2.0': { - safeMasterCopyVersion: '1.2.0', - safeMasterCopyL2Version: undefined, - safeProxyFactoryVersion: '1.1.1', - multiSendVersion: '1.1.1' - }, - '1.1.1': { - safeMasterCopyVersion: '1.1.1', - safeMasterCopyL2Version: undefined, - safeProxyFactoryVersion: '1.1.1', - multiSendVersion: '1.1.1' - } -} - -const safeDeploymentsL1ChainIds = [ - 1, // Ethereum Mainnet - 4, // Ethereum Testnet Rinkeby - 5, // Ethereum Testnet Goerli - 42 // Ethereum Testnet Kovan -] - -/* -const safeDeploymentsL2ChainIds = [ - 56, // Binance Smart Chain Mainnet - 100, // xDAI Chain - 137, // Polygon Mainnet - 246, // Energy Web Chain - 42161, // Arbitrum One - 73799, // Energy Web Volta Testnet - - 69, // Optimistic Ethereum Network - 1285, // Moonriver - 1287, // Moonbase Alpha - 4002, // Fantom Testnet - 42220, // Celo Mainnet - 43114, // Avalanche Mainnet - 333999 // Polis Mainnet -] -*/ +import { safeDeploymentsL1ChainIds, safeDeploymentsVersions, SafeVersion } from './config' export function getSafeContractDeployment( safeVersion: SafeVersion, - chainId: number + chainId: number, + isL1SafeMasterCopy: boolean = false ): SingletonDeployment | undefined { const version = safeDeploymentsVersions[safeVersion].safeMasterCopyVersion const filters: DeploymentFilter = { version, network: chainId.toString(), released: true } - if (safeDeploymentsL1ChainIds.includes(chainId)) { + if (safeDeploymentsL1ChainIds.includes(chainId) || isL1SafeMasterCopy) { return getSafeSingletonDeployment(filters) } return getSafeL2SingletonDeployment(filters) diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts index 0e9fc1873..f34faadf9 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts @@ -1,8 +1,8 @@ import { BigNumber } from '@ethersproject/bignumber' +import { SafeVersion } from '../contracts/config' import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' import MultiSendContract from '../contracts/MultiSend/MultiSendContract' -import { SafeVersion } from '../contracts/safeDeploymentContracts' import { AbiItem } from '../types' export interface EthAdapterTransaction { @@ -14,9 +14,11 @@ export interface EthAdapterTransaction { gasLimit?: number } -export interface GnosisSafeContracts { - gnosisSafeContract: GnosisSafeContract - multiSendContract: MultiSendContract +export interface GetSafeContractProps { + safeVersion: SafeVersion + chainId: number + isL1SafeMasterCopy?: boolean + customContractAddress?: string } interface EthAdapter { @@ -24,11 +26,12 @@ interface EthAdapter { getBalance(address: string): Promise getChainId(): Promise getContract(address: string, abi: AbiItem[]): any - getSafeContract( - safeVersion: SafeVersion, - chainId: number, - customContractAddress?: string - ): Promise + getSafeContract({ + safeVersion, + chainId, + isL1SafeMasterCopy, + customContractAddress + }: GetSafeContractProps): Promise getMultiSendContract( safeVersion: SafeVersion, chainId: number, diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index 581c93fcc..0791c3d03 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -3,6 +3,7 @@ import { Signer } from '@ethersproject/abstract-signer' import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' import { Provider } from '@ethersproject/providers' +import { SafeVersion } from '../contracts/config' import { getMultiSendContractInstance, getSafeContractInstance, @@ -14,11 +15,10 @@ import MultiSendEthersContract from '../contracts/MultiSend/MultiSendEthersContr import { getMultiSendContractDeployment, getSafeContractDeployment, - getSafeProxyFactoryContractDeployment, - SafeVersion + getSafeProxyFactoryContractDeployment } from '../contracts/safeDeploymentContracts' import { AbiItem } from '../types' -import EthAdapter, { EthAdapterTransaction } from './EthAdapter' +import EthAdapter, { EthAdapterTransaction, GetSafeContractProps } from './EthAdapter' export interface EthersAdapterConfig { /** ethers - Ethers v5 library */ @@ -64,16 +64,21 @@ class EthersAdapter implements EthAdapter { return (await this.#provider.getNetwork()).chainId } - async getSafeContract( - safeVersion: SafeVersion, - chainId: number, - customContractAddress?: string - ): Promise { + async getSafeContract({ + safeVersion, + chainId, + isL1SafeMasterCopy, + customContractAddress + }: GetSafeContractProps): Promise { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress } else { - const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) + const safeSingletonDeployment = getSafeContractDeployment( + safeVersion, + chainId, + isL1SafeMasterCopy + ) contractAddress = safeSingletonDeployment?.networkAddresses[chainId] } if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index b8d5a3030..93c0d90e3 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -1,4 +1,5 @@ import { BigNumber } from '@ethersproject/bignumber' +import { SafeVersion } from '../contracts/config' import { getGnosisSafeProxyFactoryContractInstance, getMultiSendContractInstance, @@ -10,11 +11,10 @@ import MultiSendWeb3Contract from '../contracts/MultiSend/MultiSendWeb3Contract' import { getMultiSendContractDeployment, getSafeContractDeployment, - getSafeProxyFactoryContractDeployment, - SafeVersion + getSafeProxyFactoryContractDeployment } from '../contracts/safeDeploymentContracts' import { AbiItem } from '../types' -import EthAdapter, { EthAdapterTransaction } from './EthAdapter' +import EthAdapter, { EthAdapterTransaction, GetSafeContractProps } from './EthAdapter' export interface Web3AdapterConfig { /** web3 - Web3 library */ @@ -47,12 +47,17 @@ class Web3Adapter implements EthAdapter { return this.#web3.eth.getChainId() } - async getSafeContract( - safeVersion: SafeVersion, - chainId: number, - customContractAddress?: string - ): Promise { - const safeSingletonDeployment = getSafeContractDeployment(safeVersion, chainId) + async getSafeContract({ + safeVersion, + chainId, + isL1SafeMasterCopy, + customContractAddress + }: GetSafeContractProps): Promise { + const safeSingletonDeployment = getSafeContractDeployment( + safeVersion, + chainId, + isL1SafeMasterCopy + ) const contractAddress = customContractAddress ?? safeSingletonDeployment?.networkAddresses[chainId] if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { diff --git a/packages/safe-core-sdk/src/managers/contractManager.ts b/packages/safe-core-sdk/src/managers/contractManager.ts index df5baeab1..862e50f89 100644 --- a/packages/safe-core-sdk/src/managers/contractManager.ts +++ b/packages/safe-core-sdk/src/managers/contractManager.ts @@ -1,40 +1,50 @@ +import { SafeVersion, SAFE_BASE_VERSION } from '../contracts/config' import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import MultiSendContract from '../contracts/MultiSend/MultiSendContract' -import { SafeVersion, SAFE_BASE_VERSION } from '../contracts/safeDeploymentContracts' -import EthAdapter from '../ethereumLibs/EthAdapter' +import { SafeConfig } from '../Safe' import { ContractNetworksConfig } from '../types' class ContractManager { #contractNetworks?: ContractNetworksConfig + #isL1SafeMasterCopy?: boolean #safeContract!: GnosisSafeContract #multiSendContract!: MultiSendContract - static async create( - ethAdapter: EthAdapter, - safeAddress: string, - contractNetworks?: ContractNetworksConfig - ): Promise { + static async create({ + ethAdapter, + safeAddress, + isL1SafeMasterCopy, + contractNetworks + }: SafeConfig): Promise { const contractManager = new ContractManager() - await contractManager.init(ethAdapter, safeAddress, contractNetworks) + await contractManager.init({ ethAdapter, safeAddress, isL1SafeMasterCopy, contractNetworks }) return contractManager } - async init( - ethAdapter: EthAdapter, - safeAddress: string, - contractNetworks?: ContractNetworksConfig - ): Promise { + async init({ + ethAdapter, + safeAddress, + isL1SafeMasterCopy, + contractNetworks + }: SafeConfig): Promise { const chainId = await ethAdapter.getChainId() - const temporarySafeContract = await ethAdapter.getSafeContract( - SAFE_BASE_VERSION, + const temporarySafeContract = await ethAdapter.getSafeContract({ + safeVersion: SAFE_BASE_VERSION, chainId, - safeAddress - ) + isL1SafeMasterCopy, + customContractAddress: safeAddress + }) const safeVersion = (await temporarySafeContract.getVersion()) as SafeVersion const customContracts = contractNetworks?.[chainId] this.#contractNetworks = contractNetworks - this.#safeContract = await ethAdapter.getSafeContract(safeVersion, chainId, safeAddress) + this.#isL1SafeMasterCopy = isL1SafeMasterCopy + this.#safeContract = await ethAdapter.getSafeContract({ + safeVersion, + chainId, + isL1SafeMasterCopy, + customContractAddress: safeAddress + }) this.#multiSendContract = await ethAdapter.getMultiSendContract( safeVersion, chainId, @@ -46,6 +56,10 @@ class ContractManager { return this.#contractNetworks } + get isL1SafeMasterCopy(): boolean | undefined { + return this.#isL1SafeMasterCopy + } + get safeContract(): GnosisSafeContract { return this.#safeContract } diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index e3e68f629..18856807b 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -1,6 +1,6 @@ +import { SafeVersion, SAFE_LAST_VERSION } from '../contracts/config' import GnosisSafeContract from '../contracts/GnosisSafe/GnosisSafeContract' import GnosisSafeProxyFactoryContract from '../contracts/GnosisSafeProxyFactory/GnosisSafeProxyFactoryContract' -import { SafeVersion, SAFE_LAST_VERSION } from '../contracts/safeDeploymentContracts' import EthAdapter from '../ethereumLibs/EthAdapter' import Safe from '../Safe' import { ContractNetworksConfig } from '../types' @@ -27,6 +27,8 @@ export interface SafeFactoryConfig { ethAdapter: EthAdapter /** safeVersion - Versions of the Safe deployed by this Factory contract */ safeVersion?: SafeVersion + /** isL1SafeMasterCopy - Forces to use the Gnosis Safe L1 version of the contract instead of the L2 version */ + isL1SafeMasterCopy?: boolean /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig } @@ -36,12 +38,15 @@ interface SafeFactoryInitConfig { ethAdapter: EthAdapter /** safeVersion - Versions of the Safe deployed by this Factory contract */ safeVersion: SafeVersion + /** isL1SafeMasterCopy - Forces to use the Gnosis Safe L1 version of the contract instead of the L2 version */ + isL1SafeMasterCopy?: boolean /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig } class SafeFactory { #contractNetworks?: ContractNetworksConfig + #isL1SafeMasterCopy?: boolean #safeVersion!: SafeVersion #ethAdapter!: EthAdapter #safeProxyFactoryContract!: GnosisSafeProxyFactoryContract @@ -50,20 +55,23 @@ class SafeFactory { static async create({ ethAdapter, safeVersion = SAFE_LAST_VERSION, + isL1SafeMasterCopy = false, contractNetworks }: SafeFactoryConfig): Promise { const safeFactorySdk = new SafeFactory() - await safeFactorySdk.init({ ethAdapter, safeVersion, contractNetworks }) + await safeFactorySdk.init({ ethAdapter, safeVersion, isL1SafeMasterCopy, contractNetworks }) return safeFactorySdk } private async init({ ethAdapter, safeVersion, + isL1SafeMasterCopy, contractNetworks }: SafeFactoryInitConfig): Promise { this.#ethAdapter = ethAdapter this.#safeVersion = safeVersion + this.#isL1SafeMasterCopy = isL1SafeMasterCopy this.#contractNetworks = contractNetworks const chainId = await this.#ethAdapter.getChainId() const customContracts = contractNetworks?.[chainId] @@ -72,11 +80,12 @@ class SafeFactory { chainId, customContracts?.safeProxyFactoryAddress ) - this.#gnosisSafeContract = await ethAdapter.getSafeContract( - this.#safeVersion, + this.#gnosisSafeContract = await ethAdapter.getSafeContract({ + safeVersion: this.#safeVersion, chainId, - customContracts?.safeMasterCopyAddress - ) + isL1SafeMasterCopy, + customContractAddress: customContracts?.safeMasterCopyAddress + }) } getEthAdapter(): EthAdapter { @@ -131,14 +140,16 @@ class SafeFactory { saltNonce: safeDeploymentConfig?.saltNonce, options: { from: signerAddress } }) - const safeContract = await this.#ethAdapter.getSafeContract( - this.#safeVersion, + const safeContract = await this.#ethAdapter.getSafeContract({ + safeVersion: this.#safeVersion, chainId, - safeAddress - ) + isL1SafeMasterCopy: this.#isL1SafeMasterCopy, + customContractAddress: safeAddress + }) const safe = await Safe.create({ ethAdapter: this.#ethAdapter, safeAddress: safeContract.getAddress(), + isL1SafeMasterCopy: this.#isL1SafeMasterCopy, contractNetworks: this.#contractNetworks }) return safe diff --git a/packages/safe-core-sdk/tests/safeFactory.test.ts b/packages/safe-core-sdk/tests/safeFactory.test.ts index 2959d84c7..9c54db960 100644 --- a/packages/safe-core-sdk/tests/safeFactory.test.ts +++ b/packages/safe-core-sdk/tests/safeFactory.test.ts @@ -8,7 +8,7 @@ import { SafeDeploymentConfig, SafeFactory } from '../src' -import { SAFE_LAST_VERSION } from '../src/contracts/safeDeploymentContracts' +import { SAFE_LAST_VERSION } from '../src/contracts/config' import { itif } from './utils/helpers' import { getFactory, getMultiSend, getSafeSingleton } from './utils/setupContracts' import { getEthAdapter } from './utils/setupEthAdapter' From 3621889f66991103b45e806870d70db97843364e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 Nov 2021 12:18:25 +0100 Subject: [PATCH 34/35] Add tests for getting the contracts from the ethAdapter --- .../src/ethereumLibs/EthAdapter.ts | 6 +- .../src/ethereumLibs/EthersAdapter.ts | 24 +-- .../src/ethereumLibs/Web3Adapter.ts | 24 +-- packages/safe-core-sdk/src/index.ts | 2 + .../src/managers/contractManager.ts | 18 ++- .../safe-core-sdk/src/safeFactory/index.ts | 16 +- .../tests/contractManager.test.ts | 2 +- .../safe-core-sdk/tests/ethAdapters.test.ts | 142 ++++++++++++++++++ .../safe-core-sdk/tests/safeFactory.test.ts | 17 +++ 9 files changed, 218 insertions(+), 33 deletions(-) create mode 100644 packages/safe-core-sdk/tests/ethAdapters.test.ts diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts index f34faadf9..4aaba31cb 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthAdapter.ts @@ -31,17 +31,17 @@ interface EthAdapter { chainId, isL1SafeMasterCopy, customContractAddress - }: GetSafeContractProps): Promise + }: GetSafeContractProps): GnosisSafeContract getMultiSendContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise + ): MultiSendContract getSafeProxyFactoryContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise + ): GnosisSafeProxyFactoryContract getContractCode(address: string): Promise getTransaction(transactionHash: string): Promise getSignerAddress(): Promise diff --git a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts index 0791c3d03..615cb55ba 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/EthersAdapter.ts @@ -64,12 +64,12 @@ class EthersAdapter implements EthAdapter { return (await this.#provider.getNetwork()).chainId } - async getSafeContract({ + getSafeContract({ safeVersion, chainId, isL1SafeMasterCopy, customContractAddress - }: GetSafeContractProps): Promise { + }: GetSafeContractProps): GnosisSafeContractEthers { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress @@ -81,17 +81,17 @@ class EthersAdapter implements EthAdapter { ) contractAddress = safeSingletonDeployment?.networkAddresses[chainId] } - if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { - throw new Error('Safe Proxy contract is not deployed in the current network') + if (!contractAddress) { + throw new Error('Invalid Safe Proxy contract address') } return getSafeContractInstance(safeVersion, contractAddress, this.#signer) } - async getMultiSendContract( + getMultiSendContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): MultiSendEthersContract { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress @@ -99,17 +99,17 @@ class EthersAdapter implements EthAdapter { const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) contractAddress = multiSendDeployment?.networkAddresses[chainId] } - if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { - throw new Error('Multi Send contract is not deployed in the current network') + if (!contractAddress) { + throw new Error('Invalid Multi Send contract address') } return getMultiSendContractInstance(safeVersion, contractAddress, this.#signer) } - async getSafeProxyFactoryContract( + getSafeProxyFactoryContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): GnosisSafeProxyFactoryEthersContract { let contractAddress: string | undefined if (customContractAddress) { contractAddress = customContractAddress @@ -117,8 +117,8 @@ class EthersAdapter implements EthAdapter { const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) contractAddress = proxyFactoryDeployment?.networkAddresses[chainId] } - if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { - throw new Error('Safe Proxy Factory contract is not deployed in the current network') + if (!contractAddress) { + throw new Error('Invalid Safe Proxy Factory contract address') } return getSafeProxyFactoryContractInstance(safeVersion, contractAddress, this.#signer) } diff --git a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts index 93c0d90e3..8d78986af 100644 --- a/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts +++ b/packages/safe-core-sdk/src/ethereumLibs/Web3Adapter.ts @@ -47,12 +47,12 @@ class Web3Adapter implements EthAdapter { return this.#web3.eth.getChainId() } - async getSafeContract({ + getSafeContract({ safeVersion, chainId, isL1SafeMasterCopy, customContractAddress - }: GetSafeContractProps): Promise { + }: GetSafeContractProps): GnosisSafeContractWeb3 { const safeSingletonDeployment = getSafeContractDeployment( safeVersion, chainId, @@ -60,8 +60,8 @@ class Web3Adapter implements EthAdapter { ) const contractAddress = customContractAddress ?? safeSingletonDeployment?.networkAddresses[chainId] - if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { - throw new Error('Safe Proxy contract is not deployed in the current network') + if (!contractAddress) { + throw new Error('Invalid Safe Proxy contract address') } const safeContract = this.getContract( contractAddress, @@ -70,15 +70,15 @@ class Web3Adapter implements EthAdapter { return getSafeContractInstance(safeVersion, safeContract) } - async getMultiSendContract( + getMultiSendContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): MultiSendWeb3Contract { const multiSendDeployment = getMultiSendContractDeployment(safeVersion, chainId) const contractAddress = customContractAddress ?? multiSendDeployment?.networkAddresses[chainId] - if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { - throw new Error('Multi Send contract is not deployed in the current network') + if (!contractAddress) { + throw new Error('Invalid Multi Send contract addresss') } const multiSendContract = this.getContract( contractAddress, @@ -87,16 +87,16 @@ class Web3Adapter implements EthAdapter { return getMultiSendContractInstance(safeVersion, multiSendContract) } - async getSafeProxyFactoryContract( + getSafeProxyFactoryContract( safeVersion: SafeVersion, chainId: number, customContractAddress?: string - ): Promise { + ): GnosisSafeProxyFactoryWeb3Contract { const proxyFactoryDeployment = getSafeProxyFactoryContractDeployment(safeVersion, chainId) const contractAddress = customContractAddress ?? proxyFactoryDeployment?.networkAddresses[chainId] - if (!contractAddress || (await this.getContractCode(contractAddress)) === '0x') { - throw new Error('Safe Proxy Factory contract is not deployed in the current network') + if (!contractAddress) { + throw new Error('Invalid Safe Proxy Factory contract address') } const proxyFactoryContract = this.getContract( contractAddress, diff --git a/packages/safe-core-sdk/src/index.ts b/packages/safe-core-sdk/src/index.ts index 978dde6a4..ad1aad542 100644 --- a/packages/safe-core-sdk/src/index.ts +++ b/packages/safe-core-sdk/src/index.ts @@ -1,3 +1,4 @@ +import { SafeVersion } from './contracts/config' import EthAdapter, { EthAdapterTransaction } from './ethereumLibs/EthAdapter' import EthersAdapter, { EthersAdapterConfig } from './ethereumLibs/EthersAdapter' import Web3Adapter, { Web3AdapterConfig } from './ethereumLibs/Web3Adapter' @@ -23,6 +24,7 @@ import { export default Safe export { + SafeVersion, SafeFactory, SafeFactoryConfig, SafeAccountConfig, diff --git a/packages/safe-core-sdk/src/managers/contractManager.ts b/packages/safe-core-sdk/src/managers/contractManager.ts index 862e50f89..e53d2613e 100644 --- a/packages/safe-core-sdk/src/managers/contractManager.ts +++ b/packages/safe-core-sdk/src/managers/contractManager.ts @@ -28,28 +28,40 @@ class ContractManager { contractNetworks }: SafeConfig): Promise { const chainId = await ethAdapter.getChainId() - const temporarySafeContract = await ethAdapter.getSafeContract({ + const temporarySafeContract = ethAdapter.getSafeContract({ safeVersion: SAFE_BASE_VERSION, chainId, isL1SafeMasterCopy, customContractAddress: safeAddress }) + if ((await ethAdapter.getContractCode(temporarySafeContract.getAddress())) === '0x') { + throw new Error('Safe Proxy contract is not deployed in the current network') + } const safeVersion = (await temporarySafeContract.getVersion()) as SafeVersion const customContracts = contractNetworks?.[chainId] this.#contractNetworks = contractNetworks this.#isL1SafeMasterCopy = isL1SafeMasterCopy - this.#safeContract = await ethAdapter.getSafeContract({ + const safeContract = ethAdapter.getSafeContract({ safeVersion, chainId, isL1SafeMasterCopy, customContractAddress: safeAddress }) - this.#multiSendContract = await ethAdapter.getMultiSendContract( + if ((await ethAdapter.getContractCode(safeContract.getAddress())) === '0x') { + throw new Error('Safe Proxy contract is not deployed in the current network') + } + this.#safeContract = safeContract + + const multiSendContract = await ethAdapter.getMultiSendContract( safeVersion, chainId, customContracts?.multiSendAddress ) + if ((await ethAdapter.getContractCode(multiSendContract.getAddress())) === '0x') { + throw new Error('Multi Send contract is not deployed in the current network') + } + this.#multiSendContract = multiSendContract } get contractNetworks(): ContractNetworksConfig | undefined { diff --git a/packages/safe-core-sdk/src/safeFactory/index.ts b/packages/safe-core-sdk/src/safeFactory/index.ts index 18856807b..390420e59 100644 --- a/packages/safe-core-sdk/src/safeFactory/index.ts +++ b/packages/safe-core-sdk/src/safeFactory/index.ts @@ -75,17 +75,26 @@ class SafeFactory { this.#contractNetworks = contractNetworks const chainId = await this.#ethAdapter.getChainId() const customContracts = contractNetworks?.[chainId] - this.#safeProxyFactoryContract = await ethAdapter.getSafeProxyFactoryContract( + const safeProxyFactoryContract = await ethAdapter.getSafeProxyFactoryContract( this.#safeVersion, chainId, customContracts?.safeProxyFactoryAddress ) - this.#gnosisSafeContract = await ethAdapter.getSafeContract({ + if ((await this.#ethAdapter.getContractCode(safeProxyFactoryContract.getAddress())) === '0x') { + throw new Error('Safe Proxy Factory contract is not deployed in the current network') + } + this.#safeProxyFactoryContract = safeProxyFactoryContract + + const gnosisSafeContract = ethAdapter.getSafeContract({ safeVersion: this.#safeVersion, chainId, isL1SafeMasterCopy, customContractAddress: customContracts?.safeMasterCopyAddress }) + if ((await this.#ethAdapter.getContractCode(gnosisSafeContract.getAddress())) === '0x') { + throw new Error('Safe Proxy contract is not deployed in the current network') + } + this.#gnosisSafeContract = gnosisSafeContract } getEthAdapter(): EthAdapter { @@ -146,6 +155,9 @@ class SafeFactory { isL1SafeMasterCopy: this.#isL1SafeMasterCopy, customContractAddress: safeAddress }) + if ((await this.#ethAdapter.getContractCode(safeContract.getAddress())) === '0x') { + throw new Error('Safe Proxy contract is not deployed in the current network') + } const safe = await Safe.create({ ethAdapter: this.#ethAdapter, safeAddress: safeContract.getAddress(), diff --git a/packages/safe-core-sdk/tests/contractManager.test.ts b/packages/safe-core-sdk/tests/contractManager.test.ts index 6bac9c08c..f46339afb 100644 --- a/packages/safe-core-sdk/tests/contractManager.test.ts +++ b/packages/safe-core-sdk/tests/contractManager.test.ts @@ -46,7 +46,7 @@ describe('Safe contracts manager', () => { safeAddress: safe.address }) ) - .to.be.rejectedWith('Multi Send contract is not deployed in the current network') + .to.be.rejectedWith('Invalid Multi Send contract') }) it('should fail if Safe Proxy contract is not deployed in the current network', async () => { diff --git a/packages/safe-core-sdk/tests/ethAdapters.test.ts b/packages/safe-core-sdk/tests/ethAdapters.test.ts new file mode 100644 index 000000000..ed2406bd7 --- /dev/null +++ b/packages/safe-core-sdk/tests/ethAdapters.test.ts @@ -0,0 +1,142 @@ +import chai from 'chai' +import chaiAsPromised from 'chai-as-promised' +import { deployments, waffle } from 'hardhat' +import { ContractNetworksConfig, SafeVersion } from '../src' +import { getFactory, getMultiSend, getSafeSingleton } from './utils/setupContracts' +import { getEthAdapter } from './utils/setupEthAdapter' +import { getAccounts } from './utils/setupTestNetwork' + +chai.use(chaiAsPromised) + +describe('Safe contracts', () => { + const setupTests = deployments.createFixture(async ({ deployments }) => { + await deployments.fixture() + const accounts = await getAccounts() + const chainId: number = (await waffle.provider.getNetwork()).chainId + const contractNetworks: ContractNetworksConfig = { + [chainId]: { + multiSendAddress: (await getMultiSend()).address, + safeMasterCopyAddress: (await getSafeSingleton()).address, + safeProxyFactoryAddress: (await getFactory()).address + } + } + return { + accounts, + contractNetworks, + chainId + } + }) + + describe('getSafeContract', async () => { + it('should return an L1 Safe contract from safe-deployments', async () => { + const { accounts } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const chainId = 1 + const safeContract = await ethAdapter.getSafeContract({ safeVersion, chainId }) + chai + .expect(await safeContract.getAddress()) + .to.be.eq('0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552') + }) + + it('should return an L2 Safe contract from safe-deployments', async () => { + const { accounts } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const chainId = 100 + const safeContract = await ethAdapter.getSafeContract({ safeVersion, chainId }) + chai + .expect(await safeContract.getAddress()) + .to.be.eq('0x3E5c63644E683549055b9Be8653de26E0B4CD36E') + }) + + it('should return an L1 Safe contract from safe-deployments using the L1 flag', async () => { + const { accounts } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const chainId = 100 + const isL1SafeMasterCopy = true + const safeContract = await ethAdapter.getSafeContract({ + safeVersion, + chainId, + isL1SafeMasterCopy + }) + chai + .expect(await safeContract.getAddress()) + .to.be.eq('0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552') + }) + + it('should return a Safe contract from the custom addresses', async () => { + const { accounts, contractNetworks, chainId } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const customContractAddress = contractNetworks[chainId].safeMasterCopyAddress + const safeContract = await ethAdapter.getSafeContract({ + safeVersion, + chainId, + customContractAddress + }) + chai.expect(await safeContract.getAddress()).to.be.eq((await getSafeSingleton()).address) + }) + }) + + describe('getMultiSendContract', async () => { + it('should return a Multi Send contract from safe-deployments', async () => { + const { accounts } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const chainId = 1 + const multiSendContract = await ethAdapter.getMultiSendContract(safeVersion, chainId) + chai + .expect(await multiSendContract.getAddress()) + .to.be.eq('0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761') + }) + + it('should return a Multi Send contract from the custom addresses', async () => { + const { accounts, contractNetworks, chainId } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const customContractAddress = contractNetworks[chainId].multiSendAddress + const multiSendContract = await ethAdapter.getMultiSendContract( + safeVersion, + chainId, + customContractAddress + ) + chai.expect(await multiSendContract.getAddress()).to.be.eq((await getMultiSend()).address) + }) + }) + + describe('getSafeProxyFactoryContract', async () => { + it('should return a Safe Proxy Factory contract from safe-deployments', async () => { + const { accounts } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const chainId = 1 + const factoryContract = await ethAdapter.getSafeProxyFactoryContract(safeVersion, chainId) + chai + .expect(await factoryContract.getAddress()) + .to.be.eq('0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2') + }) + + it('should return a Safe Proxy Factory contract from the custom addresses', async () => { + const { accounts, contractNetworks, chainId } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const safeVersion: SafeVersion = '1.3.0' + const customContractAddress = contractNetworks[chainId].safeProxyFactoryAddress + const factoryContract = await ethAdapter.getSafeProxyFactoryContract( + safeVersion, + chainId, + customContractAddress + ) + chai.expect(await factoryContract.getAddress()).to.be.eq((await getFactory()).address) + }) + }) +}) diff --git a/packages/safe-core-sdk/tests/safeFactory.test.ts b/packages/safe-core-sdk/tests/safeFactory.test.ts index 9c54db960..f7c692c99 100644 --- a/packages/safe-core-sdk/tests/safeFactory.test.ts +++ b/packages/safe-core-sdk/tests/safeFactory.test.ts @@ -9,6 +9,7 @@ import { SafeFactory } from '../src' import { SAFE_LAST_VERSION } from '../src/contracts/config' +import { ZERO_ADDRESS } from '../src/utils/constants' import { itif } from './utils/helpers' import { getFactory, getMultiSend, getSafeSingleton } from './utils/setupContracts' import { getEthAdapter } from './utils/setupEthAdapter' @@ -42,6 +43,22 @@ describe('Safe Proxy Factory', () => { const ethAdapter = await getEthAdapter(account1.signer) chai .expect(SafeFactory.create({ ethAdapter })) + .rejectedWith('Invalid Safe Proxy Factory contract') + }) + + it('should fail if the contractNetworks provided are not deployed', async () => { + const { accounts, chainId } = await setupTests() + const [account1] = accounts + const ethAdapter = await getEthAdapter(account1.signer) + const contractNetworks: ContractNetworksConfig = { + [chainId]: { + multiSendAddress: ZERO_ADDRESS, + safeMasterCopyAddress: ZERO_ADDRESS, + safeProxyFactoryAddress: ZERO_ADDRESS + } + } + chai + .expect(SafeFactory.create({ ethAdapter, contractNetworks })) .rejectedWith('Safe Proxy Factory contract is not deployed in the current network') }) From 33267d593c75cb7968b7c7c27cb87df7a099fcb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Mart=C3=ADnez?= Date: Tue, 9 Nov 2021 15:59:31 +0100 Subject: [PATCH 35/35] Update typechain script --- packages/safe-core-sdk/package.json | 4 +-- .../scripts/generateTypechainFiles.ts | 28 ++++++------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/packages/safe-core-sdk/package.json b/packages/safe-core-sdk/package.json index fa195ec99..a567d2761 100644 --- a/packages/safe-core-sdk/package.json +++ b/packages/safe-core-sdk/package.json @@ -11,7 +11,7 @@ "SDK" ], "scripts": { - "typechain": "node scripts/generateTypechainFiles.ts", + "typechain": "ts-node scripts/generateTypechainFiles.ts", "unbuild": "rimraf dist artifacts cache .nyc_output typechain", "build": "hardhat compile && yarn typechain && tsc", "test:ganache:web3:v1.2.0": "export TEST_NETWORK=ganache && export ETH_LIB=web3 && export SAFE_VERSION=1.2.0 && hardhat --network localhost deploy && nyc hardhat --network localhost test", @@ -23,7 +23,7 @@ "test:hardhat:ethers:v1.2.0": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && export SAFE_VERSION=1.2.0 && hardhat deploy && nyc hardhat test", "test:hardhat:ethers:v1.3.0": "export TEST_NETWORK=hardhat && export ETH_LIB=ethers && export SAFE_VERSION=1.3.0 && hardhat deploy && nyc hardhat test", "coverage": "nyc report --reporter=text-lcov | coveralls", - "format": "prettier --write \"{src,tests,hardhat}/**/*.ts\"", + "format": "prettier --write \"{src,tests,hardhat,scripts}/**/*.ts\"", "lint": "tslint -p tsconfig.json" }, "repository": { diff --git a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts index 15f056e53..ac35bcb67 100644 --- a/packages/safe-core-sdk/scripts/generateTypechainFiles.ts +++ b/packages/safe-core-sdk/scripts/generateTypechainFiles.ts @@ -1,17 +1,16 @@ -const { execSync } = require('child_process') -const { readdir, mkdirSync, existsSync } = require('fs') -const path = require('path') +import { execSync } from 'child_process' +import { existsSync, mkdirSync, readdir } from 'fs' +import path from 'path' // Directories where the Typechain files will be generated const outDirSrc = 'typechain/src/' const typeChainDirectorySrcPath = path.join(__dirname, `../${outDirSrc}`) -const outDirTests = 'typechain/tests/' -const typeChainDirectoryTestsPath = path.join(__dirname, `../${outDirTests}`) - const outDirBuild = 'dist/typechain/src/' const typeChainDirectoryBuildPath = path.join(__dirname, `../${outDirBuild}`) +const outDirTests = 'typechain/tests/' + // Contract list for which the Typechain files will be generated // Will be included in dist/ folder const safeContractsPath = '../../node_modules/@gnosis.pm/safe-deployments/dist/assets' @@ -40,25 +39,16 @@ const testContracts = [ ].join(' ') // Remove existing Typechain files -execSync(`rimraf ${outDirSrc} ${outDirTests}`, (error) => { - if (error) { - console.log(error.message) - return - } -}) +execSync(`rimraf ${outDirSrc} ${outDirTests}`) // Generate Typechain files -function generateTypechainFiles(typechainVersion, outDir, contractList): void { - execSync(`typechain --target ${typechainVersion} --out-dir ${outDir} ${contractList}`, (error) => { - if (error) { - console.log(error.message) - } - }) +function generateTypechainFiles(typechainVersion: string, outDir: string, contractList: string): void { + execSync(`typechain --target ${typechainVersion} --out-dir ${outDir} ${contractList}`) console.log(`Generated typechain ${typechainVersion} at ${outDir}`) } // Copy Typechain files with the right extension (.d.ts -> .ts) allows them to be included in the build folder -function moveTypechainFiles(inDir, outDir): void { +function moveTypechainFiles(inDir: string, outDir: string): void { readdir(`${inDir}`, (error, files) => { if (error) { console.log(error)