@zoralabs/coins 2.2.1 → 2.3.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.
Files changed (88) hide show
  1. package/.turbo/turbo-build$colon$js.log +125 -106
  2. package/CHANGELOG.md +50 -5
  3. package/README.md +5 -0
  4. package/abis/AddressConstants.json +7 -0
  5. package/abis/BaseCoin.json +0 -5
  6. package/abis/BaseTest.json +62 -0
  7. package/abis/BuySupplyWithV4SwapHook.json +429 -0
  8. package/abis/ContentCoin.json +0 -5
  9. package/abis/CreatorCoin.json +0 -5
  10. package/abis/FeeEstimatorHook.json +94 -1
  11. package/abis/IUniswapV4Router04.json +484 -0
  12. package/abis/IUpgradeableDestinationV4HookWithUpdateableFee.json +95 -0
  13. package/abis/IZoraFactory.json +69 -0
  14. package/abis/MockAirlock.json +39 -0
  15. package/abis/SimpleERC20.json +326 -0
  16. package/abis/ZoraFactoryImpl.json +69 -0
  17. package/abis/ZoraV4CoinHook.json +94 -1
  18. package/addresses/8453.json +8 -10
  19. package/audits/report-cantinacode-zora-0827.pdf +3498 -4
  20. package/audits/report-cantinacode-zora-1021.pdf +0 -0
  21. package/dist/index.cjs +161 -22
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.js +160 -21
  24. package/dist/index.js.map +1 -1
  25. package/dist/wagmiGenerated.d.ts +259 -40
  26. package/dist/wagmiGenerated.d.ts.map +1 -1
  27. package/foundry.toml +3 -3
  28. package/package/wagmiGenerated.ts +160 -21
  29. package/package.json +1 -1
  30. package/script/DeployPostDeploymentHooks.s.sol +1 -3
  31. package/script/TestBackingCoinSwap.s.sol +0 -2
  32. package/script/TestV4Swap.s.sol +0 -2
  33. package/src/BaseCoin.sol +4 -12
  34. package/src/ContentCoin.sol +3 -4
  35. package/src/CreatorCoin.sol +8 -10
  36. package/src/ZoraFactoryImpl.sol +115 -83
  37. package/src/deployment/CoinsDeployerBase.sol +9 -8
  38. package/src/hook-registry/ZoraHookRegistry.sol +4 -0
  39. package/src/hooks/ZoraV4CoinHook.sol +66 -9
  40. package/src/hooks/deployment/BuySupplyWithV4SwapHook.sol +310 -0
  41. package/src/interfaces/IUpgradeableV4Hook.sol +18 -0
  42. package/src/interfaces/IZoraFactory.sol +21 -2
  43. package/src/libs/CoinConstants.sol +51 -8
  44. package/src/libs/CoinDopplerMultiCurve.sol +11 -11
  45. package/src/libs/CoinRewardsV4.sol +26 -33
  46. package/src/libs/CoinSetup.sol +2 -9
  47. package/src/libs/DopplerMath.sol +2 -2
  48. package/src/libs/V4Liquidity.sol +79 -15
  49. package/src/utils/AutoSwapper.sol +1 -1
  50. package/src/version/ContractVersionBase.sol +1 -1
  51. package/test/BuySupplyWithV4SwapHook.t.sol +509 -0
  52. package/test/Coin.t.sol +26 -14
  53. package/test/CoinRewardsV4.t.sol +33 -0
  54. package/test/CoinUniV4.t.sol +3 -5
  55. package/test/ContentCoinRewards.t.sol +44 -3
  56. package/test/CreatorCoin.t.sol +54 -33
  57. package/test/CreatorCoinRewards.t.sol +1 -3
  58. package/test/DeploymentHooks.t.sol +54 -2
  59. package/test/Factory.t.sol +3 -3
  60. package/test/LiquidityMigration.t.sol +145 -7
  61. package/test/MultiOwnable.t.sol +4 -4
  62. package/test/Upgrades.t.sol +26 -17
  63. package/test/V4Liquidity.t.sol +178 -0
  64. package/test/ZoraHookRegistry.t.sol +19 -9
  65. package/test/mocks/MockAirlock.sol +22 -0
  66. package/test/mocks/SimpleERC20.sol +8 -0
  67. package/test/utils/BaseTest.sol +155 -3
  68. package/test/utils/RewardTestHelpers.sol +4 -4
  69. package/test/utils/hookmate/README.md +50 -0
  70. package/test/utils/hookmate/artifacts/DeployHelper.sol +20 -0
  71. package/test/utils/hookmate/artifacts/Permit2.sol +16 -0
  72. package/test/utils/hookmate/artifacts/UniversalRouter.sol +29 -0
  73. package/test/utils/hookmate/artifacts/V4PoolManager.sol +17 -0
  74. package/test/utils/hookmate/artifacts/V4PositionManager.sol +23 -0
  75. package/test/utils/hookmate/artifacts/V4Quoter.sol +17 -0
  76. package/test/utils/hookmate/artifacts/V4Router.sol +18 -0
  77. package/test/utils/hookmate/constants/AddressConstants.sol +193 -0
  78. package/test/utils/hookmate/interfaces/router/IUniswapV4Router04.sol +173 -0
  79. package/test/utils/hookmate/interfaces/router/PathKey.sol +34 -0
  80. package/test/utils/hookmate/test/utils/SwapFeeEventAsserter.sol +24 -0
  81. package/wagmi.config.ts +1 -1
  82. package/abis/CoinConstants.json +0 -54
  83. package/abis/CoinRewardsV4.json +0 -67
  84. package/src/libs/CreatorCoinConstants.sol +0 -15
  85. package/src/libs/MarketConstants.sol +0 -23
  86. package/src/utils/uniswap/BytesLib.sol +0 -35
  87. package/src/utils/uniswap/Path.sol +0 -31
  88. /package/abis/{VmContractHelper227.json → VmContractHelper239.json} +0 -0
