@whetstone-research/doppler-sdk 1.0.4 → 1.0.6

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.
@@ -299,6 +299,14 @@ var ADDRESSES = {
299
299
  [CHAIN_IDS.MAINNET]: {
300
300
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MAINNET].Airlock,
301
301
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MAINNET].CloneERC20Factory,
302
+ derc20V2Factory: getGeneratedAddress(
303
+ CHAIN_IDS.MAINNET,
304
+ "CloneDERC20VotesV2Factory"
305
+ ),
306
+ derc20V2Implementation: getGeneratedAddress(
307
+ CHAIN_IDS.MAINNET,
308
+ "CloneDERC20VotesV2"
309
+ ),
302
310
  v3Initializer: ZERO_ADDRESS,
303
311
  v3Quoter: ZERO_ADDRESS,
304
312
  v4Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MAINNET].UniswapV4Initializer,
@@ -331,6 +339,14 @@ var ADDRESSES = {
331
339
  [CHAIN_IDS.ETH_SEPOLIA]: {
332
340
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ETH_SEPOLIA].Airlock,
333
341
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ETH_SEPOLIA].CloneERC20Factory,
342
+ derc20V2Factory: getGeneratedAddress(
343
+ CHAIN_IDS.ETH_SEPOLIA,
344
+ "CloneDERC20VotesV2Factory"
345
+ ),
346
+ derc20V2Implementation: getGeneratedAddress(
347
+ CHAIN_IDS.ETH_SEPOLIA,
348
+ "CloneDERC20VotesV2"
349
+ ),
334
350
  v3Initializer: ZERO_ADDRESS,
335
351
  v3Quoter: ZERO_ADDRESS,
336
352
  v4Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.ETH_SEPOLIA].UniswapV4Initializer,
@@ -361,6 +377,14 @@ var ADDRESSES = {
361
377
  [CHAIN_IDS.BASE]: {
362
378
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE].Airlock,
363
379
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE].TokenFactory80,
380
+ derc20V2Factory: getGeneratedAddress(
381
+ CHAIN_IDS.BASE,
382
+ "CloneDERC20VotesV2Factory"
383
+ ),
384
+ derc20V2Implementation: getGeneratedAddress(
385
+ CHAIN_IDS.BASE,
386
+ "CloneDERC20VotesV2"
387
+ ),
364
388
  v3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE].UniswapV3Initializer,
365
389
  v3Quoter: "0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",
366
390
  lockableV3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE].LockableUniswapV3Initializer,
@@ -399,6 +423,14 @@ var ADDRESSES = {
399
423
  [CHAIN_IDS.BASE_SEPOLIA]: {
400
424
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE_SEPOLIA].Airlock,
401
425
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE_SEPOLIA].TokenFactory80,
426
+ derc20V2Factory: getGeneratedAddress(
427
+ CHAIN_IDS.BASE_SEPOLIA,
428
+ "CloneDERC20VotesV2Factory"
429
+ ),
430
+ derc20V2Implementation: getGeneratedAddress(
431
+ CHAIN_IDS.BASE_SEPOLIA,
432
+ "CloneDERC20VotesV2"
433
+ ),
402
434
  doppler404Factory: "0xdd8cea2890f1b3498436f19ec8da8fecc2cb7af7",
403
435
  v3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.BASE_SEPOLIA].UniswapV3Initializer,
404
436
  v3Quoter: "0xC5290058841028F1614F3A6F0F5816cAd0df5E27",
@@ -441,6 +473,14 @@ var ADDRESSES = {
441
473
  [CHAIN_IDS.INK]: {
442
474
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.INK].Airlock,
443
475
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.INK].TokenFactory,
476
+ derc20V2Factory: getGeneratedAddress(
477
+ CHAIN_IDS.INK,
478
+ "CloneDERC20VotesV2Factory"
479
+ ),
480
+ derc20V2Implementation: getGeneratedAddress(
481
+ CHAIN_IDS.INK,
482
+ "CloneDERC20VotesV2"
483
+ ),
444
484
  v3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.INK].UniswapV3Initializer,
445
485
  v3Quoter: "0x96b572D2d880cf2Fa2563651BD23ADE6f5516652",
446
486
  v4Initializer: "0xC99b485499f78995C6F1640dbB1413c57f8BA684",
@@ -464,6 +504,14 @@ var ADDRESSES = {
464
504
  [CHAIN_IDS.UNICHAIN]: {
465
505
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].Airlock,
466
506
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].TokenFactory,
507
+ derc20V2Factory: getGeneratedAddress(
508
+ CHAIN_IDS.UNICHAIN,
509
+ "CloneDERC20VotesV2Factory"
510
+ ),
511
+ derc20V2Implementation: getGeneratedAddress(
512
+ CHAIN_IDS.UNICHAIN,
513
+ "CloneDERC20VotesV2"
514
+ ),
467
515
  v3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN].UniswapV3Initializer,
468
516
  v3Quoter: "0x385A5cf5F83e99f7BB2852b6A19C3538b9FA7658",
469
517
  v4Initializer: "0x2F2BAcd46d3F5c9EE052Ab392b73711dB89129DB",
@@ -487,6 +535,14 @@ var ADDRESSES = {
487
535
  [CHAIN_IDS.UNICHAIN_SEPOLIA]: {
488
536
  airlock: "0x651ab94B4777e2e4cdf96082d90C65bd947b73A4",
489
537
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.UNICHAIN_SEPOLIA].TokenFactory,
538
+ derc20V2Factory: getGeneratedAddress(
539
+ CHAIN_IDS.UNICHAIN_SEPOLIA,
540
+ "CloneDERC20VotesV2Factory"
541
+ ),
542
+ derc20V2Implementation: getGeneratedAddress(
543
+ CHAIN_IDS.UNICHAIN_SEPOLIA,
544
+ "CloneDERC20VotesV2"
545
+ ),
490
546
  v3Initializer: "0x7Fb9a622186B4660A5988C223ebb9d3690dD5007",
491
547
  v3Quoter: "0x6Dd37329A1A225a6Fca658265D460423DCafBF89",
492
548
  v4Initializer: "0x992375478626E67F4e639d3298EbCAaE51C3dF0b",
@@ -510,6 +566,14 @@ var ADDRESSES = {
510
566
  [CHAIN_IDS.MONAD_TESTNET]: {
511
567
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MONAD_TESTNET].Airlock,
512
568
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MONAD_TESTNET].TokenFactory80,
569
+ derc20V2Factory: getGeneratedAddress(
570
+ CHAIN_IDS.MONAD_TESTNET,
571
+ "CloneDERC20VotesV2Factory"
572
+ ),
573
+ derc20V2Implementation: getGeneratedAddress(
574
+ CHAIN_IDS.MONAD_TESTNET,
575
+ "CloneDERC20VotesV2"
576
+ ),
513
577
  v3Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MONAD_TESTNET].UniswapV3Initializer,
514
578
  v3Quoter: ZERO_ADDRESS,
515
579
  v4Initializer: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MONAD_TESTNET].UniswapV4Initializer,
@@ -534,6 +598,14 @@ var ADDRESSES = {
534
598
  [CHAIN_IDS.MONAD_MAINNET]: {
535
599
  airlock: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MONAD_MAINNET].Airlock,
536
600
  tokenFactory: GENERATED_DOPPLER_DEPLOYMENTS[CHAIN_IDS.MONAD_MAINNET].TokenFactory80,
601
+ derc20V2Factory: getGeneratedAddress(
602
+ CHAIN_IDS.MONAD_MAINNET,
603
+ "CloneDERC20VotesV2Factory"
604
+ ),
605
+ derc20V2Implementation: getGeneratedAddress(
606
+ CHAIN_IDS.MONAD_MAINNET,
607
+ "CloneDERC20VotesV2"
608
+ ),
537
609
  v3Initializer: ZERO_ADDRESS,
538
610
  v3Quoter: "0x66266174564170519409d8853898f065c719536b",
539
611
  v4Initializer: ZERO_ADDRESS,
@@ -1774,6 +1846,87 @@ var derc20Abi = [
1774
1846
  ]
1775
1847
  }
1776
1848
  ];
