@zoralabs/coins 1.1.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +107 -110
- package/CHANGELOG.md +50 -0
- package/README.md +48 -1
- package/abis/BaseCoin.json +442 -0
- package/abis/BaseZoraV4CoinHook.json +6 -2
- package/abis/CoinTest.json +3 -246
- package/abis/CoinUniV4Test.json +20 -0
- package/abis/ContentCoinHook.json +6 -2
- package/abis/CreatorCoinHook.json +6 -2
- package/abis/FactoryTest.json +8 -133
- package/abis/FeeEstimatorHook.json +6 -2
- package/abis/HooksTest.json +0 -26
- package/abis/ICoin.json +378 -0
- package/abis/ICoinV3.json +378 -0
- package/abis/IZoraFactory.json +0 -18
- package/abis/IZoraV4CoinHook.json +2 -2
- package/abis/LiquidityMigrationTest.json +101 -0
- package/abis/MockBadFactory.json +15 -0
- package/abis/Ownable2StepUpgradeable.json +138 -0
- package/abis/ZoraFactoryImpl.json +38 -65
- package/addresses/8453.json +5 -5
- package/dist/index.cjs +272 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +270 -266
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +397 -470
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/package/wagmiGenerated.ts +275 -271
- package/package.json +3 -3
- package/script/DeployPostDeploymentHooks.s.sol +2 -2
- package/script/TestBackingCoinSwap.s.sol +9 -9
- package/script/TestV4Swap.s.sol +9 -9
- package/script/UpgradeFactoryImpl.s.sol +0 -1
- package/src/BaseCoin.sol +109 -6
- package/src/ContentCoin.sol +45 -0
- package/src/CreatorCoin.sol +7 -5
- package/src/ZoraFactoryImpl.sol +12 -95
- package/src/deployment/CoinsDeployerBase.sol +13 -30
- package/src/hooks/BaseZoraV4CoinHook.sol +8 -6
- package/src/hooks/deployment/BuySupplyWithSwapRouterHook.sol +4 -5
- package/src/interfaces/ICoin.sol +67 -1
- package/src/interfaces/ICreatorCoin.sol +2 -2
- package/src/interfaces/IZoraFactory.sol +0 -5
- package/src/interfaces/IZoraV4CoinHook.sol +1 -1
- package/src/libs/CoinConfigurationVersions.sol +1 -39
- package/src/libs/CoinRewardsV4.sol +2 -2
- package/src/libs/CoinSetup.sol +1 -4
- package/src/libs/UniV4SwapHelper.sol +1 -1
- package/src/libs/UniV4SwapToCurrency.sol +2 -2
- package/src/libs/V4Liquidity.sol +1 -1
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/Coin.t.sol +112 -535
- package/test/CoinUniV4.t.sol +66 -10
- package/test/DeploymentHooks.t.sol +5 -102
- package/test/Factory.t.sol +49 -291
- package/test/LiquidityMigration.t.sol +160 -2
- package/test/MultiOwnable.t.sol +36 -36
- package/test/Upgrades.t.sol +23 -42
- package/test/utils/BaseTest.sol +39 -84
- package/test/utils/FeeEstimatorHook.sol +3 -3
- package/wagmi.config.ts +2 -2
- package/abis/Coin.json +0 -1912
- package/abis/DopplerUniswapV3Test.json +0 -800
- package/abis/ICoinV4.json +0 -1048
- package/abis/Simulate.json +0 -29
- package/abis/UniV3BuySell.json +0 -12
- package/abis/UniV3Errors.json +0 -32
- package/script/Simulate.s.sol +0 -59
- package/src/Coin.sol +0 -236
- package/src/CoinV4.sol +0 -151
- package/src/interfaces/ICoinV4.sol +0 -74
- package/src/libs/CoinDopplerUniV3.sol +0 -50
- package/src/libs/CoinRewards.sol +0 -201
- package/src/libs/CoinSetupV3.sol +0 -50
- package/src/libs/UniV3BuySell.sol +0 -231
- package/src/libs/UniV3Errors.sol +0 -11
- package/test/CoinDopplerUniV3.t.sol +0 -310
- /package/abis/{CoinV4.json → ContentCoin.json} +0 -0
|
@@ -13,9 +13,11 @@ import {LpPosition} from "../src/types/LpPosition.sol";
|
|
|
13
13
|
import {V4Liquidity} from "../src/libs/V4Liquidity.sol";
|
|
14
14
|
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
15
15
|
import {IZoraV4CoinHook} from "../src/interfaces/IZoraV4CoinHook.sol";
|
|
16
|
-
import {
|
|
16
|
+
import {ICoin} from "../src/interfaces/ICoin.sol";
|
|
17
17
|
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
|
|
18
18
|
import {CoinCommon} from "../src/libs/CoinCommon.sol";
|
|
19
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
20
|
+
import {IHooksUpgradeGate} from "../src/interfaces/IHooksUpgradeGate.sol";
|
|
19
21
|
|
|
20
22
|
contract LiquidityMigrationReceiver is IUpgradeableDestinationV4Hook, IERC165 {
|
|
21
23
|
function initializeFromMigration(
|
|
@@ -175,7 +177,7 @@ contract LiquidityMigrationTest is BaseTest {
|
|
|
175
177
|
// migrate the liquidity
|
|
176
178
|
vm.prank(users.creator);
|
|
177
179
|
vm.expectEmit(true, true, true, true);
|
|
178
|
-
emit
|
|
180
|
+
emit ICoin.LiquidityMigrated(poolKey, fromPoolKeyHash, newPoolKey, toPoolKeyHash);
|
|
179
181
|
coinV4.migrateLiquidity(address(newHook), "");
|
|
180
182
|
}
|
|
181
183
|
|
|
@@ -230,4 +232,160 @@ contract LiquidityMigrationTest is BaseTest {
|
|
|
230
232
|
vm.expectRevert(abi.encodeWithSelector(IZoraV4CoinHook.OnlyCoin.selector, users.creator, address(coinV4)));
|
|
231
233
|
IUpgradeableV4Hook(originalHook).migrateLiquidity(address(newHook), poolKey, "");
|
|
232
234
|
}
|
|
235
|
+
|
|
236
|
+
// Hook Upgrade Gate Tests
|
|
237
|
+
function test_hookUpgradeGate_removeUpgradePath() public {
|
|
238
|
+
address baseImpl = makeAddr("baseImpl");
|
|
239
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
240
|
+
|
|
241
|
+
// First register the upgrade path
|
|
242
|
+
address[] memory baseImpls = new address[](1);
|
|
243
|
+
baseImpls[0] = baseImpl;
|
|
244
|
+
|
|
245
|
+
vm.prank(hookUpgradeGate.owner());
|
|
246
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
247
|
+
|
|
248
|
+
// Verify it's registered
|
|
249
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(baseImpl, upgradeImpl));
|
|
250
|
+
|
|
251
|
+
// Remove the upgrade path
|
|
252
|
+
vm.prank(hookUpgradeGate.owner());
|
|
253
|
+
vm.expectEmit(true, true, false, false);
|
|
254
|
+
emit IHooksUpgradeGate.UpgradeRemoved(baseImpl, upgradeImpl);
|
|
255
|
+
hookUpgradeGate.removeUpgradePath(baseImpl, upgradeImpl);
|
|
256
|
+
|
|
257
|
+
// Verify it's removed
|
|
258
|
+
assertFalse(hookUpgradeGate.isRegisteredUpgradePath(baseImpl, upgradeImpl));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function test_hookUpgradeGate_removeUpgradePath_onlyOwner() public {
|
|
262
|
+
address baseImpl = makeAddr("baseImpl");
|
|
263
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
264
|
+
address nonOwner = makeAddr("nonOwner");
|
|
265
|
+
|
|
266
|
+
// Try to remove upgrade path as non-owner
|
|
267
|
+
vm.prank(nonOwner);
|
|
268
|
+
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, nonOwner));
|
|
269
|
+
hookUpgradeGate.removeUpgradePath(baseImpl, upgradeImpl);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function test_hookUpgradeGate_registerUpgradePath_onlyOwner() public {
|
|
273
|
+
address baseImpl = makeAddr("baseImpl");
|
|
274
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
275
|
+
address nonOwner = makeAddr("nonOwner");
|
|
276
|
+
|
|
277
|
+
address[] memory baseImpls = new address[](1);
|
|
278
|
+
baseImpls[0] = baseImpl;
|
|
279
|
+
|
|
280
|
+
// Try to register upgrade path as non-owner
|
|
281
|
+
vm.prank(nonOwner);
|
|
282
|
+
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, nonOwner));
|
|
283
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function test_hookUpgradeGate_registerMultipleUpgradePaths() public {
|
|
287
|
+
address baseImpl1 = makeAddr("baseImpl1");
|
|
288
|
+
address baseImpl2 = makeAddr("baseImpl2");
|
|
289
|
+
address baseImpl3 = makeAddr("baseImpl3");
|
|
290
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
291
|
+
|
|
292
|
+
address[] memory baseImpls = new address[](3);
|
|
293
|
+
baseImpls[0] = baseImpl1;
|
|
294
|
+
baseImpls[1] = baseImpl2;
|
|
295
|
+
baseImpls[2] = baseImpl3;
|
|
296
|
+
|
|
297
|
+
// Register multiple upgrade paths at once
|
|
298
|
+
vm.prank(hookUpgradeGate.owner());
|
|
299
|
+
vm.expectEmit(true, true, false, false);
|
|
300
|
+
emit IHooksUpgradeGate.UpgradeRegistered(baseImpl1, upgradeImpl);
|
|
301
|
+
vm.expectEmit(true, true, false, false);
|
|
302
|
+
emit IHooksUpgradeGate.UpgradeRegistered(baseImpl2, upgradeImpl);
|
|
303
|
+
vm.expectEmit(true, true, false, false);
|
|
304
|
+
emit IHooksUpgradeGate.UpgradeRegistered(baseImpl3, upgradeImpl);
|
|
305
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
306
|
+
|
|
307
|
+
// Verify all paths are registered
|
|
308
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(baseImpl1, upgradeImpl));
|
|
309
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(baseImpl2, upgradeImpl));
|
|
310
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(baseImpl3, upgradeImpl));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function test_hookUpgradeGate_registerEmptyArray() public {
|
|
314
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
315
|
+
address[] memory baseImpls = new address[](0);
|
|
316
|
+
|
|
317
|
+
// Register with empty array - should succeed but do nothing
|
|
318
|
+
vm.prank(hookUpgradeGate.owner());
|
|
319
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
320
|
+
|
|
321
|
+
// No events should be emitted, no state changes
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function test_hookUpgradeGate_removeNonexistentUpgradePath() public {
|
|
325
|
+
address baseImpl = makeAddr("baseImpl");
|
|
326
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
327
|
+
|
|
328
|
+
// Try to remove a path that was never registered
|
|
329
|
+
vm.prank(hookUpgradeGate.owner());
|
|
330
|
+
vm.expectEmit(true, true, false, false);
|
|
331
|
+
emit IHooksUpgradeGate.UpgradeRemoved(baseImpl, upgradeImpl);
|
|
332
|
+
hookUpgradeGate.removeUpgradePath(baseImpl, upgradeImpl);
|
|
333
|
+
|
|
334
|
+
// Should still be false (was already false)
|
|
335
|
+
assertFalse(hookUpgradeGate.isRegisteredUpgradePath(baseImpl, upgradeImpl));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function test_hookUpgradeGate_registerSamePathTwice() public {
|
|
339
|
+
address baseImpl = makeAddr("baseImpl");
|
|
340
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
341
|
+
|
|
342
|
+
address[] memory baseImpls = new address[](1);
|
|
343
|
+
baseImpls[0] = baseImpl;
|
|
344
|
+
|
|
345
|
+
// Register once
|
|
346
|
+
vm.prank(hookUpgradeGate.owner());
|
|
347
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
348
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(baseImpl, upgradeImpl));
|
|
349
|
+
|
|
350
|
+
// Register again - should succeed and overwrite (true -> true)
|
|
351
|
+
vm.prank(hookUpgradeGate.owner());
|
|
352
|
+
vm.expectEmit(true, true, false, false);
|
|
353
|
+
emit IHooksUpgradeGate.UpgradeRegistered(baseImpl, upgradeImpl);
|
|
354
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
355
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(baseImpl, upgradeImpl));
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function test_hookUpgradeGate_zeroAddressHandling() public {
|
|
359
|
+
address[] memory baseImpls = new address[](2);
|
|
360
|
+
baseImpls[0] = address(0);
|
|
361
|
+
baseImpls[1] = makeAddr("baseImpl");
|
|
362
|
+
address upgradeImpl = address(0);
|
|
363
|
+
|
|
364
|
+
// Should allow zero addresses (no validation in contract)
|
|
365
|
+
vm.prank(hookUpgradeGate.owner());
|
|
366
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
367
|
+
|
|
368
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(address(0), address(0)));
|
|
369
|
+
assertTrue(hookUpgradeGate.isRegisteredUpgradePath(makeAddr("baseImpl"), address(0)));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function test_hookUpgradeGate_isAllowedHookUpgradeMapping() public {
|
|
373
|
+
address baseImpl = makeAddr("baseImpl");
|
|
374
|
+
address upgradeImpl = makeAddr("upgradeImpl");
|
|
375
|
+
|
|
376
|
+
// Test direct mapping access
|
|
377
|
+
assertFalse(hookUpgradeGate.isAllowedHookUpgrade(baseImpl, upgradeImpl));
|
|
378
|
+
|
|
379
|
+
// Register upgrade path
|
|
380
|
+
address[] memory baseImpls = new address[](1);
|
|
381
|
+
baseImpls[0] = baseImpl;
|
|
382
|
+
vm.prank(hookUpgradeGate.owner());
|
|
383
|
+
hookUpgradeGate.registerUpgradePath(baseImpls, upgradeImpl);
|
|
384
|
+
|
|
385
|
+
// Test direct mapping access
|
|
386
|
+
assertTrue(hookUpgradeGate.isAllowedHookUpgrade(baseImpl, upgradeImpl));
|
|
387
|
+
|
|
388
|
+
// Should match isRegisteredUpgradePath
|
|
389
|
+
assertEq(hookUpgradeGate.isAllowedHookUpgrade(baseImpl, upgradeImpl), hookUpgradeGate.isRegisteredUpgradePath(baseImpl, upgradeImpl));
|
|
390
|
+
}
|
|
233
391
|
}
|
package/test/MultiOwnable.t.sol
CHANGED
|
@@ -7,13 +7,13 @@ contract MultiOwnableTest is BaseTest {
|
|
|
7
7
|
function setUp() public override {
|
|
8
8
|
super.setUp();
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
_deployV4Coin();
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function test_initial_owners() public view {
|
|
14
|
-
assertEq(
|
|
15
|
-
assertEq(
|
|
16
|
-
assertEq(
|
|
14
|
+
assertEq(coinV4.owners().length, 1);
|
|
15
|
+
assertEq(coinV4.owners()[0], users.creator);
|
|
16
|
+
assertEq(coinV4.isOwner(users.creator), true);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function test_add_owners() public {
|
|
@@ -22,21 +22,21 @@ contract MultiOwnableTest is BaseTest {
|
|
|
22
22
|
newOwners[1] = makeAddr("NewOwner2");
|
|
23
23
|
|
|
24
24
|
vm.prank(users.creator);
|
|
25
|
-
|
|
25
|
+
coinV4.addOwners(newOwners);
|
|
26
26
|
|
|
27
|
-
assertEq(
|
|
28
|
-
assertEq(
|
|
29
|
-
assertEq(
|
|
30
|
-
assertEq(
|
|
27
|
+
assertEq(coinV4.owners().length, 3);
|
|
28
|
+
assertEq(coinV4.isOwner(users.creator), true);
|
|
29
|
+
assertEq(coinV4.isOwner(newOwners[0]), true);
|
|
30
|
+
assertEq(coinV4.isOwner(newOwners[1]), true);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function test_add_owner() public {
|
|
34
34
|
vm.prank(users.creator);
|
|
35
|
-
|
|
35
|
+
coinV4.addOwner(address(this));
|
|
36
36
|
|
|
37
|
-
assertEq(
|
|
38
|
-
assertEq(
|
|
39
|
-
assertEq(
|
|
37
|
+
assertEq(coinV4.owners().length, 2);
|
|
38
|
+
assertEq(coinV4.isOwner(users.creator), true);
|
|
39
|
+
assertEq(coinV4.isOwner(address(this)), true);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function test_remove_owners() public {
|
|
@@ -45,67 +45,67 @@ contract MultiOwnableTest is BaseTest {
|
|
|
45
45
|
newOwners[1] = makeAddr("NewOwner2");
|
|
46
46
|
|
|
47
47
|
vm.prank(users.creator);
|
|
48
|
-
|
|
48
|
+
coinV4.addOwners(newOwners);
|
|
49
49
|
|
|
50
50
|
vm.prank(users.creator);
|
|
51
|
-
|
|
51
|
+
coinV4.removeOwners(newOwners);
|
|
52
52
|
|
|
53
|
-
assertEq(
|
|
54
|
-
assertEq(
|
|
55
|
-
assertEq(
|
|
56
|
-
assertEq(
|
|
53
|
+
assertEq(coinV4.owners().length, 1);
|
|
54
|
+
assertEq(coinV4.isOwner(users.creator), true);
|
|
55
|
+
assertEq(coinV4.isOwner(newOwners[0]), false);
|
|
56
|
+
assertEq(coinV4.isOwner(newOwners[1]), false);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function test_remove_owner() public {
|
|
60
60
|
vm.prank(users.creator);
|
|
61
|
-
|
|
61
|
+
coinV4.addOwner(address(this));
|
|
62
62
|
|
|
63
63
|
vm.prank(address(this));
|
|
64
|
-
|
|
64
|
+
coinV4.removeOwner(users.creator);
|
|
65
65
|
|
|
66
|
-
assertEq(
|
|
67
|
-
assertEq(
|
|
68
|
-
assertEq(
|
|
66
|
+
assertEq(coinV4.owners().length, 1);
|
|
67
|
+
assertEq(coinV4.isOwner(users.creator), false);
|
|
68
|
+
assertEq(coinV4.isOwner(address(this)), true);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function test_revert_only_owner_can_add() public {
|
|
72
72
|
vm.expectRevert(abi.encodeWithSelector(MultiOwnable.OnlyOwner.selector));
|
|
73
|
-
|
|
73
|
+
coinV4.addOwner(address(this));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
function test_revert_only_owner_can_remove() public {
|
|
77
77
|
vm.expectRevert(abi.encodeWithSelector(MultiOwnable.OnlyOwner.selector));
|
|
78
78
|
|
|
79
79
|
vm.prank(address(this));
|
|
80
|
-
|
|
80
|
+
coinV4.removeOwner(users.creator);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
function test_revert_cannot_remove_not_owner() public {
|
|
84
84
|
vm.expectRevert(abi.encodeWithSelector(MultiOwnable.NotOwner.selector));
|
|
85
85
|
vm.prank(users.creator);
|
|
86
|
-
|
|
86
|
+
coinV4.removeOwner(address(this));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
function test_revert_last_owner_must_revoke() public {
|
|
90
90
|
address newOwner = makeAddr("NewOwner1");
|
|
91
91
|
|
|
92
92
|
vm.prank(users.creator);
|
|
93
|
-
|
|
93
|
+
coinV4.addOwner(newOwner);
|
|
94
94
|
|
|
95
95
|
vm.prank(newOwner);
|
|
96
|
-
|
|
96
|
+
coinV4.removeOwner(users.creator);
|
|
97
97
|
|
|
98
98
|
vm.prank(newOwner);
|
|
99
99
|
vm.expectRevert(abi.encodeWithSelector(MultiOwnable.UseRevokeOwnershipToRemoveSelf.selector));
|
|
100
|
-
|
|
100
|
+
coinV4.removeOwner(newOwner);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
function test_revoke_ownership() public {
|
|
104
104
|
vm.prank(users.creator);
|
|
105
|
-
|
|
105
|
+
coinV4.revokeOwnership();
|
|
106
106
|
|
|
107
|
-
assertEq(
|
|
108
|
-
assertEq(
|
|
107
|
+
assertEq(coinV4.owners().length, 0);
|
|
108
|
+
assertEq(coinV4.isOwner(users.creator), false);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
function test_revert_add_owners_with_zero_address() public {
|
|
@@ -116,7 +116,7 @@ contract MultiOwnableTest is BaseTest {
|
|
|
116
116
|
|
|
117
117
|
vm.prank(users.creator);
|
|
118
118
|
vm.expectRevert(MultiOwnable.OwnerCannotBeAddressZero.selector);
|
|
119
|
-
|
|
119
|
+
coinV4.addOwners(newOwners);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
function test_revert_add_owners_with_duplicate() public {
|
|
@@ -126,11 +126,11 @@ contract MultiOwnableTest is BaseTest {
|
|
|
126
126
|
newOwners[1] = newOwner;
|
|
127
127
|
|
|
128
128
|
vm.prank(users.creator);
|
|
129
|
-
|
|
129
|
+
coinV4.addOwner(newOwner);
|
|
130
130
|
|
|
131
131
|
vm.expectRevert(MultiOwnable.AlreadyOwner.selector);
|
|
132
132
|
vm.prank(users.creator);
|
|
133
|
-
|
|
133
|
+
coinV4.addOwners(newOwners);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
function test_revert_init_with_zero_owners() public {
|
package/test/Upgrades.t.sol
CHANGED
|
@@ -6,7 +6,7 @@ import {ZoraFactoryImpl} from "../src/ZoraFactoryImpl.sol";
|
|
|
6
6
|
import {BaseTest} from "./utils/BaseTest.sol";
|
|
7
7
|
import {CoinsDeployerBase} from "../src/deployment/CoinsDeployerBase.sol";
|
|
8
8
|
import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
|
|
9
|
-
import {
|
|
9
|
+
import {ICoin} from "../src/interfaces/ICoin.sol";
|
|
10
10
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
11
11
|
import {ISwapRouter} from "../src/interfaces/ISwapRouter.sol";
|
|
12
12
|
import {IWETH} from "../src/interfaces/IWETH.sol";
|
|
@@ -21,7 +21,7 @@ import {HooksDeployment} from "../src/libs/HooksDeployment.sol";
|
|
|
21
21
|
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
|
22
22
|
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
23
23
|
import {MultiOwnable} from "../src/utils/MultiOwnable.sol";
|
|
24
|
-
import {
|
|
24
|
+
import {ContentCoin} from "../src/ContentCoin.sol";
|
|
25
25
|
import {UniV4SwapHelper} from "../src/libs/UniV4SwapHelper.sol";
|
|
26
26
|
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
|
|
27
27
|
import {IZoraV4CoinHook} from "../src/interfaces/IZoraV4CoinHook.sol";
|
|
@@ -43,13 +43,7 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
43
43
|
|
|
44
44
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
45
45
|
|
|
46
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
47
|
-
factoryProxy.coinImpl(),
|
|
48
|
-
address(coinV4Impl),
|
|
49
|
-
address(creatorCoinImpl),
|
|
50
|
-
address(contentCoinHook),
|
|
51
|
-
address(creatorCoinHook)
|
|
52
|
-
);
|
|
46
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(coinV4Impl), address(creatorCoinImpl), address(contentCoinHook), address(creatorCoinHook));
|
|
53
47
|
|
|
54
48
|
vm.prank(factoryProxy.owner());
|
|
55
49
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
@@ -64,13 +58,7 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
64
58
|
|
|
65
59
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
66
60
|
|
|
67
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
68
|
-
factoryProxy.coinImpl(),
|
|
69
|
-
address(coinV4Impl),
|
|
70
|
-
address(creatorCoinImpl),
|
|
71
|
-
address(contentCoinHook),
|
|
72
|
-
address(creatorCoinHook)
|
|
73
|
-
);
|
|
61
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(coinV4Impl), address(creatorCoinImpl), address(contentCoinHook), address(creatorCoinHook));
|
|
74
62
|
|
|
75
63
|
vm.prank(factoryProxy.owner());
|
|
76
64
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
@@ -88,19 +76,12 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
88
76
|
|
|
89
77
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
90
78
|
|
|
91
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
92
|
-
factoryProxy.coinImpl(),
|
|
93
|
-
address(coinV4Impl),
|
|
94
|
-
address(creatorCoinImpl),
|
|
95
|
-
address(contentCoinHook),
|
|
96
|
-
address(creatorCoinHook)
|
|
97
|
-
);
|
|
79
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(address(coinV4Impl), address(creatorCoinImpl), address(contentCoinHook), address(creatorCoinHook));
|
|
98
80
|
|
|
99
81
|
vm.prank(factoryProxy.owner());
|
|
100
82
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
101
83
|
|
|
102
84
|
ZoraFactoryImpl newImpl2 = new ZoraFactoryImpl(
|
|
103
|
-
factoryProxy.coinImpl(),
|
|
104
85
|
factoryProxy.coinV4Impl(),
|
|
105
86
|
factoryProxy.creatorCoinImpl(),
|
|
106
87
|
address(contentCoinHook),
|
|
@@ -166,16 +147,16 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
166
147
|
);
|
|
167
148
|
|
|
168
149
|
// do some swaps to test out
|
|
169
|
-
_swapSomeCurrencyForCoin(
|
|
150
|
+
_swapSomeCurrencyForCoin(ICoin(coinAddress), ZORA, uint128(IERC20(ZORA).balanceOf(trader)), trader);
|
|
170
151
|
|
|
171
152
|
// do some swaps to test out
|
|
172
|
-
_swapSomeCoinForCurrency(
|
|
153
|
+
_swapSomeCoinForCurrency(ICoin(coinAddress), ZORA, uint128(IERC20(coinAddress).balanceOf(trader)), trader);
|
|
173
154
|
}
|
|
174
155
|
|
|
175
156
|
address coinVersionLookup = 0x777777751622c0d3258f214F9DF38E35BF45baF3;
|
|
176
157
|
address upgradeGate = 0xD88f6BdD765313CaFA5888C177c325E2C3AbF2D2;
|
|
177
158
|
|
|
178
|
-
function _swapSomeCurrencyForCoinAndExpectRevert(
|
|
159
|
+
function _swapSomeCurrencyForCoinAndExpectRevert(ICoin _coin, address currency, uint128 amountIn, address trader) internal {
|
|
179
160
|
uint128 minAmountOut = uint128(0);
|
|
180
161
|
|
|
181
162
|
(bytes memory commands, bytes[] memory inputs) = UniV4SwapHelper.buildExactInputSingleSwapCommand(
|
|
@@ -205,42 +186,42 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
205
186
|
|
|
206
187
|
address contentCoin = 0x4E93A01c90f812284F71291a8d1415a904957156;
|
|
207
188
|
|
|
208
|
-
address creatorCoin =
|
|
189
|
+
address creatorCoin = ICoin(contentCoin).currency();
|
|
209
190
|
|
|
210
191
|
uint256 amountIn = IERC20(creatorCoin).balanceOf(trader);
|
|
211
192
|
|
|
212
193
|
require(amountIn > 0, "no balance");
|
|
213
194
|
|
|
214
195
|
// this swap should revert because the content coin is broken
|
|
215
|
-
_swapSomeCurrencyForCoinAndExpectRevert(
|
|
196
|
+
_swapSomeCurrencyForCoinAndExpectRevert(ICoin(contentCoin), creatorCoin, uint128(amountIn), trader);
|
|
216
197
|
|
|
217
198
|
bytes memory creationCode = HooksDeployment.contentCoinCreationCode(address(poolManager), coinVersionLookup, new address[](0), upgradeGate);
|
|
218
199
|
|
|
219
200
|
(IHooks newHook, ) = HooksDeployment.deployHookWithExistingOrNewSalt(address(this), creationCode, bytes32(0));
|
|
220
201
|
|
|
221
202
|
// etch new hook into the content coin, it shouldn't revert anymore when swapping
|
|
222
|
-
vm.etch(address(
|
|
203
|
+
vm.etch(address(ICoin(contentCoin).hooks()), address(newHook).code);
|
|
223
204
|
|
|
224
|
-
_swapSomeCurrencyForCoin(
|
|
205
|
+
_swapSomeCurrencyForCoin(ICoin(contentCoin), creatorCoin, uint128(amountIn), trader);
|
|
225
206
|
}
|
|
226
207
|
|
|
227
208
|
function test_canUpgradeBrokenContentCoinAndSwap() public {
|
|
228
|
-
vm.createSelectFork("base",
|
|
209
|
+
vm.createSelectFork("base", 32613149);
|
|
229
210
|
|
|
230
211
|
address trader = 0xf69fEc6d858c77e969509843852178bd24CAd2B6;
|
|
231
212
|
|
|
232
|
-
address contentCoin =
|
|
213
|
+
address contentCoin = 0xB9799C839818bF50240CE683363D00c43a2E23b8;
|
|
233
214
|
|
|
234
|
-
address creatorCoin =
|
|
215
|
+
address creatorCoin = ICoin(contentCoin).currency();
|
|
235
216
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
uint256 amountIn = IERC20(creatorCoin).balanceOf(trader);
|
|
217
|
+
uint256 amountIn = 0.000111 ether;
|
|
239
218
|
|
|
240
219
|
bytes memory creationCode = HooksDeployment.contentCoinCreationCode(address(poolManager), coinVersionLookup, new address[](0), upgradeGate);
|
|
241
220
|
|
|
242
221
|
(IHooks newHook, ) = HooksDeployment.deployHookWithExistingOrNewSalt(address(this), creationCode, bytes32(0));
|
|
243
222
|
|
|
223
|
+
address existingHook = address(ICoin(contentCoin).hooks());
|
|
224
|
+
|
|
244
225
|
address[] memory baseImpls = new address[](1);
|
|
245
226
|
baseImpls[0] = existingHook;
|
|
246
227
|
|
|
@@ -248,10 +229,10 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
248
229
|
IHooksUpgradeGate(upgradeGate).registerUpgradePath(baseImpls, address(newHook));
|
|
249
230
|
|
|
250
231
|
vm.prank(MultiOwnable(contentCoin).owners()[0]);
|
|
251
|
-
|
|
232
|
+
ContentCoin(contentCoin).migrateLiquidity(address(newHook), "");
|
|
252
233
|
|
|
253
234
|
// do some swaps to test out
|
|
254
|
-
_swapSomeCurrencyForCoin(
|
|
235
|
+
_swapSomeCurrencyForCoin(ICoin(contentCoin), creatorCoin, uint128(amountIn), trader);
|
|
255
236
|
}
|
|
256
237
|
|
|
257
238
|
function getPositionInfo(
|
|
@@ -272,7 +253,7 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
272
253
|
}
|
|
273
254
|
}
|
|
274
255
|
|
|
275
|
-
function getLiquidityForPoolCoin(
|
|
256
|
+
function getLiquidityForPoolCoin(ICoin coin) internal view returns (uint128[] memory liquidityForPositions) {
|
|
276
257
|
return getLiquidityForPositions(coin.getPoolKey(), IZoraV4CoinHook(address(coin.hooks())).getPoolCoin(coin.getPoolKey()).positions);
|
|
277
258
|
}
|
|
278
259
|
|
|
@@ -281,7 +262,7 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
281
262
|
|
|
282
263
|
address trader = 0xf69fEc6d858c77e969509843852178bd24CAd2B6;
|
|
283
264
|
|
|
284
|
-
|
|
265
|
+
ICoin creatorCoin = ICoin(0x2F03aB8fD97F5874bc3274C296Bb954Ae92EdA34);
|
|
285
266
|
|
|
286
267
|
address zora = creatorCoin.currency();
|
|
287
268
|
|
|
@@ -305,7 +286,7 @@ contract UpgradesTest is BaseTest, CoinsDeployerBase {
|
|
|
305
286
|
uint160 beforePrice = PoolStateReader.getSqrtPriceX96(creatorCoin.getPoolKey(), poolManager);
|
|
306
287
|
|
|
307
288
|
vm.prank(MultiOwnable(address(creatorCoin)).owners()[0]);
|
|
308
|
-
|
|
289
|
+
ContentCoin(address(creatorCoin)).migrateLiquidity(address(newHook), "");
|
|
309
290
|
|
|
310
291
|
// get liquidity of original positions after migration
|
|
311
292
|
uint128[] memory liquidityOfPositionsAfterMigration = getLiquidityForPositions(beforeKey, beforePositions);
|