@whetstone-research/doppler-sdk 1.0.25 → 1.0.27

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.
@@ -124,6 +124,33 @@ var GENERATED_DOPPLER_DEPLOYMENTS = {
124
124
  NoOpGovernanceFactory: "0xddAE8B3eD08184682f7Bc32B74d943cEEfEab638",
125
125
  NoOpMigrator: "0x233A71A7bB928b1357A1Ebf454298320989Ca5B5"
126
126
  },
127
+ "4663": {
128
+ Airlock: "0xeb7C034704eF8Dcd2D32324c1545f62fB4aD0862",
129
+ Bundler: "0xEdE0B5fae363232c396724Fa962250Fa197cc5a1",
130
+ DN404Factory: "0x37A9Fa204a4d3A429FDED7e3469ab076C854Bc9d",
131
+ DopplerCreateXDeployer: "0x103004E50Bed65DFBa30dD9c264B6BdF5e529B83",
132
+ DopplerDeployer: "0x4389AD34938B14F25cff7ED983c53f5a42A2573f",
133
+ DopplerERC20V1: "0x3Be8B97Fd0e713B5aBE0649Fa830223B6B4BC599",
134
+ DopplerERC20V1Factory: "0x1B37D3a72082029c44B35B604Ea473617580b69a",
135
+ DopplerHookInitializer: "0x4e3468951D49f2EEa976eD0D6e75fFCb44a9a544",
136
+ DopplerHookMigrator: "0x7BF319d8e969f7596B1Bc171Da9ce322f67Ae0c4",
137
+ DopplerLensQuoter: "0xf4c22465532f64777FfcD7770831AEca38F35c04",
138
+ GovernanceFactory: "0xDeb0447DAE3EB177c4dbA8bBCCCa25c8F273B7ef",
139
+ LaunchpadGovernanceFactory: "0xdb036746D65DD52126b1915f1AdF555e6C5237Cf",
140
+ LockableUniswapV3Initializer: "0xde8886A0019Ea060B8378Ee37b8A23b8117F29A3",
141
+ NoOpGovernanceFactory: "0x85f37f74Ef2478A770318bc810177a9835911aD7",
142
+ NoOpMigrator: "0xba2F330EDb16cD8056f5988d8CE19BbC63475A0e",
143
+ Quoter: "0x7232686FC954f12079cadFC5e9F755a9fEAeb3Ca",
144
+ RehypeDopplerHookInitializer: "0x6f02324d20CC679d0E585290CAa6b16baCbC0F77",
145
+ RehypeDopplerHookMigrator: "0x1a0f286bB7f5967AE89c13D3425D5ce04C34cd27",
146
+ StreamableFeesLockerV2: "0x7B6147AC3F615bdb764e7EbD5f517dac1AD163B8",
147
+ SwapRestrictorDopplerHook: "0xC16c826F75338A5Ea626f94f8992191B4ce5abA2",
148
+ TimelockFactory: "0x6076fdDFCaC0dD980e0350dfF5239feC3f86C578",
149
+ TopUpDistributor: "0x46adee7595d48b1Ec53090e9bc78e1E69Fa0eF06",
150
+ UniswapV2Locker: "0x63f6Efe03F25A8C6650b38d05C5a454051d642a5",
151
+ UniswapV2MigratorSplit: "0xB05046cEa797c993FB5b583098B1c4682e9Da333",
152
+ UniswapV4Initializer: "0x6cce158B6D1747617fc218592B4D60B239B957ea"
153
+ },
127
154
  "4801": {
128
155
  Airlock: "0x5F3bA43D44375286296Cb85F1EA2EBfa25dde731",
129
156
  GovernanceFactory: "0x136191B46478cAB023cbC01a36160C4Aad81677a",
@@ -227,6 +254,8 @@ var GENERATED_DOPPLER_DEPLOYMENTS = {
227
254
  CloneERC20VotesFactory: "0x9a497a9fB78e49984B9d260abA1F4AD6321D4D92",
228
255
  DecayMulticurveInitializer: "0xD59cE43E53D69F190E15d9822Fb4540dCcc91178",
229
256
  DecayMulticurveInitializerHook: "0xbB7784A4d481184283Ed89619A3e3ed143e1Adc0",
257
+ DN404Factory: "0x98b0Aa2e0f134dbB3eb157b5646D387E6D55243a",
258
+ DopplerCreateXDeployer: "0x0000000000f13Ab5b685F03A412A26719aB6bE60",
230
259
  DopplerDeployer: "0xb35469ee64A87Afd19B31615094fE3962d73e421",
231
260
  DopplerERC20V1: "0xDB7B520bb5C3a2C5d4871198081911359f93be87",
232
261
  DopplerERC20V1Factory: "0x89C261C05B5F9b6BcBA07C199b8DeE7cFaD45292",
@@ -375,23 +404,23 @@ var DEFAULT_OPENING_DOPPLER_NUM_PD_SLUGS = DEFAULT_PD_SLUGS;
375
404
  var DEFAULT_OPENING_DOPPLER_FEE = FEE_TIERS.HIGH;
376
405
  var DEFAULT_OPENING_DOPPLER_TICK_SPACING = DOPPLER_MAX_TICK_SPACING;
377
406
  var DEFAULT_MULTICURVE_LOWER_TICKS = [
378
- -202100,
379
- -183100,
380
- -167e3
407
+ -887200,
408
+ -222200,
409
+ -176200
381
410
  ];
382
411
  var DEFAULT_MULTICURVE_UPPER_TICKS = [
383
- -188200,
384
- -172100,
385
- -156e3
412
+ -142200,
413
+ -116300,
414
+ -84100
386
415
  ];
387
416
  var DEFAULT_MULTICURVE_NUM_POSITIONS = [11, 11, 11];
388
417
  var DEFAULT_MULTICURVE_MAX_SUPPLY_SHARES = [
389
- viem.parseEther("0.05"),
390
- // 5% for LOW tier
391
- viem.parseEther("0.125"),
392
- // 12.5% for MEDIUM tier
393
- viem.parseEther("0.2")
394
- // 20% for HIGH tier
418
+ viem.parseEther("0.5"),
419
+ // 50% for LOW tier
420
+ viem.parseEther("0.25"),
421
+ // 25% for MEDIUM tier
422
+ viem.parseEther("0.24")
423
+ // 24% for HIGH tier
395
424
  ];
396
425
  var BASIS_POINTS = 1e4;
397
426
  var FLAG_MASK = BigInt(16383);
@@ -435,6 +464,7 @@ var CHAIN_IDS = {
435
464
  BASE: 8453,
436
465
  BASE_SEPOLIA: 84532,
437
466
  INK: 57073,
467
+ ROBINHOOD: 4663,
438
468
  UNICHAIN: 130,
439
469
  UNICHAIN_SEPOLIA: 1301,
440
470
  MONAD_TESTNET: 10143,
@@ -706,6 +736,55 @@ var ADDRESSES = {
706
736
  weth: "0x4200000000000000000000000000000000000006",
707
737
  uniswapV4Quoter: "0x3972c00f7ed4885e145823eb7c655375d275a1c5"
708
738
  },
739
+ [CHAIN_IDS.ROBINHOOD]: {
740
+ airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].Airlock,
741
+ tokenFactory: ZERO_ADDRESS,
742
+ dopplerERC20V1Factory: getGeneratedAddress(
743
+ CHAIN_IDS.ROBINHOOD,
744
+ "DopplerERC20V1Factory"
745
+ ),
746
+ dopplerERC20V1Implementation: getGeneratedAddress(
747
+ CHAIN_IDS.ROBINHOOD,
748
+ "DopplerERC20V1"
749
+ ),
750
+ doppler404Factory: getGeneratedAddress(CHAIN_IDS.ROBINHOOD, "DN404Factory"),
751
+ v3Initializer: ZERO_ADDRESS,
752
+ v3Quoter: "0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",
753
+ lockableV3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].LockableUniswapV3Initializer,
754
+ v4Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].UniswapV4Initializer,
755
+ dopplerHookInitializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerHookInitializer,
756
+ rehypeDopplerHookInitializer: getRehypeDopplerHookInitializerAddress(
757
+ CHAIN_IDS.ROBINHOOD
758
+ ),
759
+ rehypeDopplerHook: getRehypeDopplerHookInitializerAddress(
760
+ CHAIN_IDS.ROBINHOOD
761
+ ),
762
+ dopplerLens: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerLensQuoter,
763
+ dopplerDeployer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerDeployer,
764
+ poolManager: "0x8366a39cc670b4001a1121b8f6a443a643e40951",
765
+ v2Migrator: ZERO_ADDRESS,
766
+ v2MigratorSplit: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].UniswapV2MigratorSplit,
767
+ v4Migrator: ZERO_ADDRESS,
768
+ dopplerHookMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].DopplerHookMigrator,
769
+ rehypeDopplerHookMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].RehypeDopplerHookMigrator,
770
+ noOpMigrator: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].NoOpMigrator,
771
+ governanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].GovernanceFactory,
772
+ noOpGovernanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].NoOpGovernanceFactory,
773
+ launchpadGovernanceFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].LaunchpadGovernanceFactory,
774
+ streamableFeesLocker: ZERO_ADDRESS,
775
+ streamableFeesLockerV2: getGeneratedAddress(
776
+ CHAIN_IDS.ROBINHOOD,
777
+ "StreamableFeesLockerV2"
778
+ ),
779
+ topUpDistributor: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].TopUpDistributor,
780
+ universalRouter: "0x8876789976decbfcbbbe364623c63652db8c0904",
781
+ permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
782
+ bundler: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ROBINHOOD].Bundler,
783
+ weth: "0x0bd7d308f8e1639fab988df18a8011f41eacad73",
784
+ uniswapV2Factory: "0x8bceaa40b9acdfaedf85adf4ff01f5ad6517937f",
785
+ uniswapV3Factory: "0x1f7d7550b1b028f7571e69a784071f0205fd2efa",
786
+ uniswapV4Quoter: "0x8dc178efb8111bb0973dd9d722ebeff267c98f94"
787
+ },
709
788
  [CHAIN_IDS.UNICHAIN]: {
710
789
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].Airlock,
711
790
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].TokenFactory,
@@ -6598,6 +6677,92 @@ function getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1) {
6598
6677
  return amount1 * Q96 / diff;
6599
6678
  }
