@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.
Files changed (78) hide show
  1. package/.turbo/turbo-build.log +107 -110
  2. package/CHANGELOG.md +50 -0
  3. package/README.md +48 -1
  4. package/abis/BaseCoin.json +442 -0
  5. package/abis/BaseZoraV4CoinHook.json +6 -2
  6. package/abis/CoinTest.json +3 -246
  7. package/abis/CoinUniV4Test.json +20 -0
  8. package/abis/ContentCoinHook.json +6 -2
  9. package/abis/CreatorCoinHook.json +6 -2
  10. package/abis/FactoryTest.json +8 -133
  11. package/abis/FeeEstimatorHook.json +6 -2
  12. package/abis/HooksTest.json +0 -26
  13. package/abis/ICoin.json +378 -0
  14. package/abis/ICoinV3.json +378 -0
  15. package/abis/IZoraFactory.json +0 -18
  16. package/abis/IZoraV4CoinHook.json +2 -2
  17. package/abis/LiquidityMigrationTest.json +101 -0
  18. package/abis/MockBadFactory.json +15 -0
  19. package/abis/Ownable2StepUpgradeable.json +138 -0
  20. package/abis/ZoraFactoryImpl.json +38 -65
  21. package/addresses/8453.json +5 -5
  22. package/dist/index.cjs +272 -268
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.js +270 -266
  25. package/dist/index.js.map +1 -1
  26. package/dist/wagmiGenerated.d.ts +397 -470
  27. package/dist/wagmiGenerated.d.ts.map +1 -1
  28. package/package/wagmiGenerated.ts +275 -271
  29. package/package.json +3 -3
  30. package/script/DeployPostDeploymentHooks.s.sol +2 -2
  31. package/script/TestBackingCoinSwap.s.sol +9 -9
  32. package/script/TestV4Swap.s.sol +9 -9
  33. package/script/UpgradeFactoryImpl.s.sol +0 -1
  34. package/src/BaseCoin.sol +109 -6
  35. package/src/ContentCoin.sol +45 -0
  36. package/src/CreatorCoin.sol +7 -5
  37. package/src/ZoraFactoryImpl.sol +12 -95
  38. package/src/deployment/CoinsDeployerBase.sol +13 -30
  39. package/src/hooks/BaseZoraV4CoinHook.sol +8 -6
  40. package/src/hooks/deployment/BuySupplyWithSwapRouterHook.sol +4 -5
  41. package/src/interfaces/ICoin.sol +67 -1
  42. package/src/interfaces/ICreatorCoin.sol +2 -2
  43. package/src/interfaces/IZoraFactory.sol +0 -5
  44. package/src/interfaces/IZoraV4CoinHook.sol +1 -1
  45. package/src/libs/CoinConfigurationVersions.sol +1 -39
  46. package/src/libs/CoinRewardsV4.sol +2 -2
  47. package/src/libs/CoinSetup.sol +1 -4
  48. package/src/libs/UniV4SwapHelper.sol +1 -1
  49. package/src/libs/UniV4SwapToCurrency.sol +2 -2
  50. package/src/libs/V4Liquidity.sol +1 -1
  51. package/src/version/ContractVersionBase.sol +1 -1
  52. package/test/Coin.t.sol +112 -535
  53. package/test/CoinUniV4.t.sol +66 -10
  54. package/test/DeploymentHooks.t.sol +5 -102
  55. package/test/Factory.t.sol +49 -291
  56. package/test/LiquidityMigration.t.sol +160 -2
  57. package/test/MultiOwnable.t.sol +36 -36
  58. package/test/Upgrades.t.sol +23 -42
  59. package/test/utils/BaseTest.sol +39 -84
  60. package/test/utils/FeeEstimatorHook.sol +3 -3
  61. package/wagmi.config.ts +2 -2
  62. package/abis/Coin.json +0 -1912
  63. package/abis/DopplerUniswapV3Test.json +0 -800
  64. package/abis/ICoinV4.json +0 -1048
  65. package/abis/Simulate.json +0 -29
  66. package/abis/UniV3BuySell.json +0 -12
  67. package/abis/UniV3Errors.json +0 -32
  68. package/script/Simulate.s.sol +0 -59
  69. package/src/Coin.sol +0 -236
  70. package/src/CoinV4.sol +0 -151
  71. package/src/interfaces/ICoinV4.sol +0 -74
  72. package/src/libs/CoinDopplerUniV3.sol +0 -50
  73. package/src/libs/CoinRewards.sol +0 -201
  74. package/src/libs/CoinSetupV3.sol +0 -50
  75. package/src/libs/UniV3BuySell.sol +0 -231
  76. package/src/libs/UniV3Errors.sol +0 -11
  77. package/test/CoinDopplerUniV3.t.sol +0 -310
  78. /package/abis/{CoinV4.json → ContentCoin.json} +0 -0
