Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiSend #23

Merged
merged 40 commits into from
May 24, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e22e52a
Document missing exceptions
germartinez Apr 21, 2021
05e6daf
Add Multisend contract to tests
germartinez Apr 21, 2021
7ebe20f
Add MultiSend contract ABI
germartinez Apr 21, 2021
464d9b3
Rename safeContract variables
germartinez Apr 21, 2021
ae33f16
Add contract networks configuration
germartinez Apr 21, 2021
fc03efb
Add MultiSend utils functions
germartinez Apr 21, 2021
22569eb
Add Contract Manager
germartinez Apr 22, 2021
e7d5a05
Fix build script
germartinez Apr 22, 2021
9deadb6
Update EthersSafe to use ContractManager
germartinez Apr 22, 2021
6b98ff6
Adapt createTransaction method to support batch transactions
germartinez Apr 22, 2021
9c406c2
Add GitHub and npm badges to README file
germartinez Apr 22, 2021
1b580c5
Update README with MultiSend new changes
germartinez Apr 22, 2021
094f6cc
Test contract manager
germartinez Apr 29, 2021
58901fe
Document exceptions in README file
germartinez Apr 29, 2021
f0f54c4
Refactor tests to support batch transactions
germartinez Apr 29, 2021
49f0668
Merge branch 'main' into multisend
germartinez May 6, 2021
6d1160b
Update dependencies
germartinez May 6, 2021
323d3b0
Move safe-core-sdk to packages folder
germartinez May 6, 2021
742ef59
Add lerna
germartinez May 6, 2021
cbf558e
Add Monorepo README file
germartinez May 6, 2021
2728dfe
Add colors to scripts output when using Lerna
germartinez May 6, 2021
26de7d5
Configure tsconfig files
germartinez May 7, 2021
bcc3577
Update dependencies
germartinez May 7, 2021
2ca74ad
Fix test in GitHub action
germartinez May 7, 2021
f866e3e
Merge pull request #24 from gnosis/monorepo
germartinez May 7, 2021
c70d457
Rename getSafeAddress method
germartinez May 7, 2021
f836eec
Rename transaction types
germartinez May 7, 2021
be73eea
Update createTransaction params format
germartinez May 10, 2021
efdd601
Add ERC20Mintable contract for testing
germartinez May 16, 2021
f6f8c35
Add test case for multisend with contract calls
germartinez May 16, 2021
b1aa8df
Refactor getOwners
germartinez May 16, 2021
3ede308
Update dependencies
germartinez May 16, 2021
79e7ab9
Merge branch 'main' into multisend
germartinez May 24, 2021
0bf226b
Removed unused test setup file
germartinez May 24, 2021
de378bf
Standardize function definitions
germartinez May 24, 2021
7bcdbdb
Remove unused interface
germartinez May 24, 2021
36aaded
Update monorepo test script to run all tests from packages
germartinez May 24, 2021
cd29ee6
Add exclude to tsconfig base
germartinez May 24, 2021
f1dbacb
Improve types documentation
germartinez May 24, 2021
010c193
Fix Github workflow for testing
germartinez May 24, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 58 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Safe Core SDK

