Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(governance): script to add an owner to multisig (#13439)
* script to add a multisig owner * add cli task * use correct nonce so we dont override existing tx * fail early if no multisig address is passed * move `all_networks` to governance * switch for testnets * try/actach errors when looping * upgrade safe..glbal libs to latest
- Loading branch information
Showing
5 changed files
with
156 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#!/usr/bin/env node | ||
/** | ||
* | ||
* Just a small util to run a hardhat script for all networks | ||
* | ||
* Usage: scripts/all_networks run scripts/etc... | ||
* Usage: scripts/all_networks unlock:info | ||
*/ | ||
|
||
const allNetworks = require('@unlock-protocol/networks') | ||
const { execSync } = require('child_process') | ||
|
||
// if any network is present this array, only these will be executed | ||
const only = [] | ||
|
||
// these networks will be excluded from run | ||
const toExclude = ['localhost', 'default', 'networks'] | ||
const excludeTestnets = true | ||
|
||
const networks = only.length | ||
? only | ||
: Object.keys(allNetworks).filter( | ||
(n) => | ||
!toExclude.includes(n) && | ||
(excludeTestnets ? !allNetworks[n].isTestNetwork : true) | ||
) | ||
|
||
console.log(`Running task for the following networks: ${networks.toString()}`) | ||
|
||
for (let i = 0; i < networks.length; i++) { | ||
const cmd = `yarn hardhat` | ||
const args = ['--network', networks[i], ...process.argv.slice(2)] | ||
|
||
console.log(cmd, args) | ||
try { | ||
execSync(`${cmd} ${args.join(' ')}`, { | ||
stdio: 'inherit', | ||
}) | ||
} catch (error) { | ||
console.log(`Network ${networks[i]} failed`) | ||
console.log(error.message) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
const { ethers } = require('hardhat') | ||
|
||
const { getNetwork } = require('@unlock-protocol/hardhat-helpers') | ||
const Safe = require('@safe-global/protocol-kit').default | ||
const { EthersAdapter } = require('@safe-global/protocol-kit') | ||
const SafeApiKit = require('@safe-global/api-kit').default | ||
|
||
async function main({ newOwner, safeAddress, threshold } = {}) { | ||
const { id, multisig, name } = await getNetwork() | ||
let [signer] = await ethers.getSigners() | ||
|
||
if (!safeAddress) { | ||
safeAddress = multisig | ||
} | ||
|
||
if (!safeAddress) { | ||
throw new Error(`Missing multisig address for ${name} [${id}].`) | ||
} | ||
|
||
// default to ccarfi.eth | ||
console.log(`Adding signer ${newOwner} on chain on ${id}: | ||
- multisig: ${safeAddress} | ||
- signer: ${signer.address} | ||
`) | ||
|
||
// Use Safe v1+ with SDK | ||
const ethAdapter = new EthersAdapter({ | ||
ethers, | ||
signerOrProvider: signer, | ||
}) | ||
|
||
const safeSdk = await Safe.create({ ethAdapter, safeAddress }) | ||
const safeService = new SafeApiKit({ | ||
chainId: id, | ||
}) | ||
|
||
// get nonce so we make sure we dont erase current pending tx | ||
const nonce = await safeService.getNextNonce(safeAddress) | ||
const safeTransaction = await safeSdk.createAddOwnerTx( | ||
{ | ||
ownerAddress: newOwner, | ||
// threshold | ||
}, | ||
{ nonce } | ||
) | ||
|
||
// Get the transaction hash of the safeTransaction | ||
const safeTransactionHash = await safeSdk.getTransactionHash(safeTransaction) | ||
console.log(`submitting tx with hash : ${safeTransactionHash} ...`) | ||
|
||
// get signature | ||
const senderSignature = await safeSdk.signTransactionHash(safeTransactionHash) | ||
|
||
// Propose the transaction | ||
const txParams = { | ||
safeAddress, | ||
safeTransactionData: safeTransaction.data, | ||
safeTxHash: safeTransactionHash, | ||
senderAddress: signer.address, | ||
senderSignature: senderSignature.data, | ||
} | ||
|
||
await safeService.proposeTransaction(txParams) | ||
const { nonce: actualNonce } = await safeService.getTransaction( | ||
safeTransactionHash | ||
) | ||
console.log(`tx submitted - nonce: [${actualNonce}].`) | ||
} | ||
|
||
// execute as standalone | ||
if (require.main === module) { | ||
main() | ||
.then(() => process.exit(0)) | ||
.catch((error) => { | ||
console.error(error) | ||
process.exit(1) | ||
}) | ||
} | ||
|
||
module.exports = main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters