@zoralabs/coins 2.5.0 → 2.6.1
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$colon$js.log +136 -130
- package/CHANGELOG.md +28 -17
- package/abis/BaseCoin.json +5 -0
- package/abis/ContentCoin.json +5 -0
- package/abis/ICoin.json +5 -0
- package/abis/ICoinV3.json +5 -0
- package/abis/ITrendCoin.json +140 -0
- package/abis/ITrendCoinErrors.json +33 -0
- package/abis/IUniversalRouter.json +61 -0
- package/abis/IZoraFactory.json +237 -0
- package/abis/TrendCoin.json +2053 -0
- package/abis/ZoraFactoryImpl.json +242 -0
- package/dist/index.cjs +955 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +953 -138
- package/dist/index.js.map +1 -1
- package/dist/wagmiGenerated.d.ts +1388 -149
- package/dist/wagmiGenerated.d.ts.map +1 -1
- package/foundry.toml +1 -0
- package/package/wagmiGenerated.ts +962 -139
- package/package.json +2 -2
- package/src/BaseCoin.sol +12 -12
- package/src/ContentCoin.sol +20 -1
- package/src/CreatorCoin.sol +3 -0
- package/src/TrendCoin.sol +117 -0
- package/src/ZoraFactoryImpl.sol +142 -1
- package/src/hooks/ZoraV4CoinHook.sol +17 -7
- package/src/interfaces/ICoin.sol +5 -1
- package/src/interfaces/ICreatorCoin.sol +0 -3
- package/src/interfaces/IPoolManager.sol +13 -0
- package/src/interfaces/ITrendCoin.sol +26 -0
- package/src/interfaces/ITrendCoinErrors.sol +24 -0
- package/src/interfaces/IZoraFactory.sol +60 -1
- package/src/libs/CoinConstants.sol +13 -1
- package/src/libs/CoinRewardsV4.sol +82 -21
- package/src/libs/TickerUtils.sol +66 -0
- package/src/libs/UniV4SwapToCurrency.sol +2 -1
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/CoinRewardsV4.t.sol +48 -0
- package/test/CreatorCoin.t.sol +2 -1
- package/test/Factory.t.sol +31 -5
- package/test/LaunchFee.t.sol +0 -2
- package/test/LiquidityMigration.t.sol +0 -2
- package/test/TrendCoin.t.sol +1128 -0
- package/test/Upgrades.t.sol +16 -3
- package/test/utils/FeeEstimatorHook.sol +36 -10
- package/test/utils/V4TestSetup.sol +36 -4
- package/wagmi.config.ts +2 -0
package/test/Upgrades.t.sol
CHANGED
|
@@ -65,7 +65,8 @@ contract UpgradesTest is BaseTest, ForkedCoinsAddresses {
|
|
|
65
65
|
seller: makeAddr("seller"),
|
|
66
66
|
coinRecipient: makeAddr("coinRecipient"),
|
|
67
67
|
tradeReferrer: makeAddr("tradeReferrer"),
|
|
68
|
-
dopplerRecipient: makeAddr("dopplerRecipient")
|
|
68
|
+
dopplerRecipient: makeAddr("dopplerRecipient"),
|
|
69
|
+
metadataManager: makeAddr("metadataManager")
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -75,7 +76,13 @@ contract UpgradesTest is BaseTest, ForkedCoinsAddresses {
|
|
|
75
76
|
|
|
76
77
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
77
78
|
|
|
78
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
79
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
80
|
+
address(coinV4Impl),
|
|
81
|
+
address(creatorCoinImpl),
|
|
82
|
+
address(trendCoinImpl),
|
|
83
|
+
address(hook),
|
|
84
|
+
address(zoraHookRegistry)
|
|
85
|
+
);
|
|
79
86
|
|
|
80
87
|
vm.prank(factoryProxy.owner());
|
|
81
88
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
@@ -90,7 +97,13 @@ contract UpgradesTest is BaseTest, ForkedCoinsAddresses {
|
|
|
90
97
|
|
|
91
98
|
factoryProxy = ZoraFactoryImpl(0x777777751622c0d3258f214F9DF38E35BF45baF3);
|
|
92
99
|
|
|
93
|
-
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
100
|
+
ZoraFactoryImpl newImpl = new ZoraFactoryImpl(
|
|
101
|
+
address(coinV4Impl),
|
|
102
|
+
address(creatorCoinImpl),
|
|
103
|
+
address(trendCoinImpl),
|
|
104
|
+
address(hook),
|
|
105
|
+
address(zoraHookRegistry)
|
|
106
|
+
);
|
|
94
107
|
|
|
95
108
|
vm.prank(factoryProxy.owner());
|
|
96
109
|
factoryProxy.upgradeToAndCall(address(newImpl), "");
|
|
@@ -10,10 +10,11 @@ import {IHasRewardsRecipients} from "../../src/interfaces/IHasRewardsRecipients.
|
|
|
10
10
|
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
|
|
11
11
|
import {SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
|
|
12
12
|
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
|
|
13
|
+
import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
|
|
13
14
|
import {CoinCommon} from "../../src/libs/CoinCommon.sol";
|
|
14
15
|
import {V4Liquidity} from "../../src/libs/V4Liquidity.sol";
|
|
15
16
|
import {BaseHook} from "@uniswap/v4-periphery/src/utils/BaseHook.sol";
|
|
16
|
-
import {ICoin, IHasSwapPath} from "../../src/interfaces/ICoin.sol";
|
|
17
|
+
import {ICoin, IHasSwapPath, IHasCoinType} from "../../src/interfaces/ICoin.sol";
|
|
17
18
|
import {UniV4SwapToCurrency} from "../../src/libs/UniV4SwapToCurrency.sol";
|
|
18
19
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
19
20
|
import {CoinRewardsV4} from "../../src/libs/CoinRewardsV4.sol";
|
|
@@ -65,21 +66,46 @@ contract FeeEstimatorHook is ZoraV4CoinHook {
|
|
|
65
66
|
uint256 coinBalanceBefore = IERC20(coin).balanceOf(address(this));
|
|
66
67
|
uint256 currencyBalanceBefore = IERC20(ICoin(coin).currency()).balanceOf(address(this));
|
|
67
68
|
|
|
68
|
-
IHasSwapPath.PayoutSwapPath memory payoutSwapPath = IHasSwapPath(coin).getPayoutSwapPath(coinVersionLookup);
|
|
69
|
-
|
|
70
69
|
int128 fee0;
|
|
71
70
|
int128 fee1;
|
|
72
71
|
|
|
73
72
|
(fee0, fee1) = V4Liquidity.collectFees(poolManager, key, poolCoins[poolKeyHash].positions);
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
IHasCoinType.CoinType coinType = CoinRewardsV4.getCoinType(IHasRewardsRecipients(coin));
|
|
75
|
+
(uint128 remainingFee0, uint128 remainingFee1) = CoinRewardsV4.mintLpReward(poolManager, key, fee0, fee1, coinType);
|
|
76
|
+
|
|
77
|
+
// Execute the swap path to estimate the payout amount, but don't distribute
|
|
78
|
+
// This mirrors the logic in ZoraV4CoinHook._afterSwap
|
|
79
|
+
IHasSwapPath.PayoutSwapPath memory payoutSwapPath = IHasSwapPath(coin).getPayoutSwapPath(coinVersionLookup);
|
|
76
80
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// Execute swap and track all deltas that result
|
|
82
|
+
UniV4SwapToCurrency.swapToPath(poolManager, remainingFee0, remainingFee1, payoutSwapPath.currencyIn, payoutSwapPath.path);
|
|
83
|
+
|
|
84
|
+
// Take all positive deltas and sum them to get total payout amount
|
|
85
|
+
uint128 totalPayout = 0;
|
|
86
|
+
|
|
87
|
+
// Check currencyIn for positive delta
|
|
88
|
+
int256 deltaIn = TransientStateLibrary.currencyDelta(poolManager, address(this), payoutSwapPath.currencyIn);
|
|
89
|
+
if (deltaIn > 0) {
|
|
90
|
+
uint128 amount = uint128(uint256(deltaIn));
|
|
91
|
+
poolManager.take(payoutSwapPath.currencyIn, address(this), amount);
|
|
92
|
+
totalPayout += amount;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Check all intermediate currencies for positive deltas
|
|
96
|
+
for (uint256 i = 0; i < payoutSwapPath.path.length; i++) {
|
|
97
|
+
Currency intermediateCurrency = payoutSwapPath.path[i].intermediateCurrency;
|
|
98
|
+
int256 delta = TransientStateLibrary.currencyDelta(poolManager, address(this), intermediateCurrency);
|
|
99
|
+
if (delta > 0) {
|
|
100
|
+
uint128 amount = uint128(uint256(delta));
|
|
101
|
+
poolManager.take(intermediateCurrency, address(this), amount);
|
|
102
|
+
totalPayout += amount;
|
|
103
|
+
// Track the last positive currency as the payout currency
|
|
104
|
+
feeState.afterSwapCurrency = intermediateCurrency;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
feeState.afterSwapCurrencyAmount = totalPayout;
|
|
83
109
|
|
|
84
110
|
feeState.fees0 += uint128(fee0);
|
|
85
111
|
feeState.fees1 += uint128(fee1);
|
|
@@ -29,6 +29,7 @@ import {ZoraFactoryImpl} from "../../src/ZoraFactoryImpl.sol";
|
|
|
29
29
|
import {ZoraFactory} from "../../src/proxy/ZoraFactory.sol";
|
|
30
30
|
import {ContentCoin} from "../../src/ContentCoin.sol";
|
|
31
31
|
import {CreatorCoin} from "../../src/CreatorCoin.sol";
|
|
32
|
+
import {TrendCoin} from "../../src/TrendCoin.sol";
|
|
32
33
|
import {CoinConfigurationVersions} from "../../src/libs/CoinConfigurationVersions.sol";
|
|
33
34
|
import {CoinConstants} from "../../src/libs/CoinConstants.sol";
|
|
34
35
|
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
@@ -75,6 +76,7 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
75
76
|
address coinRecipient;
|
|
76
77
|
address tradeReferrer;
|
|
77
78
|
address dopplerRecipient;
|
|
79
|
+
address metadataManager;
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
// Fork management
|
|
@@ -101,6 +103,7 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
101
103
|
// Zora protocol contracts
|
|
102
104
|
ContentCoin internal coinV4Impl;
|
|
103
105
|
CreatorCoin internal creatorCoinImpl;
|
|
106
|
+
TrendCoin internal trendCoinImpl;
|
|
104
107
|
ZoraFactoryImpl internal factoryImpl;
|
|
105
108
|
IZoraFactory internal factory;
|
|
106
109
|
ZoraV4CoinHook internal hook;
|
|
@@ -147,7 +150,8 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
147
150
|
seller: makeAddr("seller"),
|
|
148
151
|
coinRecipient: makeAddr("coinRecipient"),
|
|
149
152
|
tradeReferrer: makeAddr("tradeReferrer"),
|
|
150
|
-
dopplerRecipient: makeAddr("dopplerRecipient")
|
|
153
|
+
dopplerRecipient: makeAddr("dopplerRecipient"),
|
|
154
|
+
metadataManager: makeAddr("metadataManager")
|
|
151
155
|
});
|
|
152
156
|
|
|
153
157
|
ProxyShim mockUpgradeableImpl = new ProxyShim();
|
|
@@ -168,12 +172,17 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
168
172
|
|
|
169
173
|
creatorCoinImpl = new CreatorCoin(users.feeRecipient, address(protocolRewards), IPoolManager(V4_POOL_MANAGER), DOPPLER_AIRLOCK);
|
|
170
174
|
|
|
171
|
-
|
|
175
|
+
trendCoinImpl = new TrendCoin(users.feeRecipient, address(protocolRewards), IPoolManager(V4_POOL_MANAGER), DOPPLER_AIRLOCK, users.metadataManager);
|
|
176
|
+
|
|
177
|
+
factoryImpl = new ZoraFactoryImpl(address(coinV4Impl), address(creatorCoinImpl), address(trendCoinImpl), address(hook), address(zoraHookRegistry));
|
|
172
178
|
UUPSUpgradeable(address(factory)).upgradeToAndCall(address(factoryImpl), "");
|
|
173
179
|
factory = IZoraFactory(address(factory));
|
|
174
180
|
|
|
175
181
|
ZoraFactoryImpl(address(factory)).initialize(users.factoryOwner);
|
|
176
182
|
|
|
183
|
+
// Set trend coin pool config
|
|
184
|
+
_setTrendCoinPoolConfig();
|
|
185
|
+
|
|
177
186
|
vm.label(address(factory), "ZORA_FACTORY");
|
|
178
187
|
vm.label(address(protocolRewards), "PROTOCOL_REWARDS");
|
|
179
188
|
vm.label(address(nonfungiblePositionManager), "NONFUNGIBLE_POSITION_MANAGER");
|
|
@@ -208,7 +217,8 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
208
217
|
seller: makeAddr("seller"),
|
|
209
218
|
coinRecipient: makeAddr("coinRecipient"),
|
|
210
219
|
tradeReferrer: makeAddr("tradeReferrer"),
|
|
211
|
-
dopplerRecipient: makeAddr("dopplerRecipient")
|
|
220
|
+
dopplerRecipient: makeAddr("dopplerRecipient"),
|
|
221
|
+
metadataManager: makeAddr("metadataManager")
|
|
212
222
|
});
|
|
213
223
|
|
|
214
224
|
// Deploy mock airlock with the dopplerRecipient as owner (for doppler rewards)
|
|
@@ -250,12 +260,16 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
250
260
|
// Deploy coin implementations
|
|
251
261
|
coinV4Impl = new ContentCoin(users.feeRecipient, address(protocolRewards), poolManager, address(mockAirlock));
|
|
252
262
|
creatorCoinImpl = new CreatorCoin(users.feeRecipient, address(protocolRewards), poolManager, address(mockAirlock));
|
|
263
|
+
trendCoinImpl = new TrendCoin(users.feeRecipient, address(protocolRewards), poolManager, address(mockAirlock), users.metadataManager);
|
|
253
264
|
|
|
254
265
|
// Deploy and initialize factory implementation
|
|
255
|
-
factoryImpl = new ZoraFactoryImpl(address(coinV4Impl), address(creatorCoinImpl), address(hook), address(zoraHookRegistry));
|
|
266
|
+
factoryImpl = new ZoraFactoryImpl(address(coinV4Impl), address(creatorCoinImpl), address(trendCoinImpl), address(hook), address(zoraHookRegistry));
|
|
256
267
|
UUPSUpgradeable(address(factory)).upgradeToAndCall(address(factoryImpl), "");
|
|
257
268
|
ZoraFactoryImpl(address(factory)).initialize(users.factoryOwner);
|
|
258
269
|
|
|
270
|
+
// Set trend coin pool config
|
|
271
|
+
_setTrendCoinPoolConfig();
|
|
272
|
+
|
|
259
273
|
// Deploy mock V3 swap router for non-forked tests
|
|
260
274
|
swapRouter = ISwapRouter(address(new MockSwapRouter()));
|
|
261
275
|
|
|
@@ -271,6 +285,24 @@ contract V4TestSetup is Test, ContractAddresses {
|
|
|
271
285
|
vm.label(address(swapRouter), "MOCK_SWAP_ROUTER");
|
|
272
286
|
}
|
|
273
287
|
|
|
288
|
+
// ============================================
|
|
289
|
+
// Trend Coin Pool Config Helper
|
|
290
|
+
// ============================================
|
|
291
|
+
|
|
292
|
+
function _setTrendCoinPoolConfig() internal {
|
|
293
|
+
(
|
|
294
|
+
,
|
|
295
|
+
address currency,
|
|
296
|
+
int24[] memory tickLower,
|
|
297
|
+
int24[] memory tickUpper,
|
|
298
|
+
uint16[] memory numDiscoveryPositions,
|
|
299
|
+
uint256[] memory maxDiscoverySupplyShare
|
|
300
|
+
) = CoinConfigurationVersions.decodeDopplerMultiCurveUniV4(CoinConstants.TREND_COIN_DEFAULT_POOL_CONFIG);
|
|
301
|
+
|
|
302
|
+
vm.prank(users.factoryOwner);
|
|
303
|
+
factory.setTrendCoinPoolConfig(currency, tickLower, tickUpper, numDiscoveryPositions, maxDiscoverySupplyShare);
|
|
304
|
+
}
|
|
305
|
+
|
|
274
306
|
// ============================================
|
|
275
307
|
// V4 Infrastructure Deployment (Non-Forked)
|
|
276
308
|
// ============================================
|
package/wagmi.config.ts
CHANGED
|
@@ -16,9 +16,11 @@ export default defineConfig({
|
|
|
16
16
|
"IUniswapV3Pool",
|
|
17
17
|
"IPoolConfigEncoding",
|
|
18
18
|
"IPermit2",
|
|
19
|
+
"IPoolManager",
|
|
19
20
|
"AutoSwapper",
|
|
20
21
|
"BuySupplyWithV4SwapHook",
|
|
21
22
|
"ZoraV4CoinHook",
|
|
23
|
+
"IUniversalRouter"
|
|
22
24
|
].map((contractName) => `${contractName}.json`),
|
|
23
25
|
}),
|
|
24
26
|
],
|