6600
6679
 
6680
+ // src/evm/utils/multicurveLiquidity.ts
6681
+ var MAX_UINT128 = (1n << 128n) - 1n;
6682
+ function getMaxLiquiditySafeMulticurveTickUpper(params) {
6683
+ if (params.tickUpper <= params.tickLower) {
6684
+ throw new Error(
6685
+ `Unable to find a uint128-safe multicurve max tick below ${params.tickUpper}`
6686
+ );
6687
+ }
6688
+ if (isCanonicalCurveLiquiditySafe(params)) return params.tickUpper;
6689
+ for (let candidate = params.tickUpper - params.tickSpacing; candidate > params.tickLower; candidate -= params.tickSpacing) {
6690
+ if (isCanonicalCurveLiquiditySafe({ ...params, tickUpper: candidate })) {
6691
+ return candidate;
6692
+ }
6693
+ }
6694
+ throw new Error(
6695
+ `Unable to find a uint128-safe multicurve max tick below ${params.tickUpper}`
6696
+ );
6697
+ }
6698
+ function isCanonicalCurveLiquiditySafe(params) {
6699
+ return isAdjustedCurveLiquiditySafe({
6700
+ ...params,
6701
+ isToken0: true
6702
+ }) && isAdjustedCurveLiquiditySafe({
6703
+ ...params,
6704
+ tickLower: -params.tickUpper,
6705
+ tickUpper: -params.tickLower,
6706
+ isToken0: false
6707
+ });
6708
+ }
6709
+ function isAdjustedCurveLiquiditySafe(params) {
6710
+ if (params.numPositions <= 0 || params.tickSpacing <= 0) {
6711
+ throw new Error("Multicurve positions and tick spacing must be positive");
6712
+ }
6713
+ const amountPerPosition = params.curveSupply / BigInt(params.numPositions);
6714
+ if (amountPerPosition <= 1n) return true;
6715
+ const amount = amountPerPosition - 1n;
6716
+ const maxLiquidityPerTick = getMaxLiquidityPerTick(params.tickSpacing);
6717
+ const liquidityByTick = /* @__PURE__ */ new Map();
6718
+ const farTick = params.isToken0 ? params.tickUpper : params.tickLower;
6719
+ const closeTick = params.isToken0 ? params.tickLower : params.tickUpper;
6720
+ const spread = params.tickUpper - params.tickLower;
6721
+ const farSqrtPriceX96 = getSqrtRatioAtTick(farTick);
6722
+ for (let i = 0; i < params.numPositions; i++) {
6723
+ const tickDelta = Number(
6724
+ BigInt(i) * BigInt(spread) / BigInt(params.numPositions)
6725
+ );
6726
+ const unalignedTick = params.isToken0 ? closeTick + tickDelta : closeTick - tickDelta;
6727
+ const startingTick = alignMulticurveTick(
6728
+ params.isToken0,
6729
+ unalignedTick,
6730
+ params.tickSpacing
6731
+ );
6732
+ if (startingTick === farTick) continue;
6733
+ const startingSqrtPriceX96 = getSqrtRatioAtTick(startingTick);
6734
+ const liquidity = params.isToken0 ? getLiquidityForAmount0(startingSqrtPriceX96, farSqrtPriceX96, amount) : getLiquidityForAmount1(farSqrtPriceX96, startingSqrtPriceX96, amount);
6735
+ if (liquidity > maxLiquidityPerTick) return false;
6736
+ const tickA = Math.min(farTick, startingTick);
6737
+ const tickB = Math.max(farTick, startingTick);
6738
+ if (!addTickLiquidity(liquidityByTick, tickA, liquidity, maxLiquidityPerTick)) {
6739
+ return false;
6740
+ }
6741
+ if (!addTickLiquidity(liquidityByTick, tickB, liquidity, maxLiquidityPerTick)) {
6742
+ return false;
6743
+ }
6744
+ }
6745
+ return true;
6746
+ }
6747
+ function getMaxLiquidityPerTick(tickSpacing) {
6748
+ const minTick = Math.trunc(MIN_TICK / tickSpacing) * tickSpacing;
6749
+ const maxTick = Math.trunc(MAX_TICK / tickSpacing) * tickSpacing;
6750
+ const numTicks = BigInt((maxTick - minTick) / tickSpacing + 1);
6751
+ return MAX_UINT128 / numTicks;
6752
+ }
6753
+ function addTickLiquidity(liquidityByTick, tick, liquidity, maxLiquidityPerTick) {
6754
+ const updatedLiquidity = (liquidityByTick.get(tick) ?? 0n) + liquidity;
6755
+ if (updatedLiquidity > maxLiquidityPerTick) return false;
6756
+ liquidityByTick.set(tick, updatedLiquidity);
6757
+ return true;
6758
+ }
6759
+ function alignMulticurveTick(isToken0, tick, tickSpacing) {
6760
+ if (isToken0) {
6761
+ return tick < 0 ? Math.trunc((tick - tickSpacing + 1) / tickSpacing) * tickSpacing : Math.trunc(tick / tickSpacing) * tickSpacing;
6762
+ }
6763
+ return tick < 0 ? Math.trunc(tick / tickSpacing) * tickSpacing : Math.trunc((tick + tickSpacing - 1) / tickSpacing) * tickSpacing;
6764
+ }
6765
+
6601
6766
  // src/evm/utils/computeOptimalGamma.ts
