-
Notifications
You must be signed in to change notification settings - Fork 68
/
FeeContract.s.sol
207 lines (172 loc) · 9.34 KB
/
FeeContract.s.sol
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
pragma solidity ^0.8.20;
import { Script } from "forge-std/Script.sol";
import {
ProposeUpgradeResponse,
Defender,
ApprovalProcessResponse
} from "openzeppelin-foundry-upgrades/Defender.sol";
import { Upgrades, Options } from "openzeppelin-foundry-upgrades/Upgrades.sol";
import { FeeContract as FC } from "../src/FeeContract.sol";
import { UtilsScript } from "./Utils.s.sol";
/// @notice Deploys an upgradeable Fee Contract using the OpenZeppelin Upgrades plugin.
contract DeployFeeContractScript is Script {
string internal contractName = vm.envString("FEE_CONTRACT_ORIGINAL_NAME");
/// @dev Deploys both the proxy and the implementation contract.
/// The proxy admin is set as the owner of the contract upon deployment.
/// The `owner` parameter should be the address of the multisig wallet to ensure proper
/// ownership management.
/// @param owner The address that will be set as the owner of the proxy (typically a multisig
/// wallet).
function run(address owner)
public
returns (address payable proxy, address implementationAddress)
{
string memory seedPhrase = vm.envString("DEPLOYER_MNEMONIC");
uint32 seedPhraseOffset = uint32(vm.envUint("DEPLOYER_MNEMONIC_OFFSET"));
(address admin,) = deriveRememberKey(seedPhrase, seedPhraseOffset);
vm.startBroadcast(admin);
address proxyAddress =
Upgrades.deployUUPSProxy(contractName, abi.encodeCall(FC.initialize, (owner)));
// Get the implementation address
implementationAddress = Upgrades.getImplementationAddress(proxyAddress);
vm.stopBroadcast();
return (payable(proxyAddress), implementationAddress);
}
}
/// @notice Upgrades the fee contract first by deploying the new implementation
/// and then executing the upgrade via the Safe Multisig wallet using the SAFE SDK.
contract UpgradeFeeContractScript is Script {
string internal originalContractName = vm.envString("FEE_CONTRACT_ORIGINAL_NAME");
string internal upgradeContractName = vm.envString("FEE_CONTRACT_UPGRADE_NAME");
/// @dev This function first deploys the new implementation contract using the deployer wallet.
/// It then uses the SAFE SDK via an ffi command to perform the upgrade through a Safe Multisig
/// wallet.
function run() public returns (address implementationAddress, bytes memory result) {
Options memory opts;
opts.referenceContract = originalContractName;
// validate that the new implementation contract is upgrade safe
Upgrades.validateUpgrade(upgradeContractName, opts);
// get the deployer info from the environment and start broadcast as the deployer
string memory seedPhrase = vm.envString("DEPLOYER_MNEMONIC");
uint32 seedPhraseOffset = uint32(vm.envUint("DEPLOYER_MNEMONIC_OFFSET"));
(address admin,) = deriveRememberKey(seedPhrase, seedPhraseOffset);
vm.startBroadcast(admin);
// deploy the new implementation contract
FC implementationContract = new FC();
vm.stopBroadcast();
//replace with something like this if there is some initiation function to call
// abi.encodeWithSignature("setNewField(uint256)", 2);
bytes memory initData = "";
// call upgradeToAndCall command so that the proxy can be upgraded to call from the new
// implementation above and
// execute the command via the Safe Multisig wallet
string[] memory cmds = new string[](3);
cmds[0] = "bash";
cmds[1] = "-c";
cmds[2] = string(
abi.encodePacked(
"source .env.contracts && ts-node contracts/script/multisigTransactionProposals/safeSDK/upgradeProxy.ts upgradeProxy ",
vm.toString(vm.envAddress("FEE_CONTRACT_PROXY_ADDRESS")),
" ",
vm.toString(address(implementationContract)),
" ",
vm.toString(initData)
)
);
result = vm.ffi(cmds);
return (address(implementationContract), result);
}
}
/// @notice Deploys an upgradeable Fee Contract using OpenZeppelin Defender.
/// the deployment environment details are set in OpenZeppelin Defender which is
/// identified via the Defender Key and Secret in the environment file
contract DeployFeeContractWithDefenderScript is Script {
string internal contractName = vm.envString("FEE_CONTRACT_ORIGINAL_NAME");
UtilsScript internal utils = new UtilsScript();
uint256 internal contractSalt = uint256(vm.envInt("FEE_CONTRACT_SALT"));
/// @dev When this function is run, a transaction to deploy the implementation is submitted to
/// Defender
/// This transaction must be signed via OpenZeppelin Defender's UI and once it completes
/// another transaction is available to sign for the deployment of the proxy
function run() public returns (address payable proxy, address multisig) {
ApprovalProcessResponse memory upgradeApprovalProcess = Defender.getUpgradeApprovalProcess();
multisig = upgradeApprovalProcess.via;
string memory approvalProcessId = upgradeApprovalProcess.approvalProcessId;
string memory viaType = upgradeApprovalProcess.viaType;
if (upgradeApprovalProcess.via == address(0)) {
revert(
string.concat(
"Upgrade approval process with id ",
upgradeApprovalProcess.approvalProcessId,
" has no assigned address"
)
);
}
Options memory opts;
opts.defender.useDefenderDeploy = true;
opts.defender.salt = bytes32(abi.encodePacked(contractSalt));
address proxyAddress =
Upgrades.deployUUPSProxy(contractName, abi.encodeCall(FC.initialize, (multisig)), opts);
//generate the deployment file path, output and write to the file
(string memory filePath, string memory fileData) = utils.generateProxyDeploymentOutput(
contractName, contractSalt, proxyAddress, multisig, approvalProcessId, viaType
);
utils.writeJson(filePath, fileData);
//generate the salt history file path, output and write to the file
(string memory saltFilePath, string memory saltFileData) =
utils.generateSaltOutput(contractName, contractSalt);
utils.writeJson(saltFilePath, saltFileData);
return (payable(proxyAddress), multisig);
}
}
/// @notice Upgrades the Fee Contract using OpenZeppelin Defender.
/// the deployment environment details are set in OpenZeppelin Defender which is
/// identified via the Defender Key and Secret in the environment file
contract UpgradeFeeContractWithDefenderScript is Script {
string internal originalContractName = vm.envString("FEE_CONTRACT_ORIGINAL_NAME");
string internal upgradeContractName = vm.envString("FEE_CONTRACT_UPGRADE_NAME");
uint256 internal contractSalt = uint256(vm.envInt("FEE_CONTRACT_SALT"));
UtilsScript internal utils = new UtilsScript();
/// @dev When this function is run, a transaction to deploy the new implementation is submitted
/// to Defender
/// This transaction must be signed via OpenZeppelin Defender's UI and once it completes
/// another transaction is available to sign to call the upgrade method on the proxy
function run() public returns (string memory proposalId, string memory proposalUrl) {
//get the previous salt from the salt history - this assumes there was first a deployment
// using `DeployFeeContractWithDefenderScript`
(string memory saltFilePath,) = utils.generateSaltFilePath(originalContractName);
(, string memory saltData) = utils.readFile(saltFilePath);
uint256 prevContractSalt = vm.parseJsonUint(saltData, ".previousSalt");
(string memory filePath,) =
utils.generateDeploymentFilePath(originalContractName, prevContractSalt);
//read the deployment file from the previous deployment to get the proxyAddress & multisig
// used for deployment
(, string memory result) = utils.readFile(filePath);
address proxyAddress = vm.parseJsonAddress(result, ".proxyAddress");
address multisig = vm.parseJsonAddress(result, ".multisig");
//set openzeppelin defender options for the deployment
Options memory opts;
opts.defender.useDefenderDeploy = true;
opts.defender.salt = bytes32(abi.encodePacked(contractSalt));
opts.referenceContract = originalContractName;
//propose the upgrade via openzeppelin defender
ProposeUpgradeResponse memory response =
Defender.proposeUpgrade(proxyAddress, upgradeContractName, opts);
//generate the file path, file output (deployment info) and write to the file
(string memory upgradeFilePath, string memory fileData) = utils.generateUpgradeOutput(
originalContractName,
contractSalt,
upgradeContractName,
proxyAddress,
multisig,
response.proposalId,
response.url
);
utils.writeJson(upgradeFilePath, fileData);
//generate the salt history file path, output and write to the file
string memory saltFileData;
(saltFilePath, saltFileData) = utils.generateSaltOutput(originalContractName, contractSalt);
utils.writeJson(saltFilePath, saltFileData);
return (response.proposalId, response.url);
}
}