Skip to content

Commit

Permalink
Merge pull request #91 from gnosis/safe-deployments
Browse files Browse the repository at this point in the history
Get Safe contracts from safe-deployments
  • Loading branch information
germartinez authored Nov 16, 2021
2 parents ce26f26 + 33267d5 commit d5a7021
Show file tree
Hide file tree
Showing 56 changed files with 1,262 additions and 982 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Hardhat Test
name: Monorepo Test
on: [push, pull_request]
env:
INFURA_KEY: ${{ secrets.INFURA_KEY }}
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/test_V1_2_0.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Safe Core SDK Test (Safe v1.2.0)
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
cd packages/safe-core-sdk
yarn test:hardhat:ethers:v1.2.0
21 changes: 21 additions & 0 deletions .github/workflows/test_V1_3_0.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Safe Core SDK Test (Safe v1.3.0)
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
cd packages/safe-core-sdk
yarn test:hardhat:ethers:v1.3.0
33 changes: 30 additions & 3 deletions packages/safe-core-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,36 @@ const safeFactory = await SafeFactory.create({ ethAdapter })

const owners = ['0x<address>', '0x<address>', '0x<address>']
const threshold = 3
const safeAccountConfig: SafeAccountConfig = { owners, threshold }
const safeAccountConfig: SafeAccountConfig = {
owners,
threshold,
// ...
}

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 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' })
```

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<multisend_address>',
safeMasterCopyAddress: '0x<master_copy_address>',
safeProxyFactoryAddress: '0x<proxy_factory_address>'
}
}
const safeFactory = await SafeFactory.create({ ethAdapter, contractNetworks })
```

Call the method `getAddress`, for example, to check the address of the newly deployed Safe.

```js
Expand Down Expand Up @@ -153,7 +176,9 @@ The property `contractNetworks` can be added to provide the Safe contract addres
```js
const contractNetworks: ContractNetworksConfig = {
[chainId]: {
multiSendAddress: '0x<multisend_address>'
multiSendAddress: '0x<multisend_address>',
safeMasterCopyAddress: '0x<master_copy_address>',
safeProxyFactoryAddress: '0x<proxy_factory_address>'
}
}
const safeSdk = await Safe.create({ ethAdapter, safeAddress, contractNetworks })
Expand All @@ -172,7 +197,9 @@ The property `contractNetworks` can be added to provide the Safe contract addres
```js
const contractNetworks: ContractNetworksConfig = {
[chainId]: {
multiSendAddress: '0x<multisend_address>'
multiSendAddress: '0x<multisend_address>',
safeMasterCopyAddress: '0x<master_copy_address>',
safeProxyFactoryAddress: '0x<proxy_factory_address>'
}
}
const safeSdk = await Safe.connect({ ethAdapter, safeAddress, contractNetworks })
Expand Down
8 changes: 0 additions & 8 deletions packages/safe-core-sdk/contracts/Deps.sol

This file was deleted.

13 changes: 13 additions & 0 deletions packages/safe-core-sdk/contracts/Deps_V1_2_0.sol
Original file line number Diff line number Diff line change
@@ -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 {}
10 changes: 10 additions & 0 deletions packages/safe-core-sdk/contracts/Deps_V1_3_0.sol
Original file line number Diff line number Diff line change
@@ -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 {}
4 changes: 3 additions & 1 deletion packages/safe-core-sdk/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
34 changes: 30 additions & 4 deletions packages/safe-core-sdk/hardhat/deploy/deploy-contracts.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,52 @@
import { DeployFunction } from 'hardhat-deploy/types'
import { HardhatRuntimeEnvironment } from 'hardhat/types'

const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
type SafeVersion = '1.3.0' | '1.2.0' | '1.1.1'

export const safeVersionDeployed = process.env.SAFE_VERSION as SafeVersion

const gnosisSafeContracts = {
'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 = {
'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 = {
'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[safeVersionDeployed]
export const proxyFactoryDeployed = proxyFactoryContracts[safeVersionDeployed]
export const multiSendDeployed = multiSendContracts[safeVersionDeployed]

const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment): Promise<void> => {
const { deployments, getNamedAccounts } = hre
const { deployer } = await getNamedAccounts()
const { deploy } = deployments

await deploy('GnosisSafe', {
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,
Expand Down
21 changes: 13 additions & 8 deletions packages/safe-core-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@
"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": "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:web3 && 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",
"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": {
Expand All @@ -38,7 +41,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/[email protected]",
"@gnosis.pm/safe-contracts-v1.3.0": "npm:@gnosis.pm/[email protected]",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@nomiclabs/hardhat-web3": "^2.0.0",
Expand Down Expand Up @@ -87,6 +91,7 @@
},
"dependencies": {
"@gnosis.pm/safe-core-sdk-types": "^0.1.1",
"@gnosis.pm/safe-deployments": "^1.4.0",
"ethereumjs-util": "^7.0.10"
}
}
81 changes: 45 additions & 36 deletions packages/safe-core-sdk/scripts/generateTypechainFiles.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,67 @@
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-contracts/build/contracts'
const openZeppelinContractsPath = '../../node_modules/openzeppelin-solidity/build/contracts'
const safeContracts = [
`${safeContractsPath}/GnosisSafe.json`,
`${safeContractsPath}/GnosisSafeProxyFactory.json`,
`${safeContractsPath}/MultiSend.json`,
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/build/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(' ')

// 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) {
execSync(`typechain --target ${typechainVersion} --out-dir ${outDir}${typechainVersion} ${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(typechainVersion, inDir, outDir) {
readdir(`${inDir}${typechainVersion}`, (error, files) => {
function moveTypechainFiles(inDir: string, outDir: string): void {
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}`)
})
})
}
Expand All @@ -69,12 +70,20 @@ const web3V1 = 'web3-v1'
const ethersV5 = 'ethers-v5'

// Src: Web3 V1 types
generateTypechainFiles(web3V1, outDirSrc, safeContracts)
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, safeContracts)
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, testContracts)
generateTypechainFiles(ethersV5, `${outDirTests}${ethersV5}`, testContracts)
Loading

0 comments on commit d5a7021

Please sign in to comment.