6602
6767
  function computeOptimalGamma(startTick, endTick, duration, epochLength, tickSpacing) {
6603
6768
  const totalEpochs = duration / epochLength;
@@ -6633,6 +6798,23 @@ function isToken0Expected(numeraire) {
6633
6798
  }
6634
6799
  }
6635
6800
 
6801
+ // src/evm/utils/beneficiaries.ts
6802
+ function sortBeneficiaries(beneficiaries) {
6803
+ const sorted = [...beneficiaries].sort((a, b) => {
6804
+ const aAddr = a.beneficiary.toLowerCase();
6805
+ const bAddr = b.beneficiary.toLowerCase();
6806
+ return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
6807
+ });
6808
+ for (let i = 1; i < sorted.length; i++) {
6809
+ if (sorted[i].beneficiary.toLowerCase() === sorted[i - 1].beneficiary.toLowerCase()) {
6810
+ throw new Error(
6811
+ `Duplicate beneficiary address: ${sorted[i].beneficiary}. Each beneficiary address must be unique \u2014 the contract requires strictly ascending addresses and reverts with UnorderedBeneficiaries() otherwise. Merge the entries into a single beneficiary with the combined shares.`
6812
+ );
6813
+ }
6814
+ }
6815
+ return sorted;
6816
+ }
6817
+
6636
6818
  // src/evm/types.ts