[![NPM Version](https://badge.fury.io/js/%40gnosis.pm%2Fsafe-core-sdk.svg)](https://badge.fury.io/js/%40gnosis.pm%2Fsafe-core-sdk)
[![GitHub Release](https://img.shields.io/github/release/gnosis/safe-core-sdk.svg?style=flat)](https://github.com/gnosis/safe-core-sdk/releases)
[![GitHub](https://img.shields.io/github/license/gnosis/safe-core-sdk)](https://github.com/gnosis/safe-core-sdk/blob/main/LICENSE.md)
[![Coverage Status](https://coveralls.io/repos/github/gnosis/safe-core-sdk/badge.svg?branch=main)](https://coveralls.io/github/gnosis/safe-core-sdk?branch=main)

Software development kit that facilitates the interaction with the [Gnosis Safe contracts](https://github.com/gnosis/safe-contracts).
Expand Down Expand Up @@ -28,7 +31,7 @@ A Safe account with three owners and threshold equal three will be used as the s

```js
import { ethers } from 'ethers'
import EthersSafe, { SafeTransaction } from '@gnosis.pm/safe-core-sdk'
import EthersSafe from '@gnosis.pm/safe-core-sdk'

const web3Provider = // ...
const provider = new ethers.providers.Web3Provider(web3Provider)
Expand All @@ -38,23 +41,23 @@ const signer3 = provider.getSigner(2)

// Existing Safe address (e.g. Safe created via https://app.gnosis-safe.io)
// Where signer1, signer2 and signer3 are the Safe owners
const safeAddress = "0x<safe_address>"
const safeAddress = '0x<safe_address>'
```

Create an instance of the Safe Core SDK with `signer1` connected as the signer.

```js
const safeSdk = await EthersSafe.create(ethers, safeAddress, signer1)
const safeSdk = await EthersSafe.create({ ethers, safeAddress, providerOrSigner: signer1 })
```

### 1. Create a Safe transaction

```js
const tx = await safeSdk.createTransaction({
const tx = await safeSdk.createTransaction([{
to: safeAddress,
value: '0',
data: '0x',
})
value: '<eth_value_in_wei>',
data: '0x<data>'
}])
```

Before executing this transaction, it must be signed by the owners and this can be done off-chain or on-chain. In this example the owner `signer1` will sign it off-chain and the owner `signer3` would have to explicitly sign it too.
Expand All @@ -74,7 +77,7 @@ Because the signature is off-chain, there is no interaction with the contract an
After `signer2` account is connected to the SDK as the signer the transaction hash is approved on-chain.

```js
const safeSdk2 = await safeSdk.connect(signer2)
const safeSdk2 = await safeSdk.connect({ providerOrSigner: signer2 })
const txHash = await safeSdk2.getTransactionHash(tx)
const signer2Signature = await safeSdk2.approveTransactionHash(txHash)
```
Expand All @@ -84,7 +87,7 @@ const signer2Signature = await safeSdk2.approveTransactionHash(txHash)
Lastly, `signer3` account is connected to the SDK as the signer and executor of the Safe transaction to execute it.

```js
const safeSdk3 = await safeSdk2.connect(signer3)
const safeSdk3 = await safeSdk2.connect({ providerOrSigner: signer3 })
const txResponse = await safeSdk3.executeTransaction(tx)
await txResponse.wait()
```
Expand All @@ -97,27 +100,49 @@ All the signatures used to execute the transaction are available at `tx.signatur
Returns an instance of the Safe Core SDK with the `providerOrSigner` connected to the `safeAddress`.

```js
const safeSdk = await EthersSafe.create(ethers, safeAddress, providerOrSigner)
const safeSdk = await EthersSafe.create({ ethers, safeAddress, providerOrSigner })
germartinez marked this conversation as resolved.
Show resolved Hide resolved
```

If `providerOrSigner` is not provided, `ethers` default provider will be used.

```js
const safeSdk = await EthersSafe.create(ethers, safeAddress)
const safeSdk = await EthersSafe.create({ ethers, safeAddress })
```

The property `contractNetworks` can be added 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>'
}
}
const safeSdk = await EthersSafe.create({ ethers, safeAddress, providerOrSigner, contractNetworks })
```

### connect

Returns a new instance of the Safe Core SDK with the `providerOrSigner` connected to the `safeAddress`.

```js
const safeSdk2 = await safeSdk.connect(providerOrSigner, safeAddress)
const safeSdk2 = await safeSdk.connect({ providerOrSigner, safeAddress })
```

If `safeAddress` is not provided, the `providerOrSigner` will be connected to the previous Safe.

```js
const safeSdk2 = await safeSdk.connect(providerOrSigner)
const safeSdk2 = await safeSdk.connect({ providerOrSigner })
```

The property `contractNetworks` can be added 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>'
}
}
const safeSdk = await EthersSafe.create({ ethers, safeAddress, providerOrSigner, contractNetworks })
```

### getProvider
Expand All @@ -136,12 +161,12 @@ Returns the connected signer.
const signer = safeSdk.getSigner()
```

### getAddress
### getSafeAddress

Returns the address of the current Safe Proxy contract.

```js
const address = safeSdk.getAddress()
const address = safeSdk.getSafeAddress()
germartinez marked this conversation as resolved.
Show resolved Hide resolved
```

### getContractVersion
Expand Down Expand Up @@ -218,7 +243,7 @@ const isOwner = await safeSdk.isOwner(address)

### createTransaction

Returns a Safe transaction ready to be signed by the owners and executed.
Returns a Safe transaction ready to be signed by the owners and executed. Batched transactions are allowed if more than one transaction is added to the array of transactions.

Each of the transactions provided as input to this function must be an object with the following properties:

Expand All @@ -236,22 +261,27 @@ Each of the transactions provided as input to this function must be an object wi
Read more about the [Safe transaction properties](https://docs.gnosis.io/safe/docs/contracts_tx_execution/).

```js
const partialTx: SafeTransactionDataPartial = {
const partialTx1: SafeTransactionDataPartial = {
to: '0x<address>',
data: '0x<data>',
value: '<eth_value_in_wei>'
}
const partialTx2: SafeTransactionDataPartial = {
to: '0x<address>',
data: '0x<data>',
value: '<eth_value_in_wei>'
}
const safeTransaction = await safeSdk.createTransaction(partialTx)
const safeTransaction = await safeSdk.createTransaction([partialTx1, partialTx2])
germartinez marked this conversation as resolved.
Show resolved Hide resolved
```

### getTransactionHash

Returns the transaction hash of a Safe transaction.

```js
const tx = await safeSdk.createTransaction({
const tx = await safeSdk.createTransaction([{
// ...
})
}])
const txHash = await safeSdk.getTransactionHash(tx)
```

Expand All @@ -260,9 +290,9 @@ const txHash = await safeSdk.getTransactionHash(tx)
Signs a hash using the current signer account.

```js
const tx = await safeSdk.createTransaction({
const tx = await safeSdk.createTransaction([{
// ...
})
}])
const txHash = await safeSdk.getTransactionHash(tx)
const signature = await safeSdk.signTransactionHash(txHash)
```
Expand All @@ -272,9 +302,9 @@ const signature = await safeSdk.signTransactionHash(txHash)
Adds the signature of the current signer to the Safe transaction object.

```js
const tx = await safeSdk.createTransaction({
const tx = await safeSdk.createTransaction([{
// ...
})
}])
await safeSdk.signTransaction(tx)
```

Expand All @@ -283,9 +313,9 @@ await safeSdk.signTransaction(tx)
Approves on-chain a hash using the current signer account.

```js
const tx = await safeSdk.createTransaction({
const tx = await safeSdk.createTransaction([{
// ...
})
}])
const txHash = await safeSdk.getTransactionHash(tx)
const txResponse = await safeSdk.approveTransactionHash(txHash)
await txResponse.wait()
Expand All @@ -296,9 +326,9 @@ await txResponse.wait()
Returns a list of owners who have approved a specific Safe transaction.

```js
const tx = await safeSdk.createTransaction({
const tx = await safeSdk.createTransaction([{
// ...
})
}])
const txHash = await safeSdk.getTransactionHash(tx)
const owners = await safeSdk.getOwnersWhoApprovedTx(txHash)
```
Expand Down
1 change: 1 addition & 0 deletions contracts/Deps.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ 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";
7 changes: 7 additions & 0 deletions hardhat/deploy/deploy-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ const deploy: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
deterministicDeployment: true
})

await deploy('MultiSend', {
from: deployer,
args: [],
log: true,
deterministicDeployment: true
})

await deploy('DailyLimitModule', {
from: deployer,
args: [],
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
"@types/chai": "^4.2.17",
"@types/chai-as-promised": "^7.1.3",
"@types/mocha": "^8.2.2",
"@types/node": "^15.0.1",
"@types/node": "^15.0.2",
"@types/yargs": "^16.0.1",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"@typescript-eslint/eslint-plugin": "^4.22.1",
"@typescript-eslint/parser": "^4.22.1",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"coveralls": "^3.1.0",
"dotenv": "^8.2.0",
"dotenv": "^9.0.0",
"eslint": "^7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
Expand All @@ -65,7 +65,7 @@
"ts-node": "^9.1.1",
"typechain": "^4.0.3",
"typescript": "^4.2.4",
"yargs": "^16.2.0"
"yargs": "^17.0.1"
},
"lint-staged": {
"src/**/!(*test).ts": [
Expand Down
Loading