-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathDeploy.s.sol
More file actions
341 lines (294 loc) · 11.2 KB
/
Deploy.s.sol
File metadata and controls
341 lines (294 loc) · 11.2 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
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.23;
import "forge-std/Script.sol";
import {
ISuperTokenFactory,
ISuperToken,
IERC20Metadata
} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol";
import { BridgedSuperTokenProxy, IBridgedSuperToken } from "../src/xchain/BridgedSuperToken.sol";
import { OPBridgedSuperTokenProxy, IOPBridgedSuperToken } from "../src/xchain/OPBridgedSuperToken.sol";
import { ArbBridgedSuperTokenProxy, IArbBridgedSuperToken } from "../src/xchain/ArbBridgedSuperToken.sol";
import { HomeERC20 } from "../src/xchain/HomeERC20.sol";
import { PureSuperTokenProxy, IPureSuperToken } from "../src/PureSuperToken.sol";
import { CustomERC20WrapperProxy, ICustomERC20Wrapper } from "../src/CustomERC20Wrapper.sol";
/// abstract base contract to avoid code duplication
abstract contract DeployBase is Script {
uint256 deployerPrivKey;
address superTokenFactoryAddr;
address owner;
string name;
string symbol;
uint256 initialSupply;
function _loadEnv() internal virtual {
// Support both private key and Foundry wallet account (via --account flag)
// If PRIVKEY is set, use it; otherwise use default account (from --account flag)
deployerPrivKey = vm.envOr("PRIVKEY", uint256(0));
// factory
superTokenFactoryAddr = vm.envOr("SUPERTOKEN_FACTORY", address(0));
owner = vm.envAddress("OWNER");
name = vm.envString("NAME");
symbol = vm.envString("SYMBOL");
initialSupply = vm.envOr("INITIAL_SUPPLY", uint256(0));
}
/// @notice Starts broadcast using private key or default account (from --account flag)
function _startBroadcast() internal {
if (deployerPrivKey != 0) {
vm.startBroadcast(deployerPrivKey);
} else {
vm.startBroadcast();
}
}
/// @notice Verifies that
/// - the proxy's implementation matches the canonical SuperToken implementation.
/// This gives more reassurance that the proxy wasn't tampered with by a fruntrunner.
/// The proxy implementation used here shouldn't be susceptible to this - meaning, "initialize()" is expected
/// to revert in case of frontrunning, because not relying on implementation contract logic
/// for setting the pointer. But it doesn't hurt to be extra cautious.
/// See https://dedaub.com/blog/the-cpimp-attack-an-insanely-far-reaching-vulnerability-successfully-mitigated/
/// - the SuperToken has been initialized as intended
/// @param proxy The proxy contract address to verify
function _verifyDeployment(address proxy) internal view {
bytes32 EIP_1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
address proxyImpl = address(uint160(uint256(vm.load(proxy, EIP_1967_IMPLEMENTATION_SLOT))));
address canonicalImpl = address((ISuperTokenFactory(superTokenFactoryAddr)).getSuperTokenLogic());
require(
proxyImpl == canonicalImpl,
"unexpected implementation set in proxy, doesn't match canonical SuperToken implementation"
);
ISuperToken token = ISuperToken(proxy);
require(keccak256(abi.encodePacked(token.name())) == keccak256(abi.encodePacked(name)), "name mismatch");
require(keccak256(abi.encodePacked(token.symbol())) == keccak256(abi.encodePacked(symbol)), "symbol mismatch");
require(token.totalSupply() == initialSupply, "totalSupply mismatch");
require(token.balanceOf(owner) == initialSupply, "balanceOf mismatch");
}
}
/// deploys an instance of HomeERC20
contract DeployL1Token is DeployBase {
function run() external {
_loadEnv();
_startBroadcast();
// log params
console.log("Deploying ERC20 with params:");
console.log(" name:", name);
console.log(" symbol:", symbol);
console.log(" initialSupply:", initialSupply);
console.log(" owner:", owner);
// since the token is permissionless and non-upgradable, the "owner" doesn't
// own the contract, just the initial supply
HomeERC20 erc20 = new HomeERC20(name, symbol, owner, initialSupply);
console.log("ERC20 deployed at", address(erc20));
vm.stopBroadcast();
}
}
/// Factory for atomic BridgedSuperTokenProxy deployment + initialization in one transaction.
contract BridgedSuperTokenFactory {
BridgedSuperTokenProxy public proxy;
constructor(
address superTokenFactoryAddr,
string memory name,
string memory symbol,
address owner,
uint256 initialSupply
) {
proxy = new BridgedSuperTokenProxy();
proxy.initialize(
ISuperTokenFactory(superTokenFactoryAddr),
name,
symbol,
owner,
initialSupply
);
proxy.transferOwnership(owner);
}
}
/// deploys and initializes an instance of BridgedSuperTokenProxy
contract DeployL2Token is DeployBase {
function run() external {
_loadEnv();
_startBroadcast();
BridgedSuperTokenFactory factory = new BridgedSuperTokenFactory(
superTokenFactoryAddr,
name,
symbol,
owner,
initialSupply
);
console.log("BridgedSuperTokenProxy deployed at", address(factory.proxy()));
vm.stopBroadcast();
_verifyDeployment(address(factory.proxy()));
}
}
/// Factory for atomic OPBridgedSuperTokenProxy deployment + initialization in one transaction.
contract OPBridgedSuperTokenFactory {
OPBridgedSuperTokenProxy public proxy;
constructor(
address nativeBridge,
address remoteToken,
address superTokenFactoryAddr,
string memory name,
string memory symbol,
address owner,
uint256 initialSupply
) {
proxy = new OPBridgedSuperTokenProxy(nativeBridge, remoteToken);
proxy.initialize(
ISuperTokenFactory(superTokenFactoryAddr),
name,
symbol,
owner,
initialSupply
);
proxy.transferOwnership(owner);
}
}
/// deploys and initializes an instance of OPBridgedSuperTokenProxy
contract DeployOPToken is DeployBase {
function run() external {
_loadEnv();
_startBroadcast();
address nativeBridge = vm.envAddress("NATIVE_BRIDGE");
address remoteToken = vm.envAddress("REMOTE_TOKEN");
OPBridgedSuperTokenFactory factory = new OPBridgedSuperTokenFactory(
nativeBridge,
remoteToken,
superTokenFactoryAddr,
name,
symbol,
owner,
initialSupply
);
console.log("OPBridgedSuperTokenProxy deployed at", address(factory.proxy()));
vm.stopBroadcast();
_verifyDeployment(address(factory.proxy()));
}
}
/// Factory for atomic ArbBridgedSuperTokenProxy deployment + initialization in one transaction.
contract ArbBridgedSuperTokenFactory {
ArbBridgedSuperTokenProxy public proxy;
constructor(
address nativeBridge,
address remoteToken,
address superTokenFactoryAddr,
string memory name,
string memory symbol,
address owner,
uint256 initialSupply
) {
proxy = new ArbBridgedSuperTokenProxy(nativeBridge, remoteToken);
proxy.initialize(
ISuperTokenFactory(superTokenFactoryAddr),
name,
symbol,
owner,
initialSupply
);
proxy.transferOwnership(owner);
}
}
/// deploys and initializes an instance of ArbBridgedSuperTokenProxy
contract DeployArbToken is DeployBase {
function run() external {
_loadEnv();
_startBroadcast();
address nativeBridge = vm.envAddress("NATIVE_BRIDGE");
address remoteToken = vm.envAddress("REMOTE_TOKEN");
ArbBridgedSuperTokenFactory factory = new ArbBridgedSuperTokenFactory(
nativeBridge,
remoteToken,
superTokenFactoryAddr,
name,
symbol,
owner,
initialSupply
);
console.log("ArbBridgedSuperTokenProxy deployed at", address(factory.proxy()));
vm.stopBroadcast();
_verifyDeployment(address(factory.proxy()));
}
}
/// Factory for atomic proxy deployment + initialization in one transaction.
contract PureSuperTokenFactory {
PureSuperTokenProxy public proxy;
constructor(
address superTokenFactoryAddr,
string memory name,
string memory symbol,
address owner,
uint256 initialSupply
) {
proxy = new PureSuperTokenProxy();
PureSuperTokenProxy(proxy).initialize(
ISuperTokenFactory(superTokenFactoryAddr),
name,
symbol,
owner,
initialSupply
);
}
}
/// deploys and initializes an instance of PureSuperTokenProxy
contract DeployPureSuperToken is DeployBase {
function run() external {
_loadEnv();
_startBroadcast();
// log params
console.log("Deploying PureSuperToken with params:");
console.log(" name:", name);
console.log(" symbol:", symbol);
console.log(" initialSupply:", initialSupply);
console.log(" receiver:", owner);
// PureSuperTokenProxy proxy = new PureSuperTokenProxy();
// proxy.initialize(ISuperTokenFactory(superTokenFactoryAddr), name, symbol, owner, initialSupply);
PureSuperTokenFactory factory = new PureSuperTokenFactory(
superTokenFactoryAddr,
name,
symbol,
owner,
initialSupply
);
console.log("PureSuperTokenProxy deployed at", address(factory.proxy()));
vm.stopBroadcast();
_verifyDeployment(address(factory.proxy()));
}
}
/// Factory for atomic CustomERC20WrapperProxy deployment + initialization in one transaction.
contract CustomERC20WrapperFactory {
CustomERC20WrapperProxy public proxy;
constructor(
address underlyingTokenAddr,
address superTokenFactoryAddr,
string memory name,
string memory symbol
) {
proxy = new CustomERC20WrapperProxy();
proxy.initialize(
IERC20Metadata(underlyingTokenAddr),
ISuperTokenFactory(superTokenFactoryAddr),
name,
symbol
);
}
}
/// deploys and initializes an instance of CustomERC20WrapperProxy
contract DeployCustomERC20Wrapper is DeployBase {
function run() external {
_loadEnv();
address underlyingTokenAddr = vm.envAddress("UNDERLYING_TOKEN");
_startBroadcast();
// log params
console.log("Deploying CustomERC20Wrapper with params:");
console.log(" name:", name);
console.log(" symbol:", symbol);
console.log(" underlyingToken:", underlyingTokenAddr);
CustomERC20WrapperFactory factory = new CustomERC20WrapperFactory(
underlyingTokenAddr,
superTokenFactoryAddr,
name,
symbol
);
console.log("CustomERC20WrapperProxy deployed at", address(factory.proxy()));
vm.stopBroadcast();
_verifyDeployment(address(factory.proxy()));
}
}