diff --git a/typescript/infra/config/environments/mainnet3/owners.ts b/typescript/infra/config/environments/mainnet3/owners.ts index 5a4e941e3..755a8b491 100644 --- a/typescript/infra/config/environments/mainnet3/owners.ts +++ b/typescript/infra/config/environments/mainnet3/owners.ts @@ -42,6 +42,14 @@ export const safes: ChainMap
= { blast: '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5', linea: '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5', mode: '0xaCD1865B262C89Fb0b50dcc8fB095330ae8F35b5', + ancient8: '0xD2BFA0F0654E3f2139b8cDC56c32eeC54D32b133', + taiko: '0xa4864301d3fa2a3e68256309F9F0F570270a1BD0', + fraxtal: '0x66e9f52800E9F89F0569fddc594Acd5EE609f762', + sei: '0xCed197FBc360C26C19889745Cf73511b71D03d5D', + redstone: '0xa1a50ff5FD859558E1899fEC5C3064483177FA23', + mantle: '0x8aFE6EECc6CcB02aA20DA8Fff7d29aadEBbc2DCd', + bob: '0x9e2fe7723b018d02cDE4f5cC1A9bC9C65b922Fc8', + zetachain: '0x9d399876522Fc5C044D048594de399A2349d6026', }; export const DEPLOYER = '0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba'; diff --git a/typescript/infra/config/environments/mainnet3/safe/safeSigners.json b/typescript/infra/config/environments/mainnet3/safe/safeSigners.json new file mode 100644 index 000000000..d66b992ab --- /dev/null +++ b/typescript/infra/config/environments/mainnet3/safe/safeSigners.json @@ -0,0 +1,13 @@ +{ + "signers": [ + "0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba", + "0xc3E966E79eF1aA4751221F55fB8A36589C24C0cA", + "0x3b7f8f68A4FD0420FeA2F42a1eFc53422f205599", + "0x88436919fAa2310d32A36D20d13E0a441D24fAc3", + "0x003DDD9eEAb62013b7332Ab4CC6B10077a8ca961", + "0xd00d6A31485C93c597D1d8231eeeE0ed17B9844B", + "0x483fd7284A696343FEc0819DDF2cf7E06E8A06E5", + "0x5b73A98165778BCCE72979B4EE3faCdb31728b8E", + "0x5dd9a0814022A61777938263308EBB336174f13D" + ] +} diff --git a/typescript/infra/package.json b/typescript/infra/package.json index a7d4e2a20..3196e4c8e 100644 --- a/typescript/infra/package.json +++ b/typescript/infra/package.json @@ -18,6 +18,7 @@ "@hyperlane-xyz/sdk": "4.1.0", "@hyperlane-xyz/utils": "4.1.0", "@nomiclabs/hardhat-etherscan": "^3.0.3", + "@safe-global/protocol-kit": "^4.0.2", "@solana/web3.js": "^1.78.0", "asn1.js": "5.4.1", "aws-kms-ethers-signer": "^0.1.3", diff --git a/typescript/infra/scripts/agent-utils.ts b/typescript/infra/scripts/agent-utils.ts index 2046d4821..93e25ed9f 100644 --- a/typescript/infra/scripts/agent-utils.ts +++ b/typescript/infra/scripts/agent-utils.ts @@ -109,6 +109,19 @@ export function withChainRequired(args: Argv) { return withChain(args).demandOption('chain'); } +export function withSafeTxServiceUrlRequired(args: Argv) { + return args + .describe('safeTxServiceUrl', 'Custom safe transaction service url') + .demandOption('safeTxServiceUrl'); +} + +export function withThreshold(args: Argv) { + return args + .describe('threshold', 'threshold for multisig') + .number('threshold') + .default('threshold', 4); +} + export function withChain(args: Argv) { return args .describe('chain', 'chain name') diff --git a/typescript/infra/scripts/safes/create-safe.ts b/typescript/infra/scripts/safes/create-safe.ts new file mode 100644 index 000000000..bd5cd8807 --- /dev/null +++ b/typescript/infra/scripts/safes/create-safe.ts @@ -0,0 +1,79 @@ +import { SafeFactory } from '@safe-global/protocol-kit'; +import { SafeAccountConfig } from '@safe-global/protocol-kit'; + +import { Contexts } from '../../config/contexts.js'; +import { getChain } from '../../config/registry.js'; +import { Role } from '../../src/roles.js'; +import { readJSONAtPath } from '../../src/utils/utils.js'; +import { + getArgs, + getKeyForRole, + withChainRequired, + withSafeTxServiceUrlRequired, + withThreshold, +} from '../agent-utils.js'; + +const OWNERS_FILE_PATH = 'config/environments/mainnet3/safe/safeSigners.json'; + +async function main() { + const { chain, safeTxServiceUrl, threshold } = await withThreshold( + withSafeTxServiceUrlRequired(withChainRequired(getArgs())), + ).argv; + + const chainMetadata = await getChain(chain); + const rpcUrls = chainMetadata.rpcUrls; + const deployerPrivateKey = await getDeployerPrivateKey(); + + let safeFactory; + try { + safeFactory = await SafeFactory.init({ + provider: rpcUrls[0].http, + signer: deployerPrivateKey, + }); + } catch (e) { + console.error(`Error initializing SafeFactory: ${e}`); + process.exit(1); + } + + const ownersConfig = readJSONAtPath(OWNERS_FILE_PATH); + const owners = ownersConfig.signers; + + const safeAccountConfig: SafeAccountConfig = { + owners, + threshold, + }; + + let safe; + try { + safe = await safeFactory.deploySafe({ safeAccountConfig }); + } catch (e) { + console.error(`Error deploying Safe: ${e}`); + process.exit(1); + } + + const safeAddress = await safe.getAddress(); + + console.log(`Safe address: ${safeAddress}`); + console.log( + `Safe url: ${safeTxServiceUrl}/home?safe=${chain}:${safeAddress}`, + ); + console.log('url may not be correct, please check by following the link'); +} + +const getDeployerPrivateKey = async () => { + const key = await getKeyForRole( + 'mainnet3', + Contexts.Hyperlane, + Role.Deployer, + ); + await key.fetch(); + + return key.privateKey; +}; + +main() + .then() + .catch((e) => { + console.error(e); + process.exit(1); + }); diff --git a/yarn.lock b/yarn.lock index bb9a49a02..50e82ebaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,6 +19,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.10.1": + version: 1.10.1 + resolution: "@adraffy/ens-normalize@npm:1.10.1" + checksum: 4cb938c4abb88a346d50cb0ea44243ab3574330c81d4f5aaaf9dfee584b96189d0faa404de0fcbef5a1b73909ea4ebc3e63d84bd23f9949e5c8d4085207a5091 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -5843,6 +5850,7 @@ __metadata: "@nomiclabs/hardhat-ethers": "npm:^2.2.3" "@nomiclabs/hardhat-etherscan": "npm:^3.0.3" "@nomiclabs/hardhat-waffle": "npm:^2.0.6" + "@safe-global/protocol-kit": "npm:^4.0.2" "@solana/web3.js": "npm:^1.78.0" "@types/chai": "npm:^4.2.21" "@types/json-stable-stringify": "npm:^1.0.36" @@ -7054,6 +7062,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:^1.3.3": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: e156e65794c473794c52fa9d06baf1eb20903d0d96719530f523cc4450f6c721a957c544796e6efd0197b2296e7cd70efeb312f861465e17940a3e3c7e0febc6 + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.5.5, @noble/secp256k1@npm:~1.5.2": version: 1.5.5 resolution: "@noble/secp256k1@npm:1.5.5" @@ -8067,6 +8082,21 @@ __metadata: languageName: node linkType: hard +"@safe-global/protocol-kit@npm:^4.0.2": + version: 4.0.2 + resolution: "@safe-global/protocol-kit@npm:4.0.2" + dependencies: + "@noble/hashes": "npm:^1.3.3" + "@safe-global/safe-core-sdk-types": "npm:^5.0.2" + "@safe-global/safe-deployments": "npm:^1.37.0" + abitype: "npm:^1.0.2" + ethereumjs-util: "npm:^7.1.5" + ethers: "npm:^6.13.1" + semver: "npm:^7.6.2" + checksum: aff8dfda28e2adc0a965969fb3513354eda7d4bf8de574075ccdac932b48337063f519fcffcf71b53b97658009e390ec7dbea84bd6c0a19ec6ff18c0a4570b68 + languageName: node + linkType: hard + "@safe-global/safe-apps-provider@npm:^0.15.2": version: 0.15.2 resolution: "@safe-global/safe-apps-provider@npm:0.15.2" @@ -8110,6 +8140,15 @@ __metadata: languageName: node linkType: hard +"@safe-global/safe-core-sdk-types@npm:^5.0.2": + version: 5.0.2 + resolution: "@safe-global/safe-core-sdk-types@npm:5.0.2" + dependencies: + abitype: "npm:^1.0.2" + checksum: 53f0221e1c86b5b04f75cc773527e5e9c59ebb13ec21fe9a9246f6834c45b107e9a165da08ed58d40ed2564952f5360fb4c02051f236bfcc61bbfdb6015e3663 + languageName: node + linkType: hard + "@safe-global/safe-deployments@npm:^1.26.0": version: 1.26.0 resolution: "@safe-global/safe-deployments@npm:1.26.0" @@ -8119,6 +8158,15 @@ __metadata: languageName: node linkType: hard +"@safe-global/safe-deployments@npm:^1.37.0": + version: 1.37.1 + resolution: "@safe-global/safe-deployments@npm:1.37.1" + dependencies: + semver: "npm:^7.6.2" + checksum: 2cb05ad0d1768264885d9e92d1fcc1340af77f88605ac46fd99b8aa4118d923671e4bb3d380e3dd7caa13ca4e8ed6edae4765dd5394b78966a51f391375d683b + languageName: node + linkType: hard + "@safe-global/safe-gateway-typescript-sdk@npm:^3.5.3": version: 3.17.0 resolution: "@safe-global/safe-gateway-typescript-sdk@npm:3.17.0" @@ -9770,6 +9818,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: b9bbe923573797ef7c5fd2641a6793489e25d9369c32aeadcaa5c7c175c85b42eb12d6fe173f6781ab6f42eaa1ebd9576a419eeaa2a1ec810094adb8adaa9a54 + languageName: node + linkType: hard + "@types/node@npm:>=13.7.0": version: 20.8.9 resolution: "@types/node@npm:20.8.9" @@ -10864,6 +10919,21 @@ __metadata: languageName: node linkType: hard +"abitype@npm:^1.0.2": + version: 1.0.5 + resolution: "abitype@npm:1.0.5" + peerDependencies: + typescript: ">=5.0.4" + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + checksum: 1acd0d9687945dd78442b71bd84ff3b9dceae27d15f0d8b14b16554a0c8c9518eeb971ff8e94d507f4d9f05a8a8b91eb8fafd735eaecebac37d5c5a4aac06d8e + languageName: node + linkType: hard + "abort-controller@npm:^3.0.0": version: 3.0.0 resolution: "abort-controller@npm:3.0.0" @@ -10991,6 +11061,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: 8f745da2e8fb38e91297a8ec13c2febe3219f8383303cd4ed4660ca67190242ccfd5fdc2f0d1642fd1ea934818fb871cd4cc28d3f28e812e3dc6c3d0f1f97c24 + languageName: node + linkType: hard + "aes-js@npm:^3.1.2": version: 3.1.2 resolution: "aes-js@npm:3.1.2" @@ -14788,6 +14865,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.13.1": + version: 6.13.1 + resolution: "ethers@npm:6.13.1" + dependencies: + "@adraffy/ens-normalize": "npm:1.10.1" + "@noble/curves": "npm:1.2.0" + "@noble/hashes": "npm:1.3.2" + "@types/node": "npm:18.15.13" + aes-js: "npm:4.0.0-beta.5" + tslib: "npm:2.4.0" + ws: "npm:8.17.1" + checksum: efc3e8d4d13101cad01823ba524dad797a23f60088ca9f8677bd6dbfad5087e4187ede121e43aa0758d704525976f935860c5d5d27183a4247deaccf7cf19950 + languageName: node + linkType: hard + "ethjs-unit@npm:0.1.6": version: 0.1.6 resolution: "ethjs-unit@npm:0.1.6" @@ -22928,6 +23020,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.2": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 296b17d027f57a87ef645e9c725bff4865a38dfc9caf29b26aa084b85820972fbe7372caea1ba6857162fa990702c6d9c1d82297cecb72d56c78ab29070d2ca2 + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" @@ -24644,6 +24745,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:2.4.0, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: d8379e68b36caf082c1905ec25d17df8261e1d68ddc1abfd6c91158a064f6e4402039ae7c02cf4c81d12e3a2a2c7cd8ea2f57b233eb80136a2e3e7279daf2911 + languageName: node + linkType: hard + "tslib@npm:^2.0.0, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -24651,13 +24759,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0": - version: 2.4.0 - resolution: "tslib@npm:2.4.0" - checksum: d8379e68b36caf082c1905ec25d17df8261e1d68ddc1abfd6c91158a064f6e4402039ae7c02cf4c81d12e3a2a2c7cd8ea2f57b233eb80136a2e3e7279daf2911 - languageName: node - linkType: hard - "tsort@npm:0.0.1": version: 0.0.1 resolution: "tsort@npm:0.0.1" @@ -26237,6 +26338,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.17.1": + version: 8.17.1 + resolution: "ws@npm:8.17.1" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 4264ae92c0b3e59c7e309001e93079b26937aab181835fb7af79f906b22cd33b6196d96556dafb4e985742dd401e99139572242e9847661fdbc96556b9e6902d + languageName: node + linkType: hard + "ws@npm:^3.0.0": version: 3.3.3 resolution: "ws@npm:3.3.3"