UNPKG

tenderly-wizard-v6

Version:

A tool for managing virtual testnets using Tenderly

79 lines (78 loc) • 5.29 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.deploySafeV2 = deploySafeV2; exports.addSafeSigners = addSafeSigners; exports.removeDeployerAsOwner = removeDeployerAsOwner; const safe_master_copy_v2_json_1 = __importDefault(require("../contracts/safe_master_copy_v2.json")); const safe_proxy_factory_v2_json_1 = __importDefault(require("../contracts/safe_proxy_factory_v2.json")); const util_1 = require("../utils/util"); const colors_1 = __importDefault(require("colors")); // @ts-ignore const hardhat_1 = require("hardhat"); const constants_1 = require("../utils/constants"); const ethers_1 = require("ethers"); async function deploySafeV2(chainConfig, saltNonce) { const [caller] = await hardhat_1.ethers.getSigners(); const safeMaster = new hardhat_1.ethers.Contract(chainConfig.SAFE_MASTER_COPY_ADDR, safe_master_copy_v2_json_1.default, caller); // In v6, we need to use the function directly for populateTransaction const initializer = await safeMaster.setup.populateTransaction([caller.address], 1, //threshold ethers_1.ZeroAddress, "0x", chainConfig.DEFAULT_FALLBACK_HANDLER_ADDRESS, ethers_1.ZeroAddress, 0, ethers_1.ZeroAddress); const safeProxyFactory = new hardhat_1.ethers.Contract(chainConfig.SAFE_PROXY_FACTORY_ADDR, safe_proxy_factory_v2_json_1.default, caller); const txResponse = await safeProxyFactory.createProxyWithNonce(chainConfig.SAFE_MASTER_COPY_ADDR, initializer.data, saltNonce, { gasLimit: constants_1.GAS_LIMIT, }); const txReceipt = await txResponse.wait(); // In v6, we need to use logs and check the fragment name const txData = txReceipt.logs?.find((x) => x.fragment?.name === "ProxyCreation"); const deployedSafeAddress = txData?.args?.proxy; console.info(colors_1.default.green(`āœ… Safe was deployed to ${deployedSafeAddress}`)); return deployedSafeAddress; } async function addSafeSigners(safeAddr, newOwners, chainConfig) { const [caller] = await hardhat_1.ethers.getSigners(); const safe = new hardhat_1.ethers.Contract(safeAddr, safe_master_copy_v2_json_1.default, caller); const currentOwners = await safe.getOwners(); const hasCommonOwner = newOwners.some(newOwner => currentOwners.some(currentOwner => currentOwner.toLowerCase() === newOwner.toLowerCase())); if (!hasCommonOwner) { const addOwnersTxs = await Promise.all(newOwners.map(async (owner) => { // In v6, we use the function directly for populateTransaction return await safe.addOwnerWithThreshold.populateTransaction(owner, 1); })); const metaTxs = (0, util_1.createMultisendTx)(addOwnersTxs, chainConfig.MULTISEND_ADDR); const signature = (0, util_1.getPreValidatedSignatures)(caller.address); const addSignersTx = await safe.execTransaction(chainConfig.MULTISEND_ADDR, constants_1.tx.zeroValue, metaTxs.data, constants_1.SAFE_OPERATION_DELEGATECALL, constants_1.tx.avatarTxGas, constants_1.tx.baseGas, constants_1.tx.gasPrice, constants_1.tx.gasToken, constants_1.tx.refundReceiver, signature); const txReceipt = await addSignersTx.wait(); // In v6, we need to use logs and check the fragment name const txData = txReceipt.logs?.filter((x) => x.fragment?.name === "AddedOwner"); const ownersAddedFromEvent = txData.map((log) => log.args); console.info(`\nšŸ”‘ New owners added: ${ownersAddedFromEvent.join(", ")} on Safe: ${safeAddr}`); } else { console.info(`No new owners were added to Safe: ${safeAddr} as at least one owner you tried to add is already an owner on this Safe`); } } async function removeDeployerAsOwner(safeAddr, threshold) { const [caller] = await hardhat_1.ethers.getSigners(); const safe = new hardhat_1.ethers.Contract(safeAddr, safe_master_copy_v2_json_1.default, caller); const owners = await safe.getOwners(); const isDeployerStillOwner = owners.some(owner => owner.toLowerCase() === caller.address.toLowerCase()); if (isDeployerStillOwner) { const callerIndex = owners.findIndex(owner => owner === caller.address); const prevOwnerIndex = (callerIndex - 1 + owners.length) % owners.length; const prevOwner = owners[prevOwnerIndex]; // In v6, we use the function directly for populateTransaction const removeOwnersPopTx = await safe.removeOwner.populateTransaction(prevOwner, caller.address, threshold); const signature = (0, util_1.getPreValidatedSignatures)(caller.address); const removeTx = await safe.execTransaction(safeAddr, constants_1.tx.zeroValue, removeOwnersPopTx.data, constants_1.tx.operation, constants_1.tx.avatarTxGas, constants_1.tx.baseGas, constants_1.tx.gasPrice, constants_1.tx.gasToken, constants_1.tx.refundReceiver, signature, { gasLimit: constants_1.GAS_LIMIT, }); await removeTx.wait(); console.info(`\nšŸ”’ Deployer: ${caller.address} was removed as an owner on Safe: ${safeAddr}`); } else { console.info(`Deployer ${caller.address} is not an owner on Safe: ${safeAddr} so we can't remove them as an owner`); } }