@@ -1174,16 +1174,15 @@ export const baseCoinABI = [
1174
1174
  },
1175
1175
  { type: 'error', inputs: [], name: 'OnlyWeth' },
1176
1176
  { type: 'error', inputs: [], name: 'OwnerCannotBeAddressZero' },
1177
- { type: 'error', inputs: [], name: 'ReentrancyGuardReentrantCall' },
1178
1177
  { type: 'error', inputs: [], name: 'SlippageBoundsExceeded' },
1179
1178
  { type: 'error', inputs: [], name: 'UseRevokeOwnershipToRemoveSelf' },
1180
1179
  ] as const
1181
1180
 
1182
1181
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1183
- // BuySupplyWithSwapRouterHook
1182
+ // BuySupplyWithV4SwapHook
1184
1183
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1185
1184
 
1186
- export const buySupplyWithSwapRouterHookABI = [
1185
+ export const buySupplyWithV4SwapHookABI = [
1187
1186
  {
1188
1187
  type: 'constructor',
1189
1188
  inputs: [
@@ -1208,6 +1207,63 @@ export const buySupplyWithSwapRouterHookABI = [
1208
1207
  outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],
1209
1208
  stateMutability: 'payable',
1210
1209
  },
1210
+ {
1211
+ type: 'function',
1212
+ inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],
1213
+ name: 'decodeV4RouteData',
1214
+ outputs: [
1215
+ {
1216
+ name: 'v4Route',
1217
+ internalType: 'struct PoolKey[]',
1218
+ type: 'tuple[]',
1219
+ components: [
1220
+ { name: 'currency0', internalType: 'Currency', type: 'address' },
1221
+ { name: 'currency1', internalType: 'Currency', type: 'address' },
1222
+ { name: 'fee', internalType: 'uint24', type: 'uint24' },
1223
+ { name: 'tickSpacing', internalType: 'int24', type: 'int24' },
1224
+ { name: 'hooks', internalType: 'contract IHooks', type: 'address' },
1225
+ ],
1226
+ },
1227
+ { name: 'startAmount', internalType: 'uint256', type: 'uint256' },
1228
+ ],
1229
+ stateMutability: 'pure',
1230
+ },
1231
+ {
1232
+ type: 'function',
1233
+ inputs: [
1234
+ {
1235
+ name: 'params',
1236
+ internalType: 'struct BuySupplyWithV4SwapHook.InitialSupplyParams',
1237
+ type: 'tuple',
1238
+ components: [
1239
+ { name: 'buyRecipient', internalType: 'address', type: 'address' },
1240
+ { name: 'v3Route', internalType: 'bytes', type: 'bytes' },
1241
+ {
1242
+ name: 'v4Route',
1243
+ internalType: 'struct PoolKey[]',
1244
+ type: 'tuple[]',
1245
+ components: [
1246
+ { name: 'currency0', internalType: 'Currency', type: 'address' },
1247
+ { name: 'currency1', internalType: 'Currency', type: 'address' },
1248
+ { name: 'fee', internalType: 'uint24', type: 'uint24' },
1249
+ { name: 'tickSpacing', internalType: 'int24', type: 'int24' },
1250
+ {
1251
+ name: 'hooks',
1252
+ internalType: 'contract IHooks',
1253
+ type: 'address',
1254
+ },
1255
+ ],
1256
+ },
1257
+ { name: 'inputCurrency', internalType: 'address', type: 'address' },
1258
+ { name: 'inputAmount', internalType: 'uint256', type: 'uint256' },
1259
+ { name: 'minAmountOut', internalType: 'uint256', type: 'uint256' },
1260
+ ],
1261
+ },
1262
+ ],
1263
+ name: 'encodeBuySupplyWithV4SwapHookData',
1264
+ outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],
1265
+ stateMutability: 'pure',
1266
+ },
1211
1267
  {
1212
1268
  type: 'function',
1213
1269
  inputs: [],
@@ -1217,6 +1273,15 @@ export const buySupplyWithSwapRouterHookABI = [
1217
1273
  ],
1218
1274
  stateMutability: 'view',
1219
1275
  },
1276
+ {
1277
+ type: 'function',
1278
+ inputs: [],
1279
+ name: 'poolManager',
1280
+ outputs: [
1281
+ { name: '', internalType: 'contract IPoolManager', type: 'address' },
1282
+ ],
1283
+ stateMutability: 'view',
1284
+ },
1220
1285
  {
1221
1286
  type: 'function',
1222
1287
  inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }],
