-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathchange-multisig-owner.ts
More file actions
146 lines (126 loc) · 4.86 KB
/
change-multisig-owner.ts
File metadata and controls
146 lines (126 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import hre, { ethers } from "hardhat";
import { read } from "./deploy";
import multisigOwners from "../../multisig-owners.json";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
/**
* Changes the multisig.ts owner of the `LiquidityBridgeContract` deployed on the current network to the safe-test-contracts wallet
* provided.
*
* This function validates the provided `newOwner` address, ensures ownership configuration matches
* expectations, and performs the transfer of ownership to the new multisig.ts address. Additionally,
* it updates both the contract and proxy admin ownership.
*
* @async
* @param {string} newOwner - The address of the new multisig.ts owner (Safe contract).
* @param {string} network - The network where the script will run, by default will be the environment network.
* @param {HardhatEthersSigner} signer - Optional signer for test.
* @throws {Error} If the proxy contract is not deployed on the current network.
* @throws {Error} If the provided `newOwner` address is not a valid multisig.ts Safe contract.
* @throws {Error} If the configuration of owners on the Safe does not match the expected configuration.
* @returns {Promise<void>} Resolves when the ownership transfer process is complete.
*
* @example
* // Change the multisig.ts owner of the contract
* const newMultisigAddress = "0xNewSafeAddress";
* await changeMultisigOwner(newMultisigAddress);
*/
export const changeMultisigOwner = async (
newOwner: string,
network = "",
signer?: HardhatEthersSigner
) => {
network = network === "" ? hre.network.name : network;
console.info(`Changing multisig owner to: ${newOwner} - ${network}`);
const currentNetworkData =
multisigOwners[network as keyof typeof multisigOwners];
const { owners } = currentNetworkData;
const proxyName = "LiquidityBridgeContract";
const proxyAddress = read()[network][proxyName].address;
if (!proxyAddress) {
throw new Error(`Proxy ${proxyName} not deployed on network ${network}`);
}
console.info(`Proxy address: ${proxyAddress}`);
const safeOwners = await validateAndGetOwners(newOwner);
if (safeOwners.length === 0) {
throw new Error(
"Exiting... Provided Safe address is not a valid Safe contract."
);
}
validateOwners(safeOwners, owners);
console.info("Starting ownership transfer process...");
await transferOwnership(proxyAddress, newOwner, signer);
console.info("Ownership transfer process complete!");
};
async function validateAndGetOwners(address: string): Promise<string[]> {
try {
const code = await ethers.provider.getCode(address);
if (code === "0x") {
throw new Error(`${address} is not a smart contract`);
}
const contract = await ethers.getContractAt("GnosisSafe", address);
const version = await contract.VERSION();
const owners = await contract.getOwners();
if (owners.length === 0) {
throw new Error("Owners array is empty");
}
console.info(`Address ${address} is a Safe contract! Version: ${version}`);
return owners;
} catch (error) {
console.error(error);
throw new Error(`Address ${address} Is not a Safe address`);
}
}
function validateOwners(safeOwners: string[], expectedOwners: string[]): void {
const safeSet = new Set(safeOwners.map((owner) => owner.toLowerCase()));
const expectedSet = new Set(
expectedOwners.map((owner) => owner.toLowerCase())
);
const isValid =
safeSet.size === expectedSet.size &&
[...safeSet].every((owner) => expectedSet.has(owner));
if (isValid) {
console.info(`Safe ownership matches expected configuration.`);
} else {
throw new Error(`Safe ownership does not match expected configuration.`);
}
}
async function transferOwnership(
proxyAddress: string,
newOwnerAddress: string,
signer?: HardhatEthersSigner
): Promise<void> {
try {
const contract = await ethers.getContractAt(
"LiquidityBridgeContractV2",
proxyAddress
);
const currentOwner = await contract.owner();
console.info(
`Current owner of contract at ${proxyAddress}: ${currentOwner}`
);
if (currentOwner.toLowerCase() === newOwnerAddress.toLowerCase()) {
console.info(
`Ownership of contract at ${proxyAddress} is already set to ${newOwnerAddress}`
);
return;
}
console.info(
`Transferring ownership of contract at ${proxyAddress} to ${newOwnerAddress}...`
);
const connectedContract = signer ? contract.connect(signer) : contract;
await connectedContract.transferOwnership(newOwnerAddress);
console.info(
`Ownership of contract at ${proxyAddress} successfully transferred to ${newOwnerAddress}!`
);
await hre.upgrades.admin.transferProxyAdminOwnership(
proxyAddress,
newOwnerAddress,
signer
);
} catch (error) {
console.error(
`Failed to transfer ownership of contract at ${proxyAddress}:`,
error
);
}
}