1849
+ var derc20V2Abi = [
1850
+ ...derc20Abi,
1851
+ {
1852
+ type: "function",
1853
+ name: "computeAvailableVestedAmount",
1854
+ inputs: [
1855
+ { name: "beneficiary", type: "address", internalType: "address" },
1856
+ { name: "scheduleId", type: "uint256", internalType: "uint256" }
1857
+ ],
1858
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1859
+ stateMutability: "view"
1860
+ },
1861
+ {
1862
+ type: "function",
1863
+ name: "getScheduleIdsOf",
1864
+ inputs: [{ name: "beneficiary", type: "address", internalType: "address" }],
1865
+ outputs: [{ name: "", type: "uint256[]", internalType: "uint256[]" }],
1866
+ stateMutability: "view"
1867
+ },
1868
+ {
1869
+ type: "function",
1870
+ name: "release",
1871
+ inputs: [{ name: "scheduleId", type: "uint256", internalType: "uint256" }],
1872
+ outputs: [],
1873
+ stateMutability: "nonpayable"
1874
+ },
1875
+ {
1876
+ type: "function",
1877
+ name: "releaseFor",
1878
+ inputs: [
1879
+ { name: "beneficiary", type: "address", internalType: "address" },
1880
+ { name: "scheduleId", type: "uint256", internalType: "uint256" }
1881
+ ],
1882
+ outputs: [],
1883
+ stateMutability: "nonpayable"
1884
+ },
1885
+ {
1886
+ type: "function",
1887
+ name: "releaseFor",
1888
+ inputs: [{ name: "beneficiary", type: "address", internalType: "address" }],
1889
+ outputs: [],
1890
+ stateMutability: "nonpayable"
1891
+ },
1892
+ {
1893
+ type: "function",
1894
+ name: "totalAllocatedOf",
1895
+ inputs: [{ name: "beneficiary", type: "address", internalType: "address" }],
1896
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1897
+ stateMutability: "view"
1898
+ },
1899
+ {
1900
+ type: "function",
1901
+ name: "vestingOf",
1902
+ inputs: [
1903
+ { name: "beneficiary", type: "address", internalType: "address" },
1904
+ { name: "scheduleId", type: "uint256", internalType: "uint256" }
1905
+ ],
1906
+ outputs: [
1907
+ { name: "totalAmount", type: "uint256", internalType: "uint256" },
1908
+ { name: "releasedAmount", type: "uint256", internalType: "uint256" }
1909
+ ],
1910
+ stateMutability: "view"
1911
+ },
1912
+ {
1913
+ type: "function",
1914
+ name: "vestingScheduleCount",
1915
+ inputs: [],
1916
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1917
+ stateMutability: "view"
1918
+ },
1919
+ {
1920
+ type: "function",
1921
+ name: "vestingSchedules",
1922
+ inputs: [{ name: "", type: "uint256", internalType: "uint256" }],
1923
+ outputs: [
1924
+ { name: "cliff", type: "uint64", internalType: "uint64" },
1925
+ { name: "duration", type: "uint64", internalType: "uint64" }
1926
+ ],
1927
+ stateMutability: "view"
1928
+ }
1929
+ ];
1777
1930
  var uniswapV4InitializerAbi = [
1778
1931
  {
1779
1932
  type: "function",
@@ -4319,6 +4472,22 @@ var STANDARD_TOKEN_DATA_ABI = [
4319
4472
  { type: "uint256[]" },
4320
4473
  { type: "string" }
4321
4474
  ];
4475
+ var STANDARD_TOKEN_V2_DATA_ABI = [
4476
+ { type: "string" },
4477
+ { type: "string" },
4478
+ { type: "uint256" },
4479
+ {
4480
+ type: "tuple[]",
4481
+ components: [
4482
+ { type: "uint64", name: "cliff" },
4483
+ { type: "uint64", name: "duration" }
4484
+ ]
4485
+ },
4486
+ { type: "address[]" },
4487
+ { type: "uint256[]" },
4488
+ { type: "uint256[]" },
4489
+ { type: "string" }
4490
+ ];
4322
4491
  var DOPPLER404_TOKEN_DATA_ABI = [
4323
4492
  { type: "string" },
4324
4493
  { type: "string" },
@@ -4376,6 +4545,13 @@ function computeCreate2AddressFast(buffer) {
4376
4545
  const hash = viem.keccak256(bytesToHex(buffer));
4377
4546
  return "0x" + hash.slice(-40).toLowerCase();
4378
4547
  }
4548
+ function computeSoladyCloneInitCodeHash(implementation) {
4549
+ return viem.keccak256(
4550
+ `0x602c3d8160093d39f33d3d3d3d363d3d37363d73${implementation.slice(
4551
+ 2
4552
+ )}5af43d3d93803e602a57fd5bf3`
4553
+ );
4554
+ }
4379
4555
  function buildTokenInitHash(params) {
4380
4556
  const {
4381
4557
  variant,
@@ -4384,7 +4560,8 @@ function buildTokenInitHash(params) {
4384
4560
  initialSupply,
4385
4561
  recipient,
4386
4562
  owner,
4387
- customBytecode
4563
+ customBytecode,
4564
+ v2Implementation
4388
4565
  } = params;
4389
4566
  if (variant === "doppler404") {
4390
4567
  const [name2, symbol2, baseURI] = viem.decodeAbiParameters(
@@ -4409,6 +4586,15 @@ function buildTokenInitHash(params) {
4409
4586
  )
4410
4587
  );
4411
4588
  }
4589
+ if (variant === "standard-v2") {
4590
+ viem.decodeAbiParameters(STANDARD_TOKEN_V2_DATA_ABI, tokenData);
4591
+ if (!v2Implementation) {
4592
+ throw new Error(
4593
+ "TokenAddressMiner: v2Implementation is required for standard-v2 tokens"
4594
+ );
4595
+ }
4596
+ return computeSoladyCloneInitCodeHash(v2Implementation);
4597
+ }
4412
4598
  const [
4413
4599
  name,
4414
4600
  symbol,
@@ -4489,7 +4675,8 @@ function mineTokenAddress(params) {
4489
4675
  initialSupply,
4490
4676
  recipient,
4491
4677
  owner,
4492
- customBytecode
4678
+ customBytecode,
4679
+ v2Implementation: params.v2Implementation
4493
4680
  });
4494
4681
  const hookConfig = hook ? {
4495
4682
  deployer: hook.deployer,
@@ -5094,6 +5281,8 @@ var erc20BalanceOfAbi = [
5094
5281
  }
5095
5282
  ];
5096
5283
  var TOKEN_FACTORY_80_ADDRESS2 = "0xf0b5141dd9096254b2ca624dff26024f46087229";
5284
+ var DERC20_V2_MIN_VESTING_DURATION = 24 * 60 * 60;
5285
+ var MAX_UINT64 = (1n << 64n) - 1n;
5097
5286
  var DopplerFactory = class {
5098
5287
  publicClient;
5099
5288
  walletClient;
@@ -5105,6 +5294,285 @@ var DopplerFactory = class {
5105
5294
  this.walletClient = walletClient;
5106
5295
  this.chainId = chainId;
5107
5296
  }
5297
+ hasCustomV2Schedules(vesting) {
5298
+ return (vesting?.schedules?.length ?? 0) > 0 || (vesting?.scheduleIds?.length ?? 0) > 0;
5299
+ }
5300
+ usesDerc20V2Vesting(vesting) {
5301
+ if (!vesting) {
5302
+ return false;
5303
+ }
5304
+ return this.hasCustomV2Schedules(vesting) || (vesting.cliffDuration ?? 0) > 0;
5305
+ }
5306
+ resolveVestingAllocations(args) {
5307
+ if (!args.vesting) {
5308
+ return { recipients: [], amounts: [] };
5309
+ }
5310
+ if (args.vesting.recipients && args.vesting.amounts) {
5311
+ return {
5312
+ recipients: args.vesting.recipients,
5313
+ amounts: args.vesting.amounts
5314
+ };
5315
+ }
5316
+ return {
5317
+ recipients: [args.userAddress],
5318
+ amounts: [args.sale.initialSupply - args.sale.numTokensToSell]
5319
+ };
5320
+ }
5321
+ normalizeV2ScheduleId(scheduleId, label) {
5322
+ if (!Number.isFinite(scheduleId) || !Number.isInteger(scheduleId)) {
5323
+ throw new Error(`${label} must be an integer`);
5324
+ }
5325
+ if (!Number.isSafeInteger(scheduleId)) {
5326
+ throw new Error(`${label} must be a safe integer`);
5327
+ }
5328
+ if (scheduleId < 0) {
5329
+ throw new Error(`${label} cannot be negative`);
5330
+ }
5331
+ return BigInt(scheduleId);
5332
+ }
5333
+ validateUint64LikeNumber(value, fieldPath, options = {}) {
5334
+ const { allowZero = true } = options;
5335
+ if (!Number.isFinite(value) || !Number.isInteger(value)) {
5336
+ throw new Error(`${fieldPath} must be a finite integer`);
5337
+ }
5338
+ if (!Number.isSafeInteger(value)) {
5339
+ throw new Error(`${fieldPath} must be a safe integer`);
5340
+ }
5341
+ if (value < 0) {
5342
+ throw new Error(`${fieldPath} cannot be negative`);
5343
+ }
5344
+ if (!allowZero && value === 0) {
5345
+ throw new Error(`${fieldPath} must be greater than zero`);
5346
+ }
5347
+ if (BigInt(value) > MAX_UINT64) {
5348
+ throw new Error(`${fieldPath} must fit in uint64`);
5349
+ }
5350
+ }
5351
+ resolveV2VestingSchedules(args) {
5352
+ if (!args.vesting) {
5353
+ return { schedules: [], scheduleIds: [] };
5354
+ }
5355
+ if (!this.hasCustomV2Schedules(args.vesting)) {
5356
+ return {
5357
+ schedules: [
5358
+ {
5359
+ cliff: BigInt(args.vesting.cliffDuration ?? 0),
5360
+ duration: BigInt(args.vesting.duration ?? 0)
5361
+ }
5362
+ ],
5363
+ scheduleIds: Array.from({ length: args.recipientCount }, () => 0n)
5364
+ };
5365
+ }
5366
+ const schedules = args.vesting.schedules?.map((schedule) => ({
5367
+ cliff: BigInt(schedule.cliffDuration ?? 0),
5368
+ duration: BigInt(schedule.duration ?? 0)
5369
+ })) ?? [];
5370
+ const explicitScheduleIds = args.vesting.scheduleIds;
5371
+ if (explicitScheduleIds && explicitScheduleIds.length > 0) {
5372
+ return {
5373
+ schedules,
5374
+ scheduleIds: explicitScheduleIds.map(
5375
+ (scheduleId, index) => this.normalizeV2ScheduleId(
5376
+ scheduleId,
5377
+ `Vesting scheduleIds[${index}]`
5378
+ )
5379
+ )
5380
+ };
5381
+ }
5382
+ if (schedules.length === 1) {
5383
+ return {
5384
+ schedules,
5385
+ scheduleIds: Array.from({ length: args.recipientCount }, () => 0n)
5386
+ };
5387
+ }
5388
+ if (schedules.length === args.recipientCount) {
5389
+ return {
5390
+ schedules,
5391
+ scheduleIds: schedules.map((_, index) => BigInt(index))
5392
+ };
5393
+ }
5394
+ throw new Error(
5395
+ "Vesting schedules must either contain exactly one shared schedule or one schedule per recipient when scheduleIds are omitted"
5396
+ );
5397
+ }
5398
+ resolveStandardTokenFactoryMode(args) {
5399
+ if (this.usesDerc20V2Vesting(args.vesting)) {
5400
+ return "v2";
5401
+ }
5402
+ const v2Factory = args.addresses.derc20V2Factory;
5403
+ if (v2Factory && args.tokenFactory.toLowerCase() === v2Factory.toLowerCase()) {
5404
+ return "v2";
5405
+ }
5406
+ return "legacy";
5407
+ }
5408
+ assertStandardTokenFactoryCompatibility(args) {
5409
+ if (this.isDoppler404Token(args.token) || !this.usesDerc20V2Vesting(args.vesting)) {
5410
+ return;
5411
+ }
5412
+ const v2Factory = args.addresses.derc20V2Factory;
5413
+ if (!v2Factory || v2Factory === ZERO_ADDRESS2) {
5414
+ throw new Error(
5415
+ "Cliff vesting requires the DERC20 V2 factory, but no V2 factory is configured for this chain."
5416
+ );
5417
+ }
5418
+ if (args.tokenFactory.toLowerCase() !== v2Factory.toLowerCase()) {
5419
+ throw new Error(
5420
+ "Cliff vesting requires the DERC20 V2 factory. Remove the tokenFactory override or point it at the chain DERC20 V2 factory."
5421
+ );
5422
+ }
5423
+ }
5424
+ buildStandardTokenFactoryData(args) {
5425
+ const { recipients, amounts } = this.resolveVestingAllocations(args);
5426
+ const yearlyMintRate = args.token.yearlyMintRate ?? DEFAULT_V4_YEARLY_MINT_RATE;
5427
+ const mode = this.resolveStandardTokenFactoryMode({
5428
+ vesting: args.vesting,
5429
+ tokenFactory: args.tokenFactory,
5430
+ addresses: args.addresses
5431
+ });
5432
+ if (mode === "v2") {
5433
+ const implementation = args.addresses.derc20V2Implementation;
5434
+ if (!implementation || implementation === ZERO_ADDRESS2) {
5435
+ throw new Error(
5436
+ "DERC20 V2 implementation address not configured for this chain."
5437
+ );
5438
+ }
5439
+ const { schedules, scheduleIds } = this.resolveV2VestingSchedules({
5440
+ vesting: args.vesting,
5441
+ recipientCount: recipients.length
5442
+ });
5443
+ return {
5444
+ kind: "v2",
5445
+ name: args.token.name,
5446
+ symbol: args.token.symbol,
5447
+ initialSupply: args.sale.initialSupply,
5448
+ airlock: args.airlock,
5449
+ yearlyMintRate,
5450
+ schedules,
5451
+ beneficiaries: recipients,
5452
+ scheduleIds,
5453
+ amounts,
5454
+ tokenURI: args.token.tokenURI,
5455
+ implementation
5456
+ };
5457
+ }
5458
+ return {
5459
+ kind: "legacy",
5460
+ name: args.token.name,
5461
+ symbol: args.token.symbol,
5462
+ initialSupply: args.sale.initialSupply,
5463
+ airlock: args.airlock,
5464
+ yearlyMintRate,
5465
+ vestingDuration: BigInt(args.vesting?.duration ?? 0),
5466
+ recipients,
5467
+ amounts,
5468
+ tokenURI: args.token.tokenURI
5469
+ };
5470
+ }
5471
+ encodeStandardTokenFactoryData(tokenFactoryData) {
5472
+ if (tokenFactoryData.kind === "v2") {
5473
+ return viem.encodeAbiParameters(
5474
+ [
5475
+ { type: "string" },
5476
+ { type: "string" },
5477
+ { type: "uint256" },
5478
+ {
5479
+ type: "tuple[]",
5480
+ components: [
5481
+ { type: "uint64", name: "cliff" },
5482
+ { type: "uint64", name: "duration" }
5483
+ ]
5484
+ },
5485
+ { type: "address[]" },
5486
+ { type: "uint256[]" },
5487
+ { type: "uint256[]" },
5488
+ { type: "string" }
5489
+ ],
5490
+ [
5491
+ tokenFactoryData.name,
5492
+ tokenFactoryData.symbol,
5493
+ tokenFactoryData.yearlyMintRate,
5494
+ tokenFactoryData.schedules.map((schedule) => ({
5495
+ cliff: schedule.cliff,
5496
+ duration: schedule.duration
5497
+ })),
5498
+ tokenFactoryData.beneficiaries,
5499
+ tokenFactoryData.scheduleIds,
5500
+ tokenFactoryData.amounts,
5501
+ tokenFactoryData.tokenURI
5502
+ ]
5503
+ );
5504
+ }
5505
+ return viem.encodeAbiParameters(
5506
+ [
5507
+ { type: "string" },
5508
+ { type: "string" },
5509
+ { type: "uint256" },
5510
+ { type: "uint256" },
5511
+ { type: "address[]" },
5512
+ { type: "uint256[]" },
5513
+ { type: "string" }
5514
+ ],
5515
+ [
5516
+ tokenFactoryData.name,
5517
+ tokenFactoryData.symbol,
5518
+ tokenFactoryData.yearlyMintRate,
5519
+ tokenFactoryData.vestingDuration,
5520
+ tokenFactoryData.recipients,
5521
+ tokenFactoryData.amounts,
5522
+ tokenFactoryData.tokenURI
5523
+ ]
5524
+ );
5525
+ }
5526
+ computeSoladyCloneInitCodeHash(implementation) {
5527
+ return viem.keccak256(
5528
+ `0x602c3d8160093d39f33d3d3d3d363d3d37363d73${implementation.slice(
5529
+ 2
5530
+ )}5af43d3d93803e602a57fd5bf3`
5531
+ );
5532
+ }
5533
+ computeStandardTokenInitHash(tokenFactoryData, tokenFactory) {
5534
+ if (tokenFactoryData.kind === "v2") {
5535
+ return this.computeSoladyCloneInitCodeHash(
5536
+ tokenFactoryData.implementation
5537
+ );
5538
+ }
5539
+ const initData = viem.encodeAbiParameters(
5540
+ [
5541
+ { type: "string" },
5542
+ { type: "string" },
5543
+ { type: "uint256" },
5544
+ { type: "address" },
5545
+ { type: "address" },
5546
+ { type: "uint256" },
5547
+ { type: "uint256" },
5548
+ { type: "address[]" },
5549
+ { type: "uint256[]" },
5550
+ { type: "string" }
5551
+ ],
5552
+ [
5553
+ tokenFactoryData.name,
5554
+ tokenFactoryData.symbol,
5555
+ tokenFactoryData.initialSupply,
5556
+ tokenFactoryData.airlock,
5557
+ tokenFactoryData.airlock,
5558
+ tokenFactoryData.yearlyMintRate,
5559
+ tokenFactoryData.vestingDuration,
5560
+ tokenFactoryData.recipients,
5561
+ tokenFactoryData.amounts,
5562
+ tokenFactoryData.tokenURI
5563
+ ]
5564
+ );
5565
+ const isTokenFactory802 = tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
5566
+ return viem.keccak256(
5567
+ viem.encodePacked(
5568
+ ["bytes", "bytes"],
5569
+ [
5570
+ isTokenFactory802 ? derc2080_default : derc20_default,
5571
+ initData
5572
+ ]
5573
+ )
5574
+ );
5575
+ }
5108
5576
  /**
5109
5577
  * Set a custom migration data encoder function
5110
5578
  * @param encoder Custom function to encode migration data
@@ -5189,6 +5657,18 @@ var DopplerFactory = class {
5189
5657
  numeraire: params.sale.numeraire,
5190
5658
  overrides: params.modules
5191
5659
  });
5660
+ const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
5661
+ if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
5662
+ throw new Error(
5663
+ "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
5664
+ );
5665
+ }
5666
+ this.assertStandardTokenFactoryCompatibility({
5667
+ token: params.token,
5668
+ vesting: params.vesting,
5669
+ tokenFactory: resolvedTokenFactory,
5670
+ addresses
5671
+ });
5192
5672
  let tokenFactoryData;
5193
5673
  if (this.isDoppler404Token(params.token)) {
5194
5674
  const token404 = params.token;
@@ -5204,41 +5684,17 @@ var DopplerFactory = class {
5204
5684
  [params.token.name, params.token.symbol, baseURI, unit]
5205
5685
  );
5206
5686
  } else {
5207
- const tokenStd = params.token;
5208
- const vestingDuration = params.vesting?.duration ?? BigInt(0);
5209
- const yearlyMintRate = tokenStd.yearlyMintRate ?? DEFAULT_V4_YEARLY_MINT_RATE;
5210
- let vestingRecipients = [];
5211
- let vestingAmounts = [];
5212
- if (params.vesting) {
5213
- if (params.vesting.recipients && params.vesting.amounts) {
5214
- vestingRecipients = params.vesting.recipients;
5215
- vestingAmounts = params.vesting.amounts;
5216
- } else {
5217
- vestingRecipients = [params.userAddress];
5218
- vestingAmounts = [
5219
- params.sale.initialSupply - params.sale.numTokensToSell
5220
- ];
5221
- }
5222
- }
5223
- tokenFactoryData = viem.encodeAbiParameters(
5224
- [
5225
- { type: "string" },
5226
- { type: "string" },
5227
- { type: "uint256" },
5228
- { type: "uint256" },
5229
- { type: "address[]" },
5230
- { type: "uint256[]" },
5231
- { type: "string" }
5232
- ],
5233
- [
5234
- tokenStd.name,
5235
- tokenStd.symbol,
5236
- yearlyMintRate,
5237
- BigInt(vestingDuration),
5238
- vestingRecipients,
5239
- vestingAmounts,
5240
- tokenStd.tokenURI
5241
- ]
5687
+ const standardTokenFactoryData = this.buildStandardTokenFactoryData({
5688
+ token: params.token,
5689
+ sale: params.sale,
5690
+ vesting: params.vesting,
5691
+ userAddress: params.userAddress,
5692
+ airlock: params.modules?.airlock ?? addresses.airlock,
5693
+ tokenFactory: resolvedTokenFactory,
5694
+ addresses
5695
+ });
5696
+ tokenFactoryData = this.encodeStandardTokenFactoryData(
5697
+ standardTokenFactoryData
5242
5698
  );
5243
5699
  }
5244
5700
  const governanceFactoryData = (() => {
@@ -5293,12 +5749,6 @@ var DopplerFactory = class {
5293
5749
  }
5294
5750
  return resolved;
5295
5751
  })();
5296
- const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : addresses.tokenFactory);
5297
- if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
5298
- throw new Error(
5299
- "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
5300
- );
5301
- }
5302
5752
  const baseCreateParams = {
5303
5753
  initialSupply: params.sale.initialSupply,
5304
5754
  numTokensToSell: params.sale.numTokensToSell,
@@ -5584,7 +6034,18 @@ var DopplerFactory = class {
5584
6034
  );
5585
6035
  }
5586
6036
  }
5587
- const vestingDuration = params.vesting?.duration ?? BigInt(0);
6037
+ const resolvedTokenFactoryDyn = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
6038
+ if (!resolvedTokenFactoryDyn || resolvedTokenFactoryDyn === ZERO_ADDRESS2) {
6039
+ throw new Error(
6040
+ "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
6041
+ );
6042
+ }
6043
+ this.assertStandardTokenFactoryCompatibility({
6044
+ token: params.token,
6045
+ vesting: params.vesting,
6046
+ tokenFactory: resolvedTokenFactoryDyn,
6047
+ addresses
6048
+ });
5588
6049
  const tokenFactoryData = this.isDoppler404Token(params.token) ? (() => {
5589
6050
  const t = params.token;
5590
6051
  return {
@@ -5593,39 +6054,15 @@ var DopplerFactory = class {
5593
6054
  baseURI: t.baseURI,
5594
6055
  unit: t.unit !== void 0 ? BigInt(t.unit) : 1000n
5595
6056
  };
5596
- })() : (() => {
5597
- const t = params.token;
5598
- let vestingRecipients = [];
5599
- let vestingAmounts = [];
5600
- if (params.vesting) {
5601
- if (params.vesting.recipients && params.vesting.amounts) {
5602
- vestingRecipients = params.vesting.recipients;
5603
- vestingAmounts = params.vesting.amounts;
5604
- } else {
5605
- vestingRecipients = [params.userAddress];
5606
- vestingAmounts = [
5607
- params.sale.initialSupply - params.sale.numTokensToSell
5608
- ];
5609
- }
5610
- }
5611
- return {
5612
- name: t.name,
5613
- symbol: t.symbol,
5614
- initialSupply: params.sale.initialSupply,
5615
- airlock: addresses.airlock,
5616
- yearlyMintRate: t.yearlyMintRate ?? DEFAULT_V4_YEARLY_MINT_RATE,
5617
- vestingDuration: BigInt(vestingDuration),
5618
- recipients: vestingRecipients,
5619
- amounts: vestingAmounts,
5620
- tokenURI: t.tokenURI
5621
- };
5622
- })();
5623
- const resolvedTokenFactoryDyn = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : addresses.tokenFactory);
5624
- if (!resolvedTokenFactoryDyn || resolvedTokenFactoryDyn === ZERO_ADDRESS2) {
5625
- throw new Error(
5626
- "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
5627
- );
5628
- }
6057
+ })() : this.buildStandardTokenFactoryData({
6058
+ token: params.token,
6059
+ sale: params.sale,
6060
+ vesting: params.vesting,
6061
+ userAddress: params.userAddress,
6062
+ airlock: params.modules?.airlock ?? addresses.airlock,
6063
+ tokenFactory: resolvedTokenFactoryDyn,
6064
+ addresses
6065
+ });
5629
6066
  const [
5630
6067
  salt,
5631
6068
  hookAddress,
@@ -5952,7 +6389,18 @@ var DopplerFactory = class {
5952
6389
  );
5953
6390
  }
5954
6391
  }
5955
- const vestingDuration = params.vesting?.duration ?? BigInt(0);
6392
+ const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
6393
+ if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
6394
+ throw new Error(
6395
+ "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
6396
+ );
6397
+ }
6398
+ this.assertStandardTokenFactoryCompatibility({
6399
+ token: params.token,
6400
+ vesting: params.vesting,
6401
+ tokenFactory: resolvedTokenFactory,
6402
+ addresses
6403
+ });
5956
6404
  const tokenFactoryData = this.isDoppler404Token(params.token) ? (() => {
5957
6405
  const t = params.token;
5958
6406
  return {
@@ -5961,39 +6409,15 @@ var DopplerFactory = class {
5961
6409
  baseURI: t.baseURI,
5962
6410
  unit: t.unit !== void 0 ? BigInt(t.unit) : 1000n
5963
6411
  };
5964
- })() : (() => {
5965
- const t = params.token;
5966
- let vestingRecipients = [];
5967
- let vestingAmounts = [];
5968
- if (params.vesting) {
5969
- if (params.vesting.recipients && params.vesting.amounts) {
5970
- vestingRecipients = params.vesting.recipients;
5971
- vestingAmounts = params.vesting.amounts;
5972
- } else {
5973
- vestingRecipients = [params.userAddress];
5974
- vestingAmounts = [
5975
- params.sale.initialSupply - params.sale.numTokensToSell
5976
- ];
5977
- }
5978
- }
5979
- return {
5980
- name: t.name,
5981
- symbol: t.symbol,
5982
- initialSupply: params.sale.initialSupply,
5983
- airlock: params.modules?.airlock ?? addresses.airlock,
5984
- yearlyMintRate: t.yearlyMintRate ?? DEFAULT_V4_YEARLY_MINT_RATE,
5985
- vestingDuration: BigInt(vestingDuration),
5986
- recipients: vestingRecipients,
5987
- amounts: vestingAmounts,
5988
- tokenURI: t.tokenURI
5989
- };
5990
- })();
5991
- const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : addresses.tokenFactory);
5992
- if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
5993
- throw new Error(
5994
- "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
5995
- );
5996
- }
6412
+ })() : this.buildStandardTokenFactoryData({
6413
+ token: params.token,
6414
+ sale: params.sale,
6415
+ vesting: params.vesting,
6416
+ userAddress: params.userAddress,
6417
+ airlock: params.modules?.airlock ?? addresses.airlock,
6418
+ tokenFactory: resolvedTokenFactory,
6419
+ addresses
6420
+ });
5997
6421
  const auctionTokens = params.sale.numTokensToSell * BigInt(params.openingAuction.shareToAuctionBps) / 10000n;
5998
6422
  if (auctionTokens <= 0n) {
5999
6423
  throw new Error("Opening auction token allocation rounds to zero");
@@ -6767,69 +7191,23 @@ var DopplerFactory = class {
6767
7191
  ["bytes", "bytes"],
6768
7192
  [openingAuction_default, initHashData]
6769
7193
  )
6770
- );
6771
- const encodedTokenFactoryData = params.tokenVariant === "doppler404" ? (() => {
6772
- const t = params.tokenFactoryData;
6773
- return viem.encodeAbiParameters(
6774
- [
6775
- { type: "string" },
6776
- { type: "string" },
6777
- { type: "string" },
6778
- { type: "uint256" }
6779
- ],
6780
- [t.name, t.symbol, t.baseURI, t.unit ?? 1000n]
6781
- );
6782
- })() : (() => {
6783
- const t = params.tokenFactoryData;
6784
- return viem.encodeAbiParameters(
6785
- [
6786
- { type: "string" },
6787
- { type: "string" },
6788
- { type: "uint256" },
6789
- { type: "uint256" },
6790
- { type: "address[]" },
6791
- { type: "uint256[]" },
6792
- { type: "string" }
6793
- ],
6794
- [
6795
- t.name,
6796
- t.symbol,
6797
- t.yearlyMintRate,
6798
- t.vestingDuration,
6799
- t.recipients,
6800
- t.amounts,
6801
- t.tokenURI
6802
- ]
6803
- );
6804
- })();
6805
- let tokenInitHash;
6806
- if (params.tokenVariant === "doppler404") {
6807
- const t = params.tokenFactoryData;
6808
- const initData = viem.encodeAbiParameters(
6809
- [
6810
- { type: "string" },
6811
- { type: "string" },
6812
- { type: "uint256" },
6813
- { type: "address" },
6814
- { type: "address" },
6815
- { type: "string" }
6816
- ],
6817
- [
6818
- t.name,
6819
- t.symbol,
6820
- params.initialSupply,
6821
- params.airlock,
6822
- params.airlock,
6823
- t.baseURI
6824
- ]
6825
- );
6826
- tokenInitHash = viem.keccak256(
6827
- viem.encodePacked(
6828
- ["bytes", "bytes"],
6829
- [dopplerDN404_default, initData]
6830
- )
7194
+ );
7195
+ const encodedTokenFactoryData = params.tokenVariant === "doppler404" ? (() => {
7196
+ const t = params.tokenFactoryData;
7197
+ return viem.encodeAbiParameters(
7198
+ [
7199
+ { type: "string" },
7200
+ { type: "string" },
7201
+ { type: "string" },
7202
+ { type: "uint256" }
7203
+ ],
7204
+ [t.name, t.symbol, t.baseURI, t.unit ?? 1000n]
6831
7205
  );
6832
- } else {
7206
+ })() : this.encodeStandardTokenFactoryData(
7207
+ params.tokenFactoryData
7208
+ );
7209
+ let tokenInitHash;
7210
+ if (params.tokenVariant === "doppler404") {
6833
7211
  const t = params.tokenFactoryData;
6834
7212
  const initData = viem.encodeAbiParameters(
6835
7213
  [
@@ -6838,10 +7216,6 @@ var DopplerFactory = class {
6838
7216
  { type: "uint256" },
6839
7217
  { type: "address" },
6840
7218
  { type: "address" },
6841
- { type: "uint256" },
6842
- { type: "uint256" },
6843
- { type: "address[]" },
6844
- { type: "uint256[]" },
6845
7219
  { type: "string" }
6846
7220
  ],
6847
7221
  [
@@ -6850,23 +7224,20 @@ var DopplerFactory = class {
6850
7224
  params.initialSupply,
6851
7225
  params.airlock,
6852
7226
  params.airlock,
6853
- t.yearlyMintRate,
6854
- t.vestingDuration,
6855
- t.recipients,
6856
- t.amounts,
6857
- t.tokenURI
7227
+ t.baseURI
6858
7228
  ]
6859
7229
  );
6860
- const isTokenFactory802 = params.tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
6861
7230
  tokenInitHash = viem.keccak256(
6862
7231
  viem.encodePacked(
6863
7232
  ["bytes", "bytes"],
6864
- [
6865
- isTokenFactory802 ? derc2080_default : derc20_default,
6866
- initData
6867
- ]
7233
+ [dopplerDN404_default, initData]
6868
7234
  )
6869
7235
  );
7236
+ } else {
7237
+ tokenInitHash = this.computeStandardTokenInitHash(
7238
+ params.tokenFactoryData,
7239
+ params.tokenFactory
7240
+ );
6870
7241
  }
6871
7242
  const isToken0 = isToken0Expected(params.numeraire);
6872
7243
  const numeraireBigInt = BigInt(params.numeraire);
@@ -7542,6 +7913,18 @@ var DopplerFactory = class {
7542
7913
  ]
7543
7914
  );
7544
7915
  }
7916
+ const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
7917
+ if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
7918
+ throw new Error(
7919
+ "Token factory address not configured. Provide an explicit address or ensure chain config includes a valid factory."
7920
+ );
7921
+ }
7922
+ this.assertStandardTokenFactoryCompatibility({
7923
+ token: params.token,
7924
+ vesting: params.vesting,
7925
+ tokenFactory: resolvedTokenFactory,
7926
+ addresses
7927
+ });
7545
7928
  let tokenFactoryData;
7546
7929
  if (this.isDoppler404Token(params.token)) {
7547
7930
  const token404 = params.token;
@@ -7556,41 +7939,17 @@ var DopplerFactory = class {
7556
7939
  [token404.name, token404.symbol, token404.baseURI, unit]
7557
7940
  );
7558
7941
  } else {
7559
- const tokenStd = params.token;
7560
- const vestingDuration = params.vesting?.duration ?? BigInt(0);
7561
- const yearlyMintRate = tokenStd.yearlyMintRate ?? DEFAULT_V4_YEARLY_MINT_RATE;
7562
- let vestingRecipients = [];
7563
- let vestingAmounts = [];
7564
- if (params.vesting) {
7565
- if (params.vesting.recipients && params.vesting.amounts) {
7566
- vestingRecipients = params.vesting.recipients;
7567
- vestingAmounts = params.vesting.amounts;
7568
- } else {
7569
- vestingRecipients = [params.userAddress];
7570
- vestingAmounts = [
7571
- params.sale.initialSupply - params.sale.numTokensToSell
7572
- ];
7573
- }
7574
- }
7575
- tokenFactoryData = viem.encodeAbiParameters(
7576
- [
7577
- { type: "string" },
7578
- { type: "string" },
7579
- { type: "uint256" },
7580
- { type: "uint256" },
7581
- { type: "address[]" },
7582
- { type: "uint256[]" },
7583
- { type: "string" }
7584
- ],
7585
- [
7586
- tokenStd.name,
7587
- tokenStd.symbol,
7588
- yearlyMintRate,
7589
- BigInt(vestingDuration),
7590
- vestingRecipients,
7591
- vestingAmounts,
7592
- tokenStd.tokenURI
7593
- ]
7942
+ const standardTokenFactoryData = this.buildStandardTokenFactoryData({
7943
+ token: params.token,
7944
+ sale: params.sale,
7945
+ vesting: params.vesting,
7946
+ userAddress: params.userAddress,
7947
+ airlock: params.modules?.airlock ?? addresses.airlock,
7948
+ tokenFactory: resolvedTokenFactory,
7949
+ addresses
7950
+ });
7951
+ tokenFactoryData = this.encodeStandardTokenFactoryData(
7952
+ standardTokenFactoryData
7594
7953
  );
7595
7954
  }
7596
7955
  const governanceFactoryData = (() => {
@@ -7619,12 +7978,6 @@ var DopplerFactory = class {
7619
7978
  );
7620
7979
  })();
7621
7980
  const salt = this.generateRandomSalt(params.userAddress);
7622
- const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : addresses.tokenFactory);
7623
- if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
7624
- throw new Error(
7625
- "Token factory address not configured. Provide an explicit address or ensure chain config includes a valid factory."
7626
- );
7627
- }
7628
7981
  const resolvedInitializer = (() => {
7629
7982
  if (useDopplerHookInitializer) {
7630
7983
  return params.modules?.dopplerHookInitializer ?? addresses.dopplerHookInitializer;
@@ -7877,6 +8230,109 @@ var DopplerFactory = class {
7877
8230
  const rounded = Math.floor(MAX_TICK / tickSpacing) * tickSpacing;
7878
8231
  return rounded;
7879
8232
  }
8233
+ validateVestingConfig(sale, vesting) {
8234
+ if (!vesting) {
8235
+ return;
8236
+ }
8237
+ const cliffDuration = vesting.cliffDuration ?? 0;
8238
+ const duration = vesting.duration ?? 0;
8239
+ const hasCustomSchedules = this.hasCustomV2Schedules(vesting);
8240
+ if (hasCustomSchedules && (cliffDuration > 0 || duration > 0)) {
8241
+ throw new Error(
8242
+ "Use vesting.schedules instead of top-level duration/cliffDuration when configuring multiple vesting schedules"
8243
+ );
8244
+ }
8245
+ if (vesting.recipients && vesting.amounts) {
8246
+ if (vesting.recipients.length !== vesting.amounts.length) {
8247
+ throw new Error(
8248
+ "Vesting recipients and amounts arrays must have the same length"
8249
+ );
8250
+ }
8251
+ if (vesting.recipients.length === 0) {
8252
+ throw new Error("Vesting recipients array cannot be empty");
8253
+ }
8254
+ const totalVested = vesting.amounts.reduce((sum, amt) => sum + amt, 0n);
8255
+ const availableForVesting = sale.initialSupply - sale.numTokensToSell;
8256
+ if (totalVested > availableForVesting) {
8257
+ throw new Error(
8258
+ `Total vesting amount (${totalVested}) exceeds available tokens (${availableForVesting})`
8259
+ );
8260
+ }
8261
+ } else {
8262
+ const vestedAmount = sale.initialSupply - sale.numTokensToSell;
8263
+ if (vestedAmount <= 0n) {
8264
+ throw new Error("No tokens available for vesting");
8265
+ }
8266
+ }
8267
+ if (hasCustomSchedules) {
8268
+ const schedules = vesting.schedules;
8269
+ if (!schedules || schedules.length === 0) {
8270
+ throw new Error(
8271
+ "Vesting schedules are required when using scheduleIds or multiple vesting schedules"
8272
+ );
8273
+ }
8274
+ const recipientCount = vesting.recipients && vesting.amounts ? vesting.recipients.length : 1;
8275
+ if (vesting.scheduleIds) {
8276
+ if (vesting.scheduleIds.length !== recipientCount) {
8277
+ throw new Error(
8278
+ "Vesting scheduleIds array must have the same length as vesting recipients"
8279
+ );
8280
+ }
8281
+ for (const [index, scheduleId] of vesting.scheduleIds.entries()) {
8282
+ this.validateUint64LikeNumber(
8283
+ scheduleId,
8284
+ `Vesting scheduleIds[${index}]`
8285
+ );
8286
+ if (scheduleId >= schedules.length) {
8287
+ throw new Error(
8288
+ `Vesting scheduleIds[${index}] references missing schedule ${scheduleId}`
8289
+ );
8290
+ }
8291
+ }
8292
+ } else if (schedules.length !== 1 && schedules.length !== recipientCount) {
8293
+ throw new Error(
8294
+ "Vesting schedules must either contain exactly one shared schedule or one schedule per recipient when scheduleIds are omitted"
8295
+ );
8296
+ }
8297
+ for (const [index, schedule] of schedules.entries()) {
8298
+ const scheduleCliff = schedule.cliffDuration ?? 0;
8299
+ const scheduleDuration = schedule.duration ?? 0;
8300
+ this.validateUint64LikeNumber(
8301
+ scheduleCliff,
8302
+ `Vesting schedules[${index}].cliffDuration`
8303
+ );
8304
+ this.validateUint64LikeNumber(
8305
+ scheduleDuration,
8306
+ `Vesting schedules[${index}].duration`
8307
+ );
8308
+ if (scheduleCliff > scheduleDuration) {
8309
+ throw new Error(
8310
+ `Vesting schedules[${index}].cliffDuration cannot exceed duration`
8311
+ );
8312
+ }
8313
+ if (scheduleCliff > 0 && scheduleDuration > 0 && scheduleDuration < DERC20_V2_MIN_VESTING_DURATION) {
8314
+ throw new Error(
8315
+ `Vesting schedules[${index}].duration must be 0 or at least ${DERC20_V2_MIN_VESTING_DURATION} seconds when using cliffs`
8316
+ );
8317
+ }
8318
+ }
8319
+ return;
8320
+ }
8321
+ if (cliffDuration < 0) {
8322
+ throw new Error("Vesting cliff duration cannot be negative");
8323
+ }
8324
+ if (duration < 0) {
8325
+ throw new Error("Vesting duration cannot be negative");
8326
+ }
8327
+ if (cliffDuration > duration) {
8328
+ throw new Error("Vesting cliff duration cannot exceed vesting duration");
8329
+ }
8330
+ if (cliffDuration > 0 && duration > 0 && duration < DERC20_V2_MIN_VESTING_DURATION) {
8331
+ throw new Error(
8332
+ `Vesting duration must be 0 or at least ${DERC20_V2_MIN_VESTING_DURATION} seconds when using cliffs`
8333
+ );
8334
+ }
8335
+ }
7880
8336
  validateStaticAuctionParams(params) {
7881
8337
  if (!params.token.name || params.token.name.trim().length === 0) {
7882
8338
  throw new Error("Token name is required");
@@ -7914,33 +8370,7 @@ var DopplerFactory = class {
7914
8370
  if (params.sale.numTokensToSell > params.sale.initialSupply) {
7915
8371
  throw new Error("Cannot sell more tokens than initial supply");
7916
8372
  }
7917
- if (params.vesting) {
7918
- if (params.vesting.recipients && params.vesting.amounts) {
7919
- if (params.vesting.recipients.length !== params.vesting.amounts.length) {
7920
- throw new Error(
7921
- "Vesting recipients and amounts arrays must have the same length"
7922
- );
7923
- }
7924
- if (params.vesting.recipients.length === 0) {
7925
- throw new Error("Vesting recipients array cannot be empty");
7926
- }
7927
- const totalVested = params.vesting.amounts.reduce(
7928
- (sum, amt) => sum + amt,
7929
- BigInt(0)
7930
- );
7931
- const availableForVesting = params.sale.initialSupply - params.sale.numTokensToSell;
7932
- if (totalVested > availableForVesting) {
7933
- throw new Error(
7934
- `Total vesting amount (${totalVested}) exceeds available tokens (${availableForVesting})`
7935
- );
7936
- }
7937
- } else {
7938
- const vestedAmount = params.sale.initialSupply - params.sale.numTokensToSell;
7939
- if (vestedAmount <= BigInt(0)) {
7940
- throw new Error("No tokens available for vesting");
7941
- }
7942
- }
7943
- }
8373
+ this.validateVestingConfig(params.sale, params.vesting);
7944
8374
  if (params.migration.type === "dopplerHook") {
7945
8375
  throw new Error(
7946
8376
  "dopplerHook migration is only supported for dynamic auctions"
@@ -8005,6 +8435,7 @@ var DopplerFactory = class {
8005
8435
  if (params.sale.numTokensToSell > params.sale.initialSupply) {
8006
8436
  throw new Error("Cannot sell more tokens than initial supply");
8007
8437
  }
8438
+ this.validateVestingConfig(params.sale, params.vesting);
8008
8439
  if (params.auction.duration <= 0) {
8009
8440
  throw new Error("Auction duration must be positive");
8010
8441
  }
@@ -8233,28 +8664,7 @@ var DopplerFactory = class {
8233
8664
  throw new Error("Cannot sell more tokens than initial supply");
8234
8665
  }
8235
8666
  this.resolveMulticurveInitializerMode(params);
8236
- if (params.vesting) {
8237
- if (params.vesting.recipients && params.vesting.amounts) {
8238
- if (params.vesting.recipients.length !== params.vesting.amounts.length) {
8239
- throw new Error(
8240
- "Vesting recipients and amounts arrays must have the same length"
8241
- );
8242
- }
8243
- if (params.vesting.recipients.length === 0) {
8244
- throw new Error("Vesting recipients array cannot be empty");
8245
- }
8246
- const totalVested = params.vesting.amounts.reduce(
8247
- (sum, amt) => sum + amt,
8248
- BigInt(0)
8249
- );
8250
- const availableForVesting = params.sale.initialSupply - params.sale.numTokensToSell;
8251
- if (totalVested > availableForVesting) {
8252
- throw new Error(
8253
- `Total vesting amount (${totalVested}) exceeds available tokens (${availableForVesting})`
8254
- );
8255
- }
8256
- }
8257
- }
8667
+ this.validateVestingConfig(params.sale, params.vesting);
8258
8668
  if (params.pool.beneficiaries && params.pool.beneficiaries.length > 0) {
8259
8669
  const beneficiaries = params.pool.beneficiaries;
8260
8670
  const totalShares = beneficiaries.reduce((sum, b) => sum + b.shares, 0n);
@@ -8654,37 +9064,9 @@ var DopplerFactory = class {
8654
9064
  ],
8655
9065
  [t.name, t.symbol, t.baseURI, t.unit ?? 1000n]
8656
9066
  );
8657
- })() : (() => {
8658
- const {
8659
- name,
8660
- symbol,
8661
- yearlyMintRate,
8662
- vestingDuration,
8663
- recipients,
8664
- amounts,
8665
- tokenURI
8666
- } = params.tokenFactoryData;
8667
- return viem.encodeAbiParameters(
8668
- [
8669
- { type: "string" },
8670
- { type: "string" },
8671
- { type: "uint256" },
8672
- { type: "uint256" },
8673
- { type: "address[]" },
8674
- { type: "uint256[]" },
8675
- { type: "string" }
8676
- ],
8677
- [
8678
- name,
8679
- symbol,
8680
- yearlyMintRate,
8681
- vestingDuration,
8682
- recipients,
8683
- amounts,
8684
- tokenURI
8685
- ]
8686
- );
8687
- })();
9067
+ })() : this.encodeStandardTokenFactoryData(
9068
+ params.tokenFactoryData
9069
+ );
8688
9070
  let tokenInitHash;
8689
9071
  if (params.tokenVariant === "doppler404") {
8690
9072
  const { name, symbol, baseURI } = params.tokenFactoryData;
@@ -8707,47 +9089,45 @@ var DopplerFactory = class {
8707
9089
  )
8708
9090
  );
8709
9091
  } else {
8710
- const {
8711
- name,
8712
- symbol,
8713
- yearlyMintRate,
8714
- vestingDuration,
8715
- recipients,
8716
- amounts,
8717
- tokenURI
8718
- } = params.tokenFactoryData;
8719
- const { airlock, initialSupply } = params;
8720
- const initHashData = viem.encodeAbiParameters(
8721
- [
8722
- { type: "string" },
8723
- { type: "string" },
8724
- { type: "uint256" },
8725
- { type: "address" },
8726
- { type: "address" },
8727
- { type: "uint256" },
8728
- { type: "uint256" },
8729
- { type: "address[]" },
8730
- { type: "uint256[]" },
8731
- { type: "string" }
8732
- ],
8733
- [
8734
- name,
8735
- symbol,
8736
- initialSupply,
8737
- airlock,
8738
- airlock,
8739
- yearlyMintRate,
8740
- vestingDuration,
8741
- recipients,
8742
- amounts,
8743
- tokenURI
8744
- ]
8745
- );
8746
- const isTokenFactory802 = params.tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
8747
- const bytecode = isTokenFactory802 ? derc2080_default : params.customDerc20Bytecode ?? derc20_default;
8748
- tokenInitHash = viem.keccak256(
8749
- viem.encodePacked(["bytes", "bytes"], [bytecode, initHashData])
8750
- );
9092
+ const standardTokenFactoryData = params.tokenFactoryData;
9093
+ if (standardTokenFactoryData.kind === "v2") {
9094
+ tokenInitHash = this.computeStandardTokenInitHash(
9095
+ standardTokenFactoryData,
9096
+ params.tokenFactory
9097
+ );
9098
+ } else {
9099
+ const initHashData = viem.encodeAbiParameters(
9100
+ [
9101
+ { type: "string" },
9102
+ { type: "string" },
9103
+ { type: "uint256" },
9104
+ { type: "address" },
9105
+ { type: "address" },
9106
+ { type: "uint256" },
9107
+ { type: "uint256" },
9108
+ { type: "address[]" },
9109
+ { type: "uint256[]" },
9110
+ { type: "string" }
9111
+ ],
9112
+ [
9113
+ standardTokenFactoryData.name,
9114
+ standardTokenFactoryData.symbol,
9115
+ standardTokenFactoryData.initialSupply,
9116
+ standardTokenFactoryData.airlock,
9117
+ standardTokenFactoryData.airlock,
9118
+ standardTokenFactoryData.yearlyMintRate,
9119
+ standardTokenFactoryData.vestingDuration,
9120
+ standardTokenFactoryData.recipients,
9121
+ standardTokenFactoryData.amounts,
9122
+ standardTokenFactoryData.tokenURI
9123
+ ]
9124
+ );
9125
+ const isTokenFactory802 = params.tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
9126
+ const bytecode = isTokenFactory802 ? derc2080_default : params.customDerc20Bytecode ?? derc20_default;
9127
+ tokenInitHash = viem.keccak256(
9128
+ viem.encodePacked(["bytes", "bytes"], [bytecode, initHashData])
9129
+ );
9130
+ }
8751
9131
  }
8752
9132
  const flags = BigInt(
8753
9133
  1 << 13 | // BEFORE_INITIALIZE_FLAG
@@ -13028,6 +13408,108 @@ var Derc20 = class _Derc20 {
13028
13408
  );
13029
13409
  }
13030
13410
  };
13411
+
13412
+ // src/evm/entities/token/derc20/Derc20V2.ts
13413
+ var Derc20V2 = class extends Derc20 {
13414
+ async getVestingScheduleCount() {
13415
+ return await this.rpc.readContract({
13416
+ address: this.address,
13417
+ abi: derc20V2Abi,
13418
+ functionName: "vestingScheduleCount"
13419
+ });
13420
+ }
13421
+ async getVestingSchedule(scheduleId) {
13422
+ const result = await this.rpc.readContract({
13423
+ address: this.address,
13424
+ abi: derc20V2Abi,
13425
+ functionName: "vestingSchedules",
13426
+ args: [scheduleId]
13427
+ });
13428
+ return {
13429
+ cliffDuration: BigInt(result[0]),
13430
+ duration: BigInt(result[1])
13431
+ };
13432
+ }
13433
+ async getScheduleIdsOf(beneficiary) {
13434
+ const result = await this.rpc.readContract({
13435
+ address: this.address,
13436
+ abi: derc20V2Abi,
13437
+ functionName: "getScheduleIdsOf",
13438
+ args: [beneficiary]
13439
+ });
13440
+ return Array.from(result);
13441
+ }
13442
+ async getTotalAllocatedOf(beneficiary) {
13443
+ return await this.rpc.readContract({
13444
+ address: this.address,
13445
+ abi: derc20V2Abi,
13446
+ functionName: "totalAllocatedOf",
13447
+ args: [beneficiary]
13448
+ });
13449
+ }
13450
+ async getAvailableVestedAmountForSchedule(beneficiary, scheduleId) {
13451
+ return await this.rpc.readContract({
13452
+ address: this.address,
13453
+ abi: derc20V2Abi,
13454
+ functionName: "computeAvailableVestedAmount",
13455
+ args: [beneficiary, scheduleId]
13456
+ });
13457
+ }
13458
+ async getVestingDataForSchedule(beneficiary, scheduleId) {
13459
+ const result = await this.rpc.readContract({
13460
+ address: this.address,
13461
+ abi: derc20V2Abi,
13462
+ functionName: "vestingOf",
13463
+ args: [beneficiary, scheduleId]
13464
+ });
13465
+ return {
13466
+ totalAmount: result[0],
13467
+ releasedAmount: result[1]
13468
+ };
13469
+ }
13470
+ async releaseSchedule(scheduleId, options) {
13471
+ if (!this.walletClient) {
13472
+ throw new Error("Wallet client required for write operations");
13473
+ }
13474
+ const { request } = await this.rpc.simulateContract({
13475
+ address: this.address,
13476
+ abi: derc20V2Abi,
13477
+ functionName: "release",
13478
+ args: [scheduleId],
13479
+ account: this.walletClient.account
13480
+ });
13481
+ return await this.walletClient.writeContract(
13482
+ options?.gas ? { ...request, gas: options.gas } : request
13483
+ );
13484
+ }
13485
+ async releaseFor(beneficiary, scheduleId, options) {
13486
+ if (!this.walletClient) {
13487
+ throw new Error("Wallet client required for write operations");
13488
+ }
13489
+ if (scheduleId === void 0) {
13490
+ const { request: request2 } = await this.rpc.simulateContract({
13491
+ address: this.address,
13492
+ abi: derc20V2Abi,
13493
+ functionName: "releaseFor",
13494
+ args: [beneficiary],
13495
+ account: this.walletClient.account
13496
+ });
13497
+ return await this.walletClient.writeContract(
13498
+ options?.gas ? { ...request2, gas: options.gas } : request2
13499
+ );
13500
+ }
13501
+ const { request } = await this.rpc.simulateContract({
13502
+ address: this.address,
13503
+ abi: derc20V2Abi,
13504
+ functionName: "releaseFor",
13505
+ args: [beneficiary, scheduleId],
13506
+ account: this.walletClient.account
13507
+ });
13508
+ return await this.walletClient.writeContract(
13509
+ options?.gas ? { ...request, gas: options.gas } : request
13510
+ );
13511
+ }
13512
+ };
13031
13513
  var Eth = class {
13032
13514
  publicClient;
13033
13515
  get rpc() {
@@ -13083,6 +13565,35 @@ var Eth = class {
13083
13565
  };
13084
13566
 
13085
13567
  // src/evm/builders/shared.ts
13568
+ var MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
13569
+ function normalizeBuilderVestingScheduleDuration(value, fieldPath) {
13570
+ const duration = value ?? 0n;
13571
+ if (duration < 0n) {
13572
+ throw new RangeError(`${fieldPath} cannot be negative`);
13573
+ }
13574
+ if (duration > MAX_SAFE_INTEGER_BIGINT) {
13575
+ throw new RangeError(`${fieldPath} must be a safe integer`);
13576
+ }
13577
+ return Number(duration);
13578
+ }
13579
+ function normalizeBuilderScheduleId(scheduleId, fieldPath) {
13580
+ if (typeof scheduleId === "bigint") {
13581
+ if (scheduleId < 0n) {
13582
+ throw new RangeError(`${fieldPath} cannot be negative`);
13583
+ }
13584
+ if (scheduleId > MAX_SAFE_INTEGER_BIGINT) {
13585
+ throw new RangeError(`${fieldPath} must be a safe integer`);
13586
+ }
13587
+ return Number(scheduleId);
13588
+ }
13589
+ if (!Number.isSafeInteger(scheduleId)) {
13590
+ throw new RangeError(`${fieldPath} must be a safe integer`);
13591
+ }
13592
+ if (scheduleId < 0) {
13593
+ throw new RangeError(`${fieldPath} cannot be negative`);
13594
+ }
13595
+ return scheduleId;
13596
+ }
13086
13597
  function computeTicks(priceRange, tickSpacing) {
13087
13598
  const startTick = Math.floor(
13088
13599
  Math.log(priceRange.startPrice) / Math.log(1.0001) / tickSpacing
@@ -13378,11 +13889,24 @@ var StaticAuctionBuilder = class _StaticAuctionBuilder {
13378
13889
  this.vesting = void 0;
13379
13890
  return this;
13380
13891
  }
13892
+ const hasCustomSchedules = (params.schedules?.length ?? 0) > 0 || (params.scheduleIds?.length ?? 0) > 0;
13381
13893
  this.vesting = {
13382
- duration: Number(params.duration ?? DEFAULT_V3_VESTING_DURATION),
13894
+ duration: Number(
13895
+ params.duration ?? (hasCustomSchedules ? 0n : DEFAULT_V3_VESTING_DURATION)
13896
+ ),
13383
13897
  cliffDuration: params.cliffDuration ?? 0,
13384
13898
  recipients: params.recipients,
13385
- amounts: params.amounts
13899
+ amounts: params.amounts,
13900
+ schedules: params.schedules?.map((schedule) => ({
13901
+ duration: normalizeBuilderVestingScheduleDuration(
13902
+ schedule.duration,
13903
+ "Vesting schedule duration"
13904
+ ),
13905
+ cliffDuration: schedule.cliffDuration ?? 0
13906
+ })),
13907
+ scheduleIds: params.scheduleIds?.map(
13908
+ (scheduleId, index) => normalizeBuilderScheduleId(scheduleId, `Vesting scheduleIds[${index}]`)
13909
+ )
13386
13910
  };
13387
13911
  return this;
13388
13912
  }
@@ -13714,7 +14238,17 @@ var DynamicAuctionBuilder = class _DynamicAuctionBuilder {
13714
14238
  duration: Number(params.duration ?? 0n),
13715
14239
  cliffDuration: params.cliffDuration ?? 0,
13716
14240
  recipients: params.recipients,
13717
- amounts: params.amounts
14241
+ amounts: params.amounts,
14242
+ schedules: params.schedules?.map((schedule) => ({
14243
+ duration: normalizeBuilderVestingScheduleDuration(
14244
+ schedule.duration,
14245
+ "Vesting schedule duration"
14246
+ ),
14247
+ cliffDuration: schedule.cliffDuration ?? 0
14248
+ })),
14249
+ scheduleIds: params.scheduleIds?.map(
14250
+ (scheduleId, index) => normalizeBuilderScheduleId(scheduleId, `Vesting scheduleIds[${index}]`)
14251
+ )
13718
14252
  };
13719
14253
  return this;
13720
14254
  }
@@ -14320,7 +14854,17 @@ var MulticurveBuilder = class _MulticurveBuilder {
14320
14854
  duration: Number(params.duration ?? 0n),
14321
14855
  cliffDuration: params.cliffDuration ?? 0,
14322
14856
  recipients: params.recipients,
14323
- amounts: params.amounts
14857
+ amounts: params.amounts,
14858
+ schedules: params.schedules?.map((schedule) => ({
14859
+ duration: normalizeBuilderVestingScheduleDuration(
14860
+ schedule.duration,
14861
+ "Vesting schedule duration"
14862
+ ),
14863
+ cliffDuration: schedule.cliffDuration ?? 0
14864
+ })),
14865
+ scheduleIds: params.scheduleIds?.map(
14866
+ (scheduleId, index) => normalizeBuilderScheduleId(scheduleId, `Vesting scheduleIds[${index}]`)
14867
+ )
14324
14868
  };
14325
14869
  return this;
14326
14870
  }
@@ -14709,7 +15253,17 @@ var OpeningAuctionBuilder = class _OpeningAuctionBuilder {
14709
15253
  duration: Number(params.duration ?? 0n),
14710
15254
  cliffDuration: params.cliffDuration ?? 0,
14711
15255
  recipients: params.recipients,
14712
- amounts: params.amounts
15256
+ amounts: params.amounts,
15257
+ schedules: params.schedules?.map((schedule) => ({
15258
+ duration: normalizeBuilderVestingScheduleDuration(
15259
+ schedule.duration,
15260
+ "Vesting schedule duration"
15261
+ ),
15262
+ cliffDuration: schedule.cliffDuration ?? 0
15263
+ })),
15264
+ scheduleIds: params.scheduleIds?.map(
15265
+ (scheduleId, index) => normalizeBuilderScheduleId(scheduleId, `Vesting scheduleIds[${index}]`)
15266
+ )
14713
15267
  };
14714
15268
  return this;
14715
15269
  }
@@ -15155,6 +15709,13 @@ var DopplerSDK = class {
15155
15709
  getDerc20(tokenAddress) {
15156
15710
  return new Derc20(this.publicClient, this.walletClient, tokenAddress);
15157
15711
  }
15712
+ /**
15713
+ * Get a DERC20 V2 token instance for interacting with cliffed / multi-schedule vesting tokens
15714
+ * @param tokenAddress The address of the DERC20 V2 token
15715
+ */
15716
+ getDerc20V2(tokenAddress) {
15717
+ return new Derc20V2(this.publicClient, this.walletClient, tokenAddress);
15718
+ }
15158
15719
  /**
15159
15720
  * Get information about a static auction pool
15160
15721
  * @param poolAddress The address of the pool
@@ -15277,6 +15838,7 @@ exports.DOPPLER_FLAGS = DOPPLER_FLAGS;
15277
15838
  exports.DOPPLER_MAX_TICK_SPACING = DOPPLER_MAX_TICK_SPACING;
15278
15839
  exports.DYNAMIC_FEE_FLAG = DYNAMIC_FEE_FLAG;
15279
15840
  exports.Derc20 = Derc20;
15841
+ exports.Derc20V2 = Derc20V2;
15280
15842
  exports.DopplerBytecode = doppler_default;
15281
15843
  exports.DopplerDN404Bytecode = dopplerDN404_default;
15282
15844
  exports.DopplerFactory = DopplerFactory;
@@ -15347,6 +15909,7 @@ exports.createAirlockBeneficiary = createAirlockBeneficiary;
15347
15909
  exports.decayMulticurveInitializerHookAbi = decayMulticurveInitializerHookAbi;
15348
15910
  exports.decodeBalanceDelta = decodeBalanceDelta;
15349
15911
  exports.derc20Abi = derc20Abi;
15912
+ exports.derc20V2Abi = derc20V2Abi;
15350
15913
  exports.dopplerHookAbi = dopplerHookAbi;
15351
15914
  exports.dopplerHookInitializerAbi = dopplerHookInitializerAbi;
15352
15915
  exports.dopplerLensAbi = dopplerLensAbi;