@@ -1224,6 +1289,15 @@ export const buySupplyWithSwapRouterHookABI = [
1224
1289
  outputs: [{ name: '', internalType: 'bool', type: 'bool' }],
1225
1290
  stateMutability: 'pure',
1226
1291
  },
1292
+ {
1293
+ type: 'function',
1294
+ inputs: [],
1295
+ name: 'swapRouter',
1296
+ outputs: [
1297
+ { name: '', internalType: 'contract ISwapRouter', type: 'address' },
1298
+ ],
1299
+ stateMutability: 'view',
1300
+ },
1227
1301
  {
1228
1302
  type: 'function',
1229
1303
  inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],
@@ -1231,6 +1305,58 @@ export const buySupplyWithSwapRouterHookABI = [
1231
1305
  outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],
1232
1306
  stateMutability: 'nonpayable',
1233
1307
  },
1308
+ {
1309
+ type: 'event',
1310
+ anonymous: false,
1311
+ inputs: [
1312
+ { name: 'coin', internalType: 'address', type: 'address', indexed: true },
1313
+ {
1314
+ name: 'recipient',
1315
+ internalType: 'address',
1316
+ type: 'address',
1317
+ indexed: true,
1318
+ },
1319
+ {
1320
+ name: 'coinsPurchased',
1321
+ internalType: 'uint256',
1322
+ type: 'uint256',
1323
+ indexed: true,
1324
+ },
1325
+ { name: 'v3Route', internalType: 'bytes', type: 'bytes', indexed: false },
1326
+ {
1327
+ name: 'v4Route',
1328
+ internalType: 'struct PoolKey[]',
1329
+ type: 'tuple[]',
1330
+ components: [
1331
+ { name: 'currency0', internalType: 'Currency', type: 'address' },
1332
+ { name: 'currency1', internalType: 'Currency', type: 'address' },
1333
+ { name: 'fee', internalType: 'uint24', type: 'uint24' },
1334
+ { name: 'tickSpacing', internalType: 'int24', type: 'int24' },
1335
+ { name: 'hooks', internalType: 'contract IHooks', type: 'address' },
1336
+ ],
1337
+ indexed: false,
1338
+ },
1339
+ {
1340
+ name: 'inputCurrency',
1341
+ internalType: 'address',
1342
+ type: 'address',
1343
+ indexed: false,
1344
+ },
1345
+ {
1346
+ name: 'inputAmount',
1347
+ internalType: 'uint256',
1348
+ type: 'uint256',
1349
+ indexed: false,
1350
+ },
1351
+ {
1352
+ name: 'v4SwapInput',
1353
+ internalType: 'uint256',
1354
+ type: 'uint256',
1355
+ indexed: false,
1356
+ },
1357
+ ],
1358
+ name: 'BuyInitialSupply',
1359
+ },
1234
1360
  {
1235
1361
  type: 'error',
1236
1362
  inputs: [{ name: 'target', internalType: 'address', type: 'address' }],
@@ -1242,20 +1368,17 @@ export const buySupplyWithSwapRouterHookABI = [
1242
1368
  name: 'AddressInsufficientBalance',
1243
1369
  },
1244
1370
  { type: 'error', inputs: [], name: 'AddressZero' },
1371
+ { type: 'error', inputs: [], name: 'FailedInnerCall' },
1372
+ { type: 'error', inputs: [], name: 'HookNotImplemented' },
1245
1373
  {
1246
1374
  type: 'error',
1247
- inputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],
1248
- name: 'CoinBalanceNot0',
1249
- },
1250
- {
1251
- type: 'error',
1252
- inputs: [{ name: 'balance', internalType: 'uint256', type: 'uint256' }],
1253
- name: 'CurrencyBalanceNot0',
1375
+ inputs: [
1376
+ { name: 'inputAmount', internalType: 'uint256', type: 'uint256' },
1377
+ { name: 'availableAmount', internalType: 'uint256', type: 'uint256' },
1378
+ ],
1379
+ name: 'InsufficientInputCurrency',
1254
1380
  },
1255
- { type: 'error', inputs: [], name: 'Erc20NotReceived' },
1256
- { type: 'error', inputs: [], name: 'FailedInnerCall' },
1257
- { type: 'error', inputs: [], name: 'HookNotImplemented' },
1258
- { type: 'error', inputs: [], name: 'InvalidSwapRouterCall' },
1381
+ { type: 'error', inputs: [], name: 'InsufficientOutputAmount' },
1259
1382
  { type: 'error', inputs: [], name: 'NotFactory' },
1260
1383
  { type: 'error', inputs: [], name: 'OnlyPoolManager' },
1261
1384
  {
@@ -1263,11 +1386,8 @@ export const buySupplyWithSwapRouterHookABI = [
1263
1386
  inputs: [{ name: 'token', internalType: 'address', type: 'address' }],
1264
1387
  name: 'SafeERC20FailedOperation',
1265
1388
  },
1266
- {
1267
- type: 'error',
1268
- inputs: [{ name: 'error', internalType: 'bytes', type: 'bytes' }],
1269
- name: 'SwapReverted',
1270
- },
1389
+ { type: 'error', inputs: [], name: 'V3RouteCannotStartWithInputCurrency' },
1390
+ { type: 'error', inputs: [], name: 'V3RouteDoesNotConnectToV4RouteStart' },
1271
1391
  ] as const