@@ -1,310 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.13;
3
-
4
- import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
5
- import {MarketConstants} from "../src/libs/MarketConstants.sol";
6
- import {BaseTest} from "./utils/BaseTest.sol";
7
- import {Coin} from "../src/Coin.sol";
8
- import {CoinConstants} from "../src/libs/CoinConstants.sol";
9
- import {IUniswapV3Pool} from "../src/interfaces/IUniswapV3Pool.sol";
10
- import {LpPosition} from "../src/types/LpPosition.sol";
11
- import {IDopplerErrors} from "../src/interfaces/IDopplerErrors.sol";
12
- import {DopplerMath, CoinDopplerUniV3} from "../src/libs/CoinDopplerUniV3.sol";
13
- import {TickMath} from "../src/utils/uniswap/TickMath.sol";
14
-
15
- contract DopplerUniswapV3Test is BaseTest {
16
- function _deployCoin(bytes memory poolConfig_) internal {
17
- vm.prank(users.creator);
18
- (address coinAddress, ) = factory.deploy(
19
- users.creator,
20
- _getDefaultOwners(),
21
- "https://test.com",
22
- "Testcoin",
23
- "TEST",
24
- poolConfig_,
25
- users.platformReferrer,
26
- 0
27
- );
28
-
29
- coin = Coin(payable(coinAddress));
30
- pool = IUniswapV3Pool(coin.poolAddress());
31
-
32
- vm.label(address(coin), "COIN");
33
- vm.label(address(pool), "POOL");
34
- }
35
-
36
- function setUp() public override {
37
- super.setUp();
38
- }
39
-
40
- function test_supply_constants() public {
41
- bytes memory poolConfig = _generatePoolConfig(
42
- CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION,
43
- address(weth),
44
- DEFAULT_DISCOVERY_TICK_LOWER,
45
- DEFAULT_DISCOVERY_TICK_UPPER,
46
- DEFAULT_NUM_DISCOVERY_POSITIONS,
47
- DEFAULT_DISCOVERY_SUPPLY_SHARE
48
- );
49
-
50
- _deployCoin(poolConfig);
51
- assertEq(CoinConstants.MAX_TOTAL_SUPPLY, CoinConstants.POOL_LAUNCH_SUPPLY + CoinConstants.CREATOR_LAUNCH_REWARD);
52
-
53
- assertEq(CoinConstants.MAX_TOTAL_SUPPLY, 1_000_000_000e18);
54
- assertEq(CoinConstants.POOL_LAUNCH_SUPPLY, 990_000_000e18);
55
- assertEq(CoinConstants.CREATOR_LAUNCH_REWARD, 10_000_000e18);
56
-
57
- assertEq(coin.totalSupply(), CoinConstants.MAX_TOTAL_SUPPLY);
58
- assertEq(coin.balanceOf(coin.payoutRecipient()), CoinConstants.CREATOR_LAUNCH_REWARD);
59
- assertApproxEqAbs(coin.balanceOf(address(pool)), CoinConstants.POOL_LAUNCH_SUPPLY, 1e18);
60
- }
61
-
62
- function test_deploy_doppler_eth_with_prebuy(uint256 initialOrderSize) public {
63
- vm.assume(initialOrderSize > CoinConstants.MIN_ORDER_SIZE);
64
- vm.assume(initialOrderSize < 1 ether);
65
-
66
- vm.deal(users.creator, initialOrderSize);
67
-
68
- bytes memory poolConfig = _generatePoolConfig(
69
- CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION,
70
- address(weth),
71
- DEFAULT_DISCOVERY_TICK_LOWER,
72
- DEFAULT_DISCOVERY_TICK_UPPER,
73
- DEFAULT_NUM_DISCOVERY_POSITIONS,
74
- DEFAULT_DISCOVERY_SUPPLY_SHARE
75
- );
76
-
77
- vm.prank(users.creator);
78
- (address coinAddress, uint256 coinsPurchased) = factory.deploy{value: initialOrderSize}(
79
- users.creator,
80
- _getDefaultOwners(),
81
- "https://test.com",
82
- "Testcoin",
83
- "TEST",
84
- poolConfig,
85
- users.platformReferrer,
86
- initialOrderSize
87
- );
88
-
89
- coin = Coin(payable(coinAddress));
90
- pool = IUniswapV3Pool(coin.poolAddress());
91
-
92
- assertEq(coin.currency(), address(weth), "currency");
93
- assertGt(coinsPurchased, 0, "coinsPurchased > 0");
94
- assertEq(coin.balanceOf(users.creator), CoinConstants.CREATOR_LAUNCH_REWARD + coinsPurchased, "balanceOf creator");
95
- assertGt(weth.balanceOf(address(pool)), 0, "Pool WETH balance");
96
- }
97
-
98
- function test_invalid_pool_config() public {
99
- bytes memory poolConfig = _generatePoolConfig(CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION, address(weth), -100, 100, 0, 10);
100
-
101
- vm.expectRevert(abi.encodeWithSignature("NumDiscoveryPositionsOutOfRange()"));
102
- factory.deploy(users.creator, _getDefaultOwners(), "https://test.com", "Testcoin", "TEST", poolConfig, users.platformReferrer, 0);
103
- }
104
-
105
- function test_revert_deploy_invalid_discovery_supply_share() public {
106
- bytes memory poolConfig = _generatePoolConfig(
107
- CoinConfigurationVersions.DOPPLER_UNI_V3_POOL_VERSION,
108
- address(weth),
109
- DEFAULT_DISCOVERY_TICK_LOWER,
110
- DEFAULT_DISCOVERY_TICK_UPPER,
111
- DEFAULT_NUM_DISCOVERY_POSITIONS,
112
- 1.1e18
113
- );
114
-
115
- vm.expectRevert(abi.encodeWithSelector(IDopplerErrors.MaxShareToBeSoldExceeded.selector, 1.1e18, 1e18));
116
- factory.deploy(users.creator, _getDefaultOwners(), "https://test.com", "Testcoin", "TEST", poolConfig, users.platformReferrer, 0);
117
- }
118
-
119
- function test_alignTick_isToken0_positive() public pure {
120
- int24 tick = 12345;
121
- int24 TICK_SPACING = 60;
122
- int24 expected = 12300;
123
-
124
- assertEq(DopplerMath.alignTickToTickSpacing(true, tick, TICK_SPACING), expected, "Align positive tick (token0)");
125
- }
126
-
127
- function test_alignTick_isToken0_negative() public pure {
128
- int24 tick = -12345;
129
- int24 TICK_SPACING = 60;
130
- int24 expected = -12360;
131
- assertEq(DopplerMath.alignTickToTickSpacing(true, tick, TICK_SPACING), expected, "Align negative tick (token0)");
132
- }
133
-
134
- function test_alignTick_isToken1_negative() public pure {
135
- int24 tick = -12345;
136
- int24 TICK_SPACING = 60;
137
- int24 expected = -12300;
138
- assertEq(DopplerMath.alignTickToTickSpacing(false, tick, TICK_SPACING), expected, "Align negative tick (token1)");
139
- }
140
-
141
- function test_alignTick_isToken1_zero() public pure {
142
- int24 tick = 0;
143
- int24 expected = 0;
144
- assertEq(DopplerMath.alignTickToTickSpacing(false, tick, MarketConstants.TICK_SPACING), expected, "Align zero tick (token1)");
145
- }
146
-
147
- // Additional tick alignment test for full branch coverage
148
- function test_alignTick_isToken0_zero() public pure {
149
- int24 tick = 0;
150
- int24 expected = 0;
151
- assertEq(DopplerMath.alignTickToTickSpacing(true, tick, MarketConstants.TICK_SPACING), expected, "Align zero tick (token0)");
152
- }
153
-
154
- function test_alignTick_isToken1_positive() public pure {
155
- int24 tick = 12345;
156
- int24 expected = 12400; // Round up for token1
157
- assertEq(DopplerMath.alignTickToTickSpacing(false, tick, MarketConstants.TICK_SPACING), expected, "Align positive tick (token1)");
158
- }
159
-
160
- function test_calculateLpTail_isToken0() public pure {
161
- int24 tickLower = DEFAULT_DISCOVERY_TICK_LOWER;
162
- int24 tickUpper = DEFAULT_DISCOVERY_TICK_UPPER;
163
- uint256 tailSupply = 1e18;
164
- bool isToken0 = true;
165
-
166
- LpPosition memory tail = DopplerMath.calculateLpTail(tickLower, tickUpper, isToken0, tailSupply, MarketConstants.TICK_SPACING);
167
-
168
- int24 expectedPosTickLower = tickUpper;
169
- int24 expectedPosTickUpper = DopplerMath.alignTickToTickSpacing(true, TickMath.MAX_TICK, MarketConstants.TICK_SPACING);
170
-
171
- assertEq(tail.tickLower, expectedPosTickLower, "Tail tickLower (token0)");
172
- assertEq(tail.tickUpper, expectedPosTickUpper, "Tail tickUpper (token0)");
173
- assertGt(tail.liquidity, 0, "Tail liquidity should be > 0 (token0)");
174
- }
175
-
176
- function test_calculateLpTail_isToken1() public pure {
177
- int24 tickLower = DEFAULT_DISCOVERY_TICK_LOWER;
178
- int24 tickUpper = DEFAULT_DISCOVERY_TICK_UPPER;
179
- uint256 tailSupply = 1e18;
180
- bool isToken0 = false;
181
-
182
- LpPosition memory tail = DopplerMath.calculateLpTail(tickLower, tickUpper, isToken0, tailSupply, MarketConstants.TICK_SPACING);
183
-
184
- int24 expectedPosTickLower = DopplerMath.alignTickToTickSpacing(false, TickMath.MIN_TICK, MarketConstants.TICK_SPACING);
185
- int24 expectedPosTickUpper = tickLower;
186
-
187
- assertEq(tail.tickLower, expectedPosTickLower, "Tail tickLower (token1)");
188
- assertEq(tail.tickUpper, expectedPosTickUpper, "Tail tickUpper (token1)");
189
- assertGt(tail.liquidity, 0, "Tail liquidity should be > 0 (token1)");
190
- }
191
-
192
- function test_calculateLogNormalDistribution_isToken0() public pure {
193
- int24 tickLower = -60000;
194
- int24 tickUpper = 0;
195
- bool isToken0 = true;
196
- uint256 discoverySupply = 100e18;
197
- LpPosition[] memory newPositions = new LpPosition[](DEFAULT_NUM_DISCOVERY_POSITIONS);
198
-
199
- (LpPosition[] memory positions, uint256 totalAssetsSold) = DopplerMath.calculateLogNormalDistribution(
200
- tickLower,
201
- tickUpper,
202
- MarketConstants.TICK_SPACING,
203
- isToken0,
204
- discoverySupply,
205
- DEFAULT_NUM_DISCOVERY_POSITIONS,
206
- newPositions,
207
- 0
208
- );
209
-
210
- assertEq(positions.length, DEFAULT_NUM_DISCOVERY_POSITIONS, "Correct number of positions (token0)");
211
- assertTrue(totalAssetsSold <= discoverySupply, "Total assets sold <= discovery supply (token0)");
212
- assertTrue(totalAssetsSold > 0, "Total assets sold > 0 (token0)");
213
-
214
- int24 expectedFarTick = tickUpper; // 0
215
- for (uint i = 0; i < DEFAULT_NUM_DISCOVERY_POSITIONS; i++) {
216
- assertTrue(positions[i].liquidity > 0, "Position liquidity > 0 (token0)");
217
- assertTrue(positions[i].tickLower <= positions[i].tickUpper, "Tick order check (token0)");
218
- assertEq(positions[i].tickLower % MarketConstants.TICK_SPACING, 0, "Lower tick alignment (token0)");
219
- assertEq(positions[i].tickUpper % MarketConstants.TICK_SPACING, 0, "Upper tick alignment (token0)");
220
- assertEq(positions[i].tickUpper, expectedFarTick, "Far tick check (token0)");
221
- }
222
- }
223
-
224
- function test_calculateLogNormalDistribution_isToken1() public pure {
225
- int24 tickLower = -60000;
226
- int24 tickUpper = 0;
227
- bool isToken0 = false;
228
- uint256 discoverySupply = 100e18;
229
- LpPosition[] memory newPositions = new LpPosition[](DEFAULT_NUM_DISCOVERY_POSITIONS);
230
-
231
- (LpPosition[] memory positions, uint256 totalAssetsSold) = DopplerMath.calculateLogNormalDistribution(
232
- tickLower,
233
- tickUpper,
234
- MarketConstants.TICK_SPACING,
235
- isToken0,
236
- discoverySupply,
237
- DEFAULT_NUM_DISCOVERY_POSITIONS,
238
- newPositions,
239
- 0
240
- );
241
-
242
- assertEq(positions.length, DEFAULT_NUM_DISCOVERY_POSITIONS, "Correct number of positions (token1)");
243
- assertTrue(totalAssetsSold <= discoverySupply, "Total assets sold <= discovery supply (token1)");
244
- assertTrue(totalAssetsSold > 0, "Total assets sold > 0 (token1)");
245
-
246
- int24 expectedFarTick = tickLower; // -60000
247
- for (uint i = 0; i < DEFAULT_NUM_DISCOVERY_POSITIONS; i++) {
248
- assertTrue(positions[i].liquidity > 0, "Position liquidity > 0 (token1)");
249
- assertTrue(positions[i].tickLower <= positions[i].tickUpper, "Tick order check (token1)");
250
- assertEq(positions[i].tickLower % MarketConstants.TICK_SPACING, 0, "Lower tick alignment (token1)");
251
- assertEq(positions[i].tickUpper % MarketConstants.TICK_SPACING, 0, "Upper tick alignment (token1)");
252
- assertEq(positions[i].tickLower, expectedFarTick, "Far tick check (token1)");
253
- }
254
- }
255
-
256
- function test_calculateLogNormalDistribution_zeroDiscoverySupply() public pure {
257
- int24 tickLower = -60000;
258
- int24 tickUpper = 0;
259
- bool isToken0 = true;
260
- uint256 discoverySupply = 0;
261
- LpPosition[] memory newPositions = new LpPosition[](DEFAULT_NUM_DISCOVERY_POSITIONS);
262
-
263
- (LpPosition[] memory positions, uint256 totalAssetsSold) = DopplerMath.calculateLogNormalDistribution(
264
- tickLower,
265
- tickUpper,
266
- MarketConstants.TICK_SPACING,
267
- isToken0,
268
- discoverySupply,
269
- DEFAULT_NUM_DISCOVERY_POSITIONS,
270
- newPositions,
271
- 0
272
- );
273
-
274
- assertEq(positions.length, DEFAULT_NUM_DISCOVERY_POSITIONS, "Correct number of positions (zero supply)");
275
- assertEq(totalAssetsSold, 0, "Total assets sold is 0 (zero supply)");
276
-
277
- for (uint i = 0; i < DEFAULT_NUM_DISCOVERY_POSITIONS; i++) {
278
- assertEq(positions[i].liquidity, 0, "Position liquidity is 0 (zero supply)");
279
- assertTrue(positions[i].tickLower <= positions[i].tickUpper, "Tick order check (zero supply)");
280
- assertEq(positions[i].tickLower % MarketConstants.TICK_SPACING, 0, "Lower tick alignment (zero supply)");
281
- assertEq(positions[i].tickUpper % MarketConstants.TICK_SPACING, 0, "Upper tick alignment (zero supply)");
282
- }
283
- }
284
-
285
- function test_calculateLogNormalDistribution_startingTickEqualsFarTick() public pure {
286
- // Will force startingTick == farTick
287
- int24 tickLower = 0;
288
- int24 tickUpper = 0;
289
-
290
- bool isToken0 = true;
291
- uint256 discoverySupply = 100e18;
292
- uint16 totalPositions = 1;
293
- LpPosition[] memory newPositions = new LpPosition[](totalPositions);
294
-
295
- (LpPosition[] memory positions, uint256 totalAssetsSold) = DopplerMath.calculateLogNormalDistribution(
296
- tickLower,
297
- tickUpper,
298
- MarketConstants.TICK_SPACING,
299
- isToken0,
300
- discoverySupply,
301
- totalPositions,
302
- newPositions,
303
- 0
304
- );
305
-
306
- assertEq(positions.length, totalPositions, "Correct number of positions");
307
- assertEq(totalAssetsSold, 0, "No assets sold when startingTick equals farTick");
308
- assertEq(positions[0].liquidity, 0, "Position should have zero liquidity");
309
- }
310
- }
File without changes