6637
6819
  var NO_OP_ENABLED_CHAIN_IDS = [
6638
6820
  CHAIN_IDS.MAINNET,
@@ -6641,6 +6823,7 @@ var NO_OP_ENABLED_CHAIN_IDS = [
6641
6823
  CHAIN_IDS.BASE_SEPOLIA,
6642
6824
  CHAIN_IDS.UNICHAIN,
6643
6825
  CHAIN_IDS.UNICHAIN_SEPOLIA,
6826
+ CHAIN_IDS.ROBINHOOD,
6644
6827
  CHAIN_IDS.MONAD_TESTNET,
6645
6828
  CHAIN_IDS.MONAD_MAINNET
6646
6829
  ];
@@ -6651,6 +6834,7 @@ var LAUNCHPAD_ENABLED_CHAIN_IDS = [
6651
6834
  CHAIN_IDS.MAINNET,
6652
6835
  CHAIN_IDS.BASE,
6653
6836
  CHAIN_IDS.BASE_SEPOLIA,
6837
+ CHAIN_IDS.ROBINHOOD,
6654
6838
  CHAIN_IDS.MONAD_MAINNET
6655
6839
  ];
6656
6840
  function isLaunchpadEnabledChain(chainId) {
@@ -7235,7 +7419,7 @@ function buildCurvesFromPresets(params) {
7235
7419
  }
7236
7420
 
7237
7421
  // src/evm/entities/DopplerFactory.ts
7238
- var MAX_UINT128 = (1n << 128n) - 1n;
7422
+ var MAX_UINT1282 = (1n << 128n) - 1n;
7239
7423
  var MAX_PROCEEDS_SPLIT_SHARE = WAD / 2n;
7240
7424
  var DERC20_V1_MAX_PREMINT_WAD = WAD * 8n / 10n;
7241
7425
  var ONE_MILLION = 1000000n;
@@ -7931,11 +8115,7 @@ var DopplerFactory = class {
7931
8115
  const hasBeneficiaries = params.pool.beneficiaries && params.pool.beneficiaries.length > 0;
7932
8116
  let poolInitializerData;
7933
8117
  if (hasBeneficiaries) {
7934
- const sortedBeneficiaries = params.pool.beneficiaries.slice().sort((a, b) => {
7935
- const aAddr = a.beneficiary.toLowerCase();
7936
- const bAddr = b.beneficiary.toLowerCase();
7937
- return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
7938
- });
8118
+ const sortedBeneficiaries = sortBeneficiaries(params.pool.beneficiaries);
7939
8119
  poolInitializerData = viem.encodeAbiParameters(
7940
8120
  [
7941
8121
  {
@@ -8015,14 +8195,20 @@ var DopplerFactory = class {
8015
8195
  const poolInitializerAddress = (() => {
8016
8196
  if (hasBeneficiaries) {
8017
8197
  const lockableInitializer = params.modules?.lockableV3Initializer ?? addresses.lockableV3Initializer;
8018
- if (!lockableInitializer) {
8198
+ if (!lockableInitializer || lockableInitializer === ZERO_ADDRESS) {
8019
8199
  throw new Error(
8020
8200
  "Lockable V3 initializer address not configured on this chain. Required when using beneficiaries."
8021
8201
  );
8022
8202
  }
8023
8203
  return lockableInitializer;
8024
8204
  }
8025
- return params.modules?.v3Initializer ?? addresses.v3Initializer;
8205
+ const standardInitializer = params.modules?.v3Initializer ?? addresses.v3Initializer;
8206
+ if (!standardInitializer || standardInitializer === ZERO_ADDRESS) {
8207
+ throw new Error(
8208
+ "UniswapV3Initializer address not configured on this chain. Use beneficiaries for lockable V3 support, provide an override via builder.withV3Initializer(...), or use a chain with standard V3 initializer support."
8209
+ );
8210
+ }
8211
+ return standardInitializer;
8026
8212
  })();
8027
8213
  const liquidityMigratorAddress = this.getMigratorAddress(
8028
8214
  params.migration,
@@ -8437,6 +8623,11 @@ var DopplerFactory = class {
8437
8623
  addresses
8438
8624
  });
8439
8625
  const poolInitializerAddress = params.modules?.v4Initializer ?? addresses.v4Initializer;
8626
+ if (!poolInitializerAddress || poolInitializerAddress === ZERO_ADDRESS) {
8627
+ throw new Error(
8628
+ "UniswapV4Initializer address not configured on this chain. Provide an override via builder.withV4Initializer(...) or use a chain with dynamic auction support."
8629
+ );
8630
+ }
8440
8631
  const liquidityMigratorAddress = this.getMigratorAddress(
8441
8632
  params.migration,
8442
8633
  params.modules
@@ -9767,13 +9958,7 @@ var DopplerFactory = class {
9767
9958
  if (!streamableFees) {
9768
9959
  return "0x";
9769
9960
  }
9770
- const beneficiaryData = [...streamableFees.beneficiaries].sort(
9771
- (a, b) => {
9772
- const addrA = a.beneficiary.toLowerCase();
9773
- const addrB = b.beneficiary.toLowerCase();
9774
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9775
- }
9776
- );
9961
+ const beneficiaryData = sortBeneficiaries(streamableFees.beneficiaries);
9777
9962
  return viem.encodeAbiParameters(
9778
9963
  [
9779
9964
  { type: "uint24" },
@@ -9798,12 +9983,8 @@ var DopplerFactory = class {
9798
9983
  ]
9799
9984
  );
9800
9985
  case "uniswapV4Split": {
9801
- const beneficiaryData2 = [...config.streamableFees.beneficiaries].sort(
9802
- (a, b) => {
9803
- const addrA = a.beneficiary.toLowerCase();
9804
- const addrB = b.beneficiary.toLowerCase();
9805
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9806
- }
9986
+ const beneficiaryData2 = sortBeneficiaries(
9987
+ config.streamableFees.beneficiaries
9807
9988
  );
9808
9989
  const proceedsRecipient = config.proceedsSplit?.recipient ?? ZERO_ADDRESS;
9809
9990
  const proceedsShare = config.proceedsSplit?.share ?? 0n;
@@ -9839,12 +10020,8 @@ var DopplerFactory = class {
9839
10020
  "dopplerHook migration cannot set both hook and rehype config. Use exactly one hook mode."
9840
10021
  );
9841
10022
  }
9842
- const beneficiaries = [...dopplerHookConfig.beneficiaries].sort(
9843
- (a, b) => {
9844
- const addrA = a.beneficiary.toLowerCase();
9845
- const addrB = b.beneficiary.toLowerCase();
9846
- return addrA < addrB ? -1 : addrA > addrB ? 1 : 0;
9847
- }
10023
+ const beneficiaries = sortBeneficiaries(
10024
+ dopplerHookConfig.beneficiaries
9848
10025
  );
9849
10026
  let dopplerHookAddress = ZERO_ADDRESS;
9850
10027
  let onInitializationCalldata = "0x";
@@ -10247,15 +10424,12 @@ var DopplerFactory = class {
10247
10424
  }
10248
10425
  const normalizedCurves = this.normalizeMulticurveCurves(
10249
10426
  params.pool.curves,
10250
- params.pool.tickSpacing
10427
+ params.pool.tickSpacing,
10428
+ params.sale.numTokensToSell
10251
10429
  );
10252
10430
  const addresses = getAddresses(this.chainId);
10253
- const sortedBeneficiaries = (params.pool.beneficiaries ?? []).slice().sort(
10254
- (a, b) => {
10255
- const aAddr = a.beneficiary.toLowerCase();
10256
- const bAddr = b.beneficiary.toLowerCase();
10257
- return aAddr < bAddr ? -1 : aAddr > bAddr ? 1 : 0;
10258
- }
10431
+ const sortedBeneficiaries = sortBeneficiaries(
10432
+ params.pool.beneficiaries ?? []
10259
10433
  );
10260
10434
  const initializerMode = this.resolveMulticurveInitializerMode(params);
10261
10435
  const useScheduledInitializer = initializerMode.type === "scheduled";
@@ -10730,7 +10904,7 @@ var DopplerFactory = class {
10730
10904
  /**
10731
10905
  * Normalize user-provided multicurve positions and ensure they satisfy SDK constraints
10732
10906
  */
10733
- normalizeMulticurveCurves(curves, tickSpacing) {
10907
+ normalizeMulticurveCurves(curves, tickSpacing, numTokensToSell) {
10734
10908
  if (tickSpacing <= 0) {
10735
10909
  throw new Error("Tick spacing must be positive");
10736
10910
  }
@@ -10777,25 +10951,19 @@ var DopplerFactory = class {
10777
10951
  if (fallbackTickLower === void 0) {
10778
10952
  throw new Error("Unable to determine fallback multicurve tick range");
10779
10953
  }
10780
- const fallbackTickUpper = this.roundMaxTickDown(tickSpacing);
10781
- if (fallbackTickLower >= fallbackTickUpper) {
10782
- const adjustedLower = fallbackTickUpper - tickSpacing;
10783
- if (adjustedLower < fallbackTickLower) {
10784
- return sanitizedCurves;
10785
- }
10786
- const fallbackCurve2 = {
10787
- tickLower: adjustedLower,
10788
- tickUpper: fallbackTickUpper,
10789
- numPositions: sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1,
10790
- shares: missingShare
10791
- };
10792
- return [...sanitizedCurves, fallbackCurve2];
10793
- }
10954
+ const fallbackNumPositions = sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1;
10955
+ const fallbackTickUpper = getMaxLiquiditySafeMulticurveTickUpper({
10956
+ tickLower: fallbackTickLower,
10957
+ tickUpper: this.roundMaxTickDown(tickSpacing),
10958
+ tickSpacing,
10959
+ numPositions: fallbackNumPositions,
10960
+ curveSupply: numTokensToSell * missingShare / WAD
10961
+ });
10794
10962
  const fallbackCurve = {
10795
10963
  // Extend from the most positive user tick out to the maximum supported tick bucket
10796
10964
  tickLower: fallbackTickLower,
10797
10965
  tickUpper: fallbackTickUpper,
10798
- numPositions: sanitizedCurves[sanitizedCurves.length - 1]?.numPositions ?? 1,
10966
+ numPositions: fallbackNumPositions,
10799
10967
  shares: missingShare
10800
10968
  };
10801
10969
  return [...sanitizedCurves, fallbackCurve];
@@ -11315,8 +11483,15 @@ var DopplerFactory = class {
11315
11483
  getMigratorAddress(config, overrides) {
11316
11484
  const addresses = getAddresses(this.chainId);
11317
11485
  switch (config.type) {
11318
- case "uniswapV2":
11319
- return overrides?.v2Migrator ?? addresses.v2Migrator;
11486
+ case "uniswapV2": {
11487
+ const v2Address = overrides?.v2Migrator ?? addresses.v2Migrator;
11488
+ if (!v2Address || v2Address === ZERO_ADDRESS) {
11489
+ throw new Error(
11490
+ "UniswapV2Migrator not deployed on this chain. Use uniswapV2Split migration or provide override via modules.v2Migrator."
11491
+ );
11492
+ }
11493
+ return v2Address;
11494
+ }
11320
11495
  case "uniswapV2Split": {
11321
11496
  const v2SplitAddress = overrides?.v2MigratorSplit ?? addresses.v2MigratorSplit;
11322
11497
  if (!v2SplitAddress || v2SplitAddress === ZERO_ADDRESS) {
@@ -11328,7 +11503,7 @@ var DopplerFactory = class {
11328
11503
  }
11329
11504
  case "uniswapV4": {
11330
11505
  const v4Address = overrides?.v4Migrator ?? addresses.v4Migrator;
11331
- if (v4Address === "0x0000000000000000000000000000000000000000") {
11506
+ if (!v4Address || v4Address === ZERO_ADDRESS) {
11332
11507
  throw new Error(
11333
11508
  "UniswapV4Migrator not deployed on this chain. Use uniswapV2 migration or provide override via modules.v4Migrator."
11334
11509
  );
@@ -11494,7 +11669,7 @@ var DopplerFactory = class {
11494
11669
  if (!allowZero && value === 0n) {
11495
11670
  throw new Error(`${paramName} must be greater than zero`);
11496
11671
  }
11497
- if (value > MAX_UINT128) {
11672
+ if (value > MAX_UINT1282) {
11498
11673
  throw new Error(`${paramName} exceeds uint128 range`);
11499
11674
  }
11500
11675
  }
@@ -18491,9 +18666,16 @@ var MulticurveBuilder = class _MulticurveBuilder {
18491
18666
  tokenDecimals: config.tokenDecimals ?? 18,
18492
18667
  numeraireDecimals: config.numeraireDecimals ?? 18
18493
18668
  });
18669
+ const curveSupply = this.sale.numTokensToSell * curve.shares / WAD;
18670
+ const tickUpper = curve.marketCap.end === "max" ? getMaxLiquiditySafeMulticurveTickUpper({
18671
+ ...curveTicks,
18672
+ tickSpacing,
18673
+ numPositions: curve.numPositions,
18674
+ curveSupply
18675
+ }) : curveTicks.tickUpper;
18494
18676
  curves.push({
18495
18677
  tickLower: curveTicks.tickLower,
18496
- tickUpper: curveTicks.tickUpper,
18678
+ tickUpper,
18497
18679
  numPositions: curve.numPositions,
18498
18680
  shares: curve.shares
18499
18681
  });
@@ -18554,7 +18736,7 @@ var MulticurveBuilder = class _MulticurveBuilder {
18554
18736
  }
18555
18737
  dopplerHook = { ...dopplerHook, farTick };
18556
18738
  }
18557
- const initializer = this.initializer ?? (dopplerHook ? { type: "rehype", config: dopplerHook } : this.schedule ? { type: "scheduled", startTime: this.schedule.startTime } : { type: "standard" });
18739
+ const initializer = this.initializer?.type === "rehype" && dopplerHook ? { type: "rehype", config: dopplerHook } : this.initializer ?? (dopplerHook ? { type: "rehype", config: dopplerHook } : this.schedule ? { type: "scheduled", startTime: this.schedule.startTime } : { type: "standard" });
18558
18740
  if (initializer.type === "scheduled" && dopplerHook) {
18559
18741
  throw new Error(
18560
18742
  "Cannot combine scheduled multicurve with rehype initializer. Use exactly one initializer mode."
@@ -19382,6 +19564,7 @@ exports.getAmount0ForLiquidity = getAmount0ForLiquidity;
19382
19564
  exports.getAmount1ForLiquidity = getAmount1ForLiquidity;
19383
19565
  exports.getLiquidityForAmount0 = getLiquidityForAmount0;
19384
19566
  exports.getLiquidityForAmount1 = getLiquidityForAmount1;
19567
+ exports.getMaxLiquiditySafeMulticurveTickUpper = getMaxLiquiditySafeMulticurveTickUpper;
19385
19568
  exports.getMaxTickRounded = getMaxTickRounded;
19386
19569
  exports.getNearestUsableTick = getNearestUsableTick;
19387
19570
  exports.getSqrtRatioAtTick = getSqrtRatioAtTick;
@@ -19410,6 +19593,7 @@ exports.ratioToTick = ratioToTick;
19410
19593
  exports.rehypeDopplerHookAbi = rehypeDopplerHookAbi;
19411
19594
  exports.rehypeDopplerHookMigratorAbi = rehypeDopplerHookMigratorAbi;
19412
19595
  exports.resolveGasEstimate = resolveGasEstimate;
19596
+ exports.sortBeneficiaries = sortBeneficiaries;
19413
19597
  exports.sqrtPriceX96ToPrice = sqrtPriceX96ToPrice;
19414
19598
  exports.streamableFeesLockerAbi = streamableFeesLockerAbi;
19415
19599
  exports.streamableFeesLockerV2Abi = streamableFeesLockerV2Abi;