1272
1392
 
1273
1393
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2367,7 +2487,6 @@ export const contentCoinABI = [
2367
2487
  },
2368
2488
  { type: 'error', inputs: [], name: 'OnlyWeth' },
2369
2489
  { type: 'error', inputs: [], name: 'OwnerCannotBeAddressZero' },
2370
- { type: 'error', inputs: [], name: 'ReentrancyGuardReentrantCall' },
2371
2490
  { type: 'error', inputs: [], name: 'SlippageBoundsExceeded' },
2372
2491
  { type: 'error', inputs: [], name: 'UseRevokeOwnershipToRemoveSelf' },
2373
2492
  ] as const
@@ -3542,7 +3661,6 @@ export const creatorCoinABI = [
3542
3661
  },
3543
3662
  { type: 'error', inputs: [], name: 'OnlyWeth' },
3544
3663
  { type: 'error', inputs: [], name: 'OwnerCannotBeAddressZero' },
3545
- { type: 'error', inputs: [], name: 'ReentrancyGuardReentrantCall' },
3546
3664
  { type: 'error', inputs: [], name: 'SlippageBoundsExceeded' },
3547
3665
  { type: 'error', inputs: [], name: 'UseRevokeOwnershipToRemoveSelf' },
3548
3666
  ] as const
@@ -4414,6 +4532,27 @@ export const zoraFactoryImplABI = [
4414
4532
  outputs: [{ name: '', internalType: 'address', type: 'address' }],
4415
4533
  stateMutability: 'nonpayable',
4416
4534
  },
4535
+ {
4536
+ type: 'function',
4537
+ inputs: [
4538
+ { name: 'payoutRecipient', internalType: 'address', type: 'address' },
4539
+ { name: 'owners', internalType: 'address[]', type: 'address[]' },
4540
+ { name: 'uri', internalType: 'string', type: 'string' },
4541
+ { name: 'name', internalType: 'string', type: 'string' },
4542
+ { name: 'symbol', internalType: 'string', type: 'string' },
4543
+ { name: 'poolConfig', internalType: 'bytes', type: 'bytes' },
4544
+ { name: 'platformReferrer', internalType: 'address', type: 'address' },
4545
+ { name: 'postDeployHook', internalType: 'address', type: 'address' },
4546
+ { name: 'postDeployHookData', internalType: 'bytes', type: 'bytes' },
4547
+ { name: 'coinSalt', internalType: 'bytes32', type: 'bytes32' },
4548
+ ],
4549
+ name: 'deployCreatorCoin',
4550
+ outputs: [
4551
+ { name: 'coin', internalType: 'address', type: 'address' },
4552
+ { name: 'postDeployHookDataOut', internalType: 'bytes', type: 'bytes' },
4553
+ ],
4554
+ stateMutability: 'payable',
4555
+ },
4417
4556
  {
4418
4557
  type: 'function',
4419
4558
  inputs: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoralabs/coins",
3
- "version": "2.2.1",
3
+ "version": "2.3.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -10,9 +10,7 @@ contract DeployHooks is CoinsDeployerBase {
10
10
 
11
11
  vm.startBroadcast();
12
12
 
13
- // address buySupplyWithSwapRouterHook = address(deployBuySupplyWithSwapRouterHook(deployment));
14
-
15
- // deployment.buySupplyWithSwapRouterHook = buySupplyWithSwapRouterHook;
13
+ deployment.buySupplyWithSwapRouterHook = address(deployBuySupplyWithV4SwapHook(deployment));
16
14
 
17
15
  vm.stopBroadcast();
18
16
 
@@ -6,14 +6,12 @@ import {CoinsDeployerBase} from "../src/deployment/CoinsDeployerBase.sol";
6
6
 
7
7
  import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
8
8
  import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
9
- import {MarketConstants} from "../src/libs/MarketConstants.sol";
10
9
  import {UniV4SwapHelper} from "../src/libs/UniV4SwapHelper.sol";
11
10
  import {ContentCoin} from "../src/ContentCoin.sol";
12
11
  import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
13
12
  import {IUniversalRouter} from "@uniswap/universal-router/contracts/interfaces/IUniversalRouter.sol";
14
13
  import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
15
14
  import {MockERC20} from "../test/mocks/MockERC20.sol";
16
- import {MarketConstants} from "../src/libs/MarketConstants.sol";
17
15
  import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
18
16
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
19
17
  import {ICoin} from "../src/interfaces/ICoin.sol";
@@ -6,14 +6,12 @@ import {CoinsDeployerBase} from "../src/deployment/CoinsDeployerBase.sol";
6
6
 
7
7
  import {IZoraFactory} from "../src/interfaces/IZoraFactory.sol";
8
8
  import {CoinConfigurationVersions} from "../src/libs/CoinConfigurationVersions.sol";
9
- import {MarketConstants} from "../src/libs/MarketConstants.sol";
10
9
  import {UniV4SwapHelper} from "../src/libs/UniV4SwapHelper.sol";
11
10
  import {ContentCoin} from "../src/ContentCoin.sol";
12
11
  import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
13
12
  import {IUniversalRouter} from "@uniswap/universal-router/contracts/interfaces/IUniversalRouter.sol";
14
13
  import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
15
14
  import {MockERC20} from "../test/mocks/MockERC20.sol";
16
- import {MarketConstants} from "../src/libs/MarketConstants.sol";
17
15
  import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
18
16
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
19
17
  import {ICoin} from "../src/interfaces/ICoin.sol";
package/src/BaseCoin.sol CHANGED
@@ -32,7 +32,6 @@ import {CoinCommon} from "./libs/CoinCommon.sol";
32
32
  import {Address} from "@openzeppelin/contracts/utils/Address.sol";
33
33
  import {ERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
34
34
  import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
35
- import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
36
35
  import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
37
36
  import {ContractVersionBase} from "./version/ContractVersionBase.sol";
38
37
  import {MultiOwnable} from "./utils/MultiOwnable.sol";
@@ -40,7 +39,6 @@ import {FullMath} from "./utils/uniswap/FullMath.sol";
40
39
  import {TickMath} from "./utils/uniswap/TickMath.sol";
41
40
  import {LiquidityAmounts} from "./utils/uniswap/LiquidityAmounts.sol";
42
41
  import {CoinConstants} from "./libs/CoinConstants.sol";
43
- import {MarketConstants} from "./libs/MarketConstants.sol";
44
42
  import {LpPosition} from "./types/LpPosition.sol";
45
43
  import {PoolState} from "./types/PoolState.sol";
46
44
 
@@ -54,7 +52,7 @@ import {PoolState} from "./types/PoolState.sol";
54
52
  \$$$$$$ | $$$$$$ |$$$$$$\ $$ | \$$ |
55
53
  \______/ \______/ \______|\__| \__|
56
54
  */
57
- abstract contract BaseCoin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnable, ReentrancyGuardUpgradeable, ERC165Upgradeable {
55
+ abstract contract BaseCoin is ICoin, ContractVersionBase, ERC20PermitUpgradeable, MultiOwnable, ERC165Upgradeable {
58
56
  using SafeERC20 for IERC20;
59
57
 
60
58
  /// @notice The address of the protocol rewards contract
@@ -168,7 +166,6 @@ abstract contract BaseCoin is ICoin, ContractVersionBase, ERC20PermitUpgradeable
168
166
  __ERC20Permit_init("");
169
167
 
170
168
  __MultiOwnable_init(owners_);
171
- __ReentrancyGuard_init();
172
169
 
173
170
  // Set mutable state
174
171
  _setPayoutRecipient(payoutRecipient_);
@@ -181,14 +178,9 @@ abstract contract BaseCoin is ICoin, ContractVersionBase, ERC20PermitUpgradeable
181
178
  _handleInitialDistribution();
182
179
  }
183
180
 
184
- /// @dev The initial mint and distribution of the coin supply.
185
- function _handleInitialDistribution() internal virtual {
186
- // Mint the total supply to the coin contract
187
- _mint(address(this), CoinConstants.MAX_TOTAL_SUPPLY);
188
-
189
- // Distribute the creator launch reward to the payout recipient
190
- _transfer(address(this), payoutRecipient, CoinConstants.CREATOR_LAUNCH_REWARD);
191
- }
181
+ /// @notice The initial mint and distribution of the coin supply.
182
+ /// @dev This function must be overridden by the child contract.
183
+ function _handleInitialDistribution() internal virtual;
192
184
 
193
185
  /// @notice Returns the name of the token for EIP712 domain.
194
186
  /// @notice This can change when the user changes the "name" of the token.
@@ -10,12 +10,11 @@ pragma solidity ^0.8.23;
10
10
  import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
11
11
  import {BaseCoin} from "./BaseCoin.sol";
12
12
  import {CoinConstants} from "./libs/CoinConstants.sol";
13
- import {MarketConstants} from "./libs/MarketConstants.sol";
14
13
  import {IHasCoinType} from "./interfaces/ICoin.sol";
15
14
 
16
15
  /**
17
16
  * @title ContentCoin
18
- * @notice Content coin implementation that uses creator coins as backing currency
17
+ * @notice Content coin implementation that typically uses creator coins as backing currency, but can be set to any currency as the backing currency
19
18
  * @dev Inherits from BaseCoin and implements content-specific distribution logic
20
19
  */
21
20
  contract ContentCoin is BaseCoin {
@@ -39,14 +38,14 @@ contract ContentCoin is BaseCoin {
39
38
  _mint(address(this), CoinConstants.MAX_TOTAL_SUPPLY);
40
39
 
41
40
  // Distribute the creator launch reward to the payout recipient
42
- _transfer(address(this), payoutRecipient, CoinConstants.CREATOR_LAUNCH_REWARD);
41
+ _transfer(address(this), payoutRecipient, CoinConstants.CONTENT_COIN_INITIAL_CREATOR_SUPPLY);
43
42
 
44
43
  // Transfer the market supply to the hook for liquidity
45
44
  _transfer(address(this), address(poolKey.hooks), balanceOf(address(this)));
46
45
  }
47
46
 
48
47
  function totalSupplyForPositions() external pure override returns (uint256) {
49
- return MarketConstants.CONTENT_COIN_MARKET_SUPPLY;
48
+ return CoinConstants.CONTENT_COIN_MARKET_SUPPLY;
50
49
  }
51
50
 
52
51
  function coinType() external pure override returns (IHasCoinType.CoinType) {
@@ -8,12 +8,11 @@
8
8
  pragma solidity ^0.8.28;
9
9
 
10
10
  import {ICreatorCoin} from "./interfaces/ICreatorCoin.sol";
11
- import {CreatorCoinConstants} from "./libs/CreatorCoinConstants.sol";
11
+ import {CoinConstants} from "./libs/CoinConstants.sol";
12
12
  import {IHooks, PoolConfiguration, PoolKey, ICoin} from "./interfaces/ICoin.sol";
13
13
  import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
14
14
  import {BaseCoin} from "./BaseCoin.sol";
15
15
  import {IHasCoinType} from "./interfaces/ICoin.sol";
16
- import {MarketConstants} from "./libs/MarketConstants.sol";
17
16
 
18
17
  contract CreatorCoin is ICreatorCoin, BaseCoin {
19
18
  uint256 public vestingStartTime;
@@ -28,7 +27,7 @@ contract CreatorCoin is ICreatorCoin, BaseCoin {
28
27
  ) BaseCoin(protocolRewardRecipient_, protocolRewards_, poolManager_, airlock_) initializer {}
29
28
 
30
29
  function totalSupplyForPositions() external pure override returns (uint256) {
31
- return MarketConstants.CREATOR_COIN_MARKET_SUPPLY;
30
+ return CoinConstants.CREATOR_COIN_MARKET_SUPPLY;
32
31
  }
33
32
 
34
33
  function coinType() external pure override returns (IHasCoinType.CoinType) {
@@ -47,7 +46,7 @@ contract CreatorCoin is ICreatorCoin, BaseCoin {
47
46
  uint160 sqrtPriceX96,
48
47
  PoolConfiguration memory poolConfiguration_
49
48
  ) public override(BaseCoin, ICoin) {
50
- require(currency_ == CreatorCoinConstants.CURRENCY, InvalidCurrency());
49
+ require(currency_ == CoinConstants.CREATOR_COIN_CURRENCY, InvalidCurrency());
51
50
 
52
51
  super.initialize({
53
52
  payoutRecipient_: payoutRecipient_,
@@ -63,19 +62,18 @@ contract CreatorCoin is ICreatorCoin, BaseCoin {
63
62
  });
64
63
 
65
64
  vestingStartTime = block.timestamp;
66
- vestingEndTime = block.timestamp + CreatorCoinConstants.CREATOR_VESTING_DURATION;
65
+ vestingEndTime = block.timestamp + CoinConstants.CREATOR_VESTING_DURATION;
67
66
  }
68
67
 
69
68
  /// @dev The initial mint and distribution of the coin supply.
70
69
  /// Implements creator coin specific distribution: 500M to liquidity pool, 500M vested to creator.
71
70
  function _handleInitialDistribution() internal override {
72
- _mint(address(this), CreatorCoinConstants.TOTAL_SUPPLY);
71
+ _mint(address(this), CoinConstants.TOTAL_SUPPLY);
73
72
 
74
- _transfer(address(this), address(poolKey.hooks), MarketConstants.CREATOR_COIN_MARKET_SUPPLY);
73
+ _transfer(address(this), address(poolKey.hooks), CoinConstants.CREATOR_COIN_MARKET_SUPPLY);
75
74
  }
76
75
 
77
76
  /// @notice Allows the creator payout recipient to claim vested tokens
78
- /// @dev Optimized for frequent calls from Uniswap V4 hooks
79
77
  /// @return claimAmount The amount of tokens claimed
80
78
  function claimVesting() external returns (uint256) {
81
79
  uint256 claimAmount = getClaimableAmount();
@@ -114,13 +112,13 @@ contract CreatorCoin is ICreatorCoin, BaseCoin {
114
112
 
115
113
  // After vesting ends - fully vested
116
114
  if (timestamp >= vestingEndTime) {
117
- return CreatorCoinConstants.CREATOR_VESTING_SUPPLY;
115
+ return CoinConstants.CREATOR_COIN_CREATOR_VESTING_SUPPLY;
118
116
  }
119
117
 
120
118
  // Linear vesting: (elapsed_time / total_duration) * total_amount
121
119
  uint256 elapsedTime = timestamp - vestingStartTime;
122
120
 
123
121
  // Multiply first to avoid precision loss
124
- return (CreatorCoinConstants.CREATOR_VESTING_SUPPLY * elapsedTime) / CreatorCoinConstants.CREATOR_VESTING_DURATION;
122
+ return (CoinConstants.CREATOR_COIN_CREATOR_VESTING_SUPPLY * elapsedTime) / CoinConstants.CREATOR_VESTING_DURATION;
125
123
  }
126
124
  }