@whetstone-research/doppler-sdk 1.0.4 → 1.0.5

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,7 @@ var erc20BalanceOfAbi = [
5094
5281
  }
5095
5282
  ];
5096
5283
  var TOKEN_FACTORY_80_ADDRESS2 = "0xf0b5141dd9096254b2ca624dff26024f46087229";
5284
+ var DERC20_V2_MIN_VESTING_DURATION = 24 * 60 * 60;
5097
5285
  var DopplerFactory = class {
5098
5286
  publicClient;
5099
5287
  walletClient;
@@ -5105,6 +5293,204 @@ var DopplerFactory = class {
5105
5293
  this.walletClient = walletClient;
5106
5294
  this.chainId = chainId;
5107
5295
  }
5296
+ usesDerc20V2Vesting(vesting) {
5297
+ return (vesting?.cliffDuration ?? 0) > 0;
5298
+ }
5299
+ resolveVestingAllocations(args) {
5300
+ if (!args.vesting) {
5301
+ return { recipients: [], amounts: [] };
5302
+ }
5303
+ if (args.vesting.recipients && args.vesting.amounts) {
5304
+ return {
5305
+ recipients: args.vesting.recipients,
5306
+ amounts: args.vesting.amounts
5307
+ };
5308
+ }
5309
+ return {
5310
+ recipients: [args.userAddress],
5311
+ amounts: [args.sale.initialSupply - args.sale.numTokensToSell]
5312
+ };
5313
+ }
5314
+ resolveStandardTokenFactoryMode(args) {
5315
+ if (this.usesDerc20V2Vesting(args.vesting)) {
5316
+ return "v2";
5317
+ }
5318
+ const v2Factory = args.addresses.derc20V2Factory;
5319
+ if (v2Factory && args.tokenFactory.toLowerCase() === v2Factory.toLowerCase()) {
5320
+ return "v2";
5321
+ }
5322
+ return "legacy";
5323
+ }
5324
+ assertStandardTokenFactoryCompatibility(args) {
5325
+ if (this.isDoppler404Token(args.token) || !this.usesDerc20V2Vesting(args.vesting)) {
5326
+ return;
5327
+ }
5328
+ const v2Factory = args.addresses.derc20V2Factory;
5329
+ if (!v2Factory || v2Factory === ZERO_ADDRESS2) {
5330
+ throw new Error(
5331
+ "Cliff vesting requires the DERC20 V2 factory, but no V2 factory is configured for this chain."
5332
+ );
5333
+ }
5334
+ if (args.tokenFactory.toLowerCase() !== v2Factory.toLowerCase()) {
5335
+ throw new Error(
5336
+ "Cliff vesting requires the DERC20 V2 factory. Remove the tokenFactory override or point it at the chain DERC20 V2 factory."
5337
+ );
5338
+ }
5339
+ }
5340
+ buildStandardTokenFactoryData(args) {
5341
+ const { recipients, amounts } = this.resolveVestingAllocations(args);
5342
+ const yearlyMintRate = args.token.yearlyMintRate ?? DEFAULT_V4_YEARLY_MINT_RATE;
5343
+ const mode = this.resolveStandardTokenFactoryMode({
5344
+ vesting: args.vesting,
5345
+ tokenFactory: args.tokenFactory,
5346
+ addresses: args.addresses
5347
+ });
5348
+ if (mode === "v2") {
5349
+ const implementation = args.addresses.derc20V2Implementation;
5350
+ if (!implementation || implementation === ZERO_ADDRESS2) {
5351
+ throw new Error(
5352
+ "DERC20 V2 implementation address not configured for this chain."
5353
+ );
5354
+ }
5355
+ const schedules = args.vesting === void 0 ? [] : [
5356
+ {
5357
+ cliff: BigInt(args.vesting.cliffDuration ?? 0),
5358
+ duration: BigInt(args.vesting.duration ?? 0)
5359
+ }
5360
+ ];
5361
+ return {
5362
+ kind: "v2",
5363
+ name: args.token.name,
5364
+ symbol: args.token.symbol,
5365
+ initialSupply: args.sale.initialSupply,
5366
+ airlock: args.airlock,
5367
+ yearlyMintRate,
5368
+ schedules,
5369
+ beneficiaries: recipients,
5370
+ scheduleIds: recipients.map(() => 0n),
5371
+ amounts,
5372
+ tokenURI: args.token.tokenURI,
5373
+ implementation
5374
+ };
5375
+ }
5376
+ return {
5377
+ kind: "legacy",
5378
+ name: args.token.name,
5379
+ symbol: args.token.symbol,
5380
+ initialSupply: args.sale.initialSupply,
5381
+ airlock: args.airlock,
5382
+ yearlyMintRate,
5383
+ vestingDuration: BigInt(args.vesting?.duration ?? 0),
5384
+ recipients,
5385
+ amounts,
5386
+ tokenURI: args.token.tokenURI
5387
+ };
5388
+ }
5389
+ encodeStandardTokenFactoryData(tokenFactoryData) {
5390
+ if (tokenFactoryData.kind === "v2") {
5391
+ return viem.encodeAbiParameters(
5392
+ [
5393
+ { type: "string" },
5394
+ { type: "string" },
5395
+ { type: "uint256" },
5396
+ {
5397
+ type: "tuple[]",
5398
+ components: [
5399
+ { type: "uint64", name: "cliff" },
5400
+ { type: "uint64", name: "duration" }
5401
+ ]
5402
+ },
5403
+ { type: "address[]" },
5404
+ { type: "uint256[]" },
5405
+ { type: "uint256[]" },
5406
+ { type: "string" }
5407
+ ],
5408
+ [
5409
+ tokenFactoryData.name,
5410
+ tokenFactoryData.symbol,
5411
+ tokenFactoryData.yearlyMintRate,
5412
+ tokenFactoryData.schedules.map((schedule) => ({
5413
+ cliff: schedule.cliff,
5414
+ duration: schedule.duration
5415
+ })),
5416
+ tokenFactoryData.beneficiaries,
5417
+ tokenFactoryData.scheduleIds,
5418
+ tokenFactoryData.amounts,
5419
+ tokenFactoryData.tokenURI
5420
+ ]
5421
+ );
5422
+ }
5423
+ return viem.encodeAbiParameters(
5424
+ [
5425
+ { type: "string" },
5426
+ { type: "string" },
5427
+ { type: "uint256" },
5428
+ { type: "uint256" },
5429
+ { type: "address[]" },
5430
+ { type: "uint256[]" },
5431
+ { type: "string" }
5432
+ ],
5433
+ [
5434
+ tokenFactoryData.name,
5435
+ tokenFactoryData.symbol,
5436
+ tokenFactoryData.yearlyMintRate,
5437
+ tokenFactoryData.vestingDuration,
5438
+ tokenFactoryData.recipients,
5439
+ tokenFactoryData.amounts,
5440
+ tokenFactoryData.tokenURI
5441
+ ]
5442
+ );
5443
+ }
5444
+ computeSoladyCloneInitCodeHash(implementation) {
5445
+ return viem.keccak256(
5446
+ `0x602c3d8160093d39f33d3d3d3d363d3d37363d73${implementation.slice(
5447
+ 2
5448
+ )}5af43d3d93803e602a57fd5bf3`
5449
+ );
5450
+ }
5451
+ computeStandardTokenInitHash(tokenFactoryData, tokenFactory) {
5452
+ if (tokenFactoryData.kind === "v2") {
5453
+ return this.computeSoladyCloneInitCodeHash(
5454
+ tokenFactoryData.implementation
5455
+ );
5456
+ }
5457
+ const initData = viem.encodeAbiParameters(
5458
+ [
5459
+ { type: "string" },
5460
+ { type: "string" },
5461
+ { type: "uint256" },
5462
+ { type: "address" },
5463
+ { type: "address" },
5464
+ { type: "uint256" },
5465
+ { type: "uint256" },
5466
+ { type: "address[]" },
5467
+ { type: "uint256[]" },
5468
+ { type: "string" }
5469
+ ],
5470
+ [
5471
+ tokenFactoryData.name,
5472
+ tokenFactoryData.symbol,
5473
+ tokenFactoryData.initialSupply,
5474
+ tokenFactoryData.airlock,
5475
+ tokenFactoryData.airlock,
5476
+ tokenFactoryData.yearlyMintRate,
5477
+ tokenFactoryData.vestingDuration,
5478
+ tokenFactoryData.recipients,
5479
+ tokenFactoryData.amounts,
5480
+ tokenFactoryData.tokenURI
5481
+ ]
5482
+ );
5483
+ const isTokenFactory802 = tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
5484
+ return viem.keccak256(
5485
+ viem.encodePacked(
5486
+ ["bytes", "bytes"],
5487
+ [
5488
+ isTokenFactory802 ? derc2080_default : derc20_default,
5489
+ initData
5490
+ ]
5491
+ )
5492
+ );
5493
+ }
5108
5494
  /**
5109
5495
  * Set a custom migration data encoder function
5110
5496
  * @param encoder Custom function to encode migration data
@@ -5189,6 +5575,18 @@ var DopplerFactory = class {
5189
5575
  numeraire: params.sale.numeraire,
5190
5576
  overrides: params.modules
5191
5577
  });
5578
+ const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
5579
+ if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
5580
+ throw new Error(
5581
+ "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
5582
+ );
5583
+ }
5584
+ this.assertStandardTokenFactoryCompatibility({
5585
+ token: params.token,
5586
+ vesting: params.vesting,
5587
+ tokenFactory: resolvedTokenFactory,
5588
+ addresses
5589
+ });
5192
5590
  let tokenFactoryData;
5193
5591
  if (this.isDoppler404Token(params.token)) {
5194
5592
  const token404 = params.token;
@@ -5204,41 +5602,17 @@ var DopplerFactory = class {
5204
5602
  [params.token.name, params.token.symbol, baseURI, unit]
5205
5603
  );
5206
5604
  } 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
- ]
5605
+ const standardTokenFactoryData = this.buildStandardTokenFactoryData({
5606
+ token: params.token,
5607
+ sale: params.sale,
5608
+ vesting: params.vesting,
5609
+ userAddress: params.userAddress,
5610
+ airlock: params.modules?.airlock ?? addresses.airlock,
5611
+ tokenFactory: resolvedTokenFactory,
5612
+ addresses
5613
+ });
5614
+ tokenFactoryData = this.encodeStandardTokenFactoryData(
5615
+ standardTokenFactoryData
5242
5616
  );
5243
5617
  }
5244
5618
  const governanceFactoryData = (() => {
@@ -5293,12 +5667,6 @@ var DopplerFactory = class {
5293
5667
  }
5294
5668
  return resolved;
5295
5669
  })();
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
5670
  const baseCreateParams = {
5303
5671
  initialSupply: params.sale.initialSupply,
5304
5672
  numTokensToSell: params.sale.numTokensToSell,
@@ -5584,7 +5952,18 @@ var DopplerFactory = class {
5584
5952
  );
5585
5953
  }
5586
5954
  }
5587
- const vestingDuration = params.vesting?.duration ?? BigInt(0);
5955
+ const resolvedTokenFactoryDyn = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
5956
+ if (!resolvedTokenFactoryDyn || resolvedTokenFactoryDyn === ZERO_ADDRESS2) {
5957
+ throw new Error(
5958
+ "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
5959
+ );
5960
+ }
5961
+ this.assertStandardTokenFactoryCompatibility({
5962
+ token: params.token,
5963
+ vesting: params.vesting,
5964
+ tokenFactory: resolvedTokenFactoryDyn,
5965
+ addresses
5966
+ });
5588
5967
  const tokenFactoryData = this.isDoppler404Token(params.token) ? (() => {
5589
5968
  const t = params.token;
5590
5969
  return {
@@ -5593,39 +5972,15 @@ var DopplerFactory = class {
5593
5972
  baseURI: t.baseURI,
5594
5973
  unit: t.unit !== void 0 ? BigInt(t.unit) : 1000n
5595
5974
  };
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
- }
5975
+ })() : this.buildStandardTokenFactoryData({
5976
+ token: params.token,
5977
+ sale: params.sale,
5978
+ vesting: params.vesting,
5979
+ userAddress: params.userAddress,
5980
+ airlock: params.modules?.airlock ?? addresses.airlock,
5981
+ tokenFactory: resolvedTokenFactoryDyn,
5982
+ addresses
5983
+ });
5629
5984
  const [
5630
5985
  salt,
5631
5986
  hookAddress,
@@ -5952,7 +6307,18 @@ var DopplerFactory = class {
5952
6307
  );
5953
6308
  }
5954
6309
  }
5955
- const vestingDuration = params.vesting?.duration ?? BigInt(0);
6310
+ const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
6311
+ if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
6312
+ throw new Error(
6313
+ "Token factory address not configured. Provide an explicit address via builder.withTokenFactory(...) or ensure chain config includes a valid factory."
6314
+ );
6315
+ }
6316
+ this.assertStandardTokenFactoryCompatibility({
6317
+ token: params.token,
6318
+ vesting: params.vesting,
6319
+ tokenFactory: resolvedTokenFactory,
6320
+ addresses
6321
+ });
5956
6322
  const tokenFactoryData = this.isDoppler404Token(params.token) ? (() => {
5957
6323
  const t = params.token;
5958
6324
  return {
@@ -5961,39 +6327,15 @@ var DopplerFactory = class {
5961
6327
  baseURI: t.baseURI,
5962
6328
  unit: t.unit !== void 0 ? BigInt(t.unit) : 1000n
5963
6329
  };
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
- }
6330
+ })() : this.buildStandardTokenFactoryData({
6331
+ token: params.token,
6332
+ sale: params.sale,
6333
+ vesting: params.vesting,
6334
+ userAddress: params.userAddress,
6335
+ airlock: params.modules?.airlock ?? addresses.airlock,
6336
+ tokenFactory: resolvedTokenFactory,
6337
+ addresses
6338
+ });
5997
6339
  const auctionTokens = params.sale.numTokensToSell * BigInt(params.openingAuction.shareToAuctionBps) / 10000n;
5998
6340
  if (auctionTokens <= 0n) {
5999
6341
  throw new Error("Opening auction token allocation rounds to zero");
@@ -6779,29 +7121,9 @@ var DopplerFactory = class {
6779
7121
  ],
6780
7122
  [t.name, t.symbol, t.baseURI, t.unit ?? 1000n]
6781
7123
  );
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
- })();
7124
+ })() : this.encodeStandardTokenFactoryData(
7125
+ params.tokenFactoryData
7126
+ );
6805
7127
  let tokenInitHash;
6806
7128
  if (params.tokenVariant === "doppler404") {
6807
7129
  const t = params.tokenFactoryData;
@@ -6830,42 +7152,9 @@ var DopplerFactory = class {
6830
7152
  )
6831
7153
  );
6832
7154
  } else {
6833
- const t = params.tokenFactoryData;
6834
- const initData = viem.encodeAbiParameters(
6835
- [
6836
- { type: "string" },
6837
- { type: "string" },
6838
- { type: "uint256" },
6839
- { type: "address" },
6840
- { type: "address" },
6841
- { type: "uint256" },
6842
- { type: "uint256" },
6843
- { type: "address[]" },
6844
- { type: "uint256[]" },
6845
- { type: "string" }
6846
- ],
6847
- [
6848
- t.name,
6849
- t.symbol,
6850
- params.initialSupply,
6851
- params.airlock,
6852
- params.airlock,
6853
- t.yearlyMintRate,
6854
- t.vestingDuration,
6855
- t.recipients,
6856
- t.amounts,
6857
- t.tokenURI
6858
- ]
6859
- );
6860
- const isTokenFactory802 = params.tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
6861
- tokenInitHash = viem.keccak256(
6862
- viem.encodePacked(
6863
- ["bytes", "bytes"],
6864
- [
6865
- isTokenFactory802 ? derc2080_default : derc20_default,
6866
- initData
6867
- ]
6868
- )
7155
+ tokenInitHash = this.computeStandardTokenInitHash(
7156
+ params.tokenFactoryData,
7157
+ params.tokenFactory
6869
7158
  );
6870
7159
  }
6871
7160
  const isToken0 = isToken0Expected(params.numeraire);
@@ -7542,6 +7831,18 @@ var DopplerFactory = class {
7542
7831
  ]
7543
7832
  );
7544
7833
  }
7834
+ const resolvedTokenFactory = params.modules?.tokenFactory ?? (this.isDoppler404Token(params.token) ? addresses.doppler404Factory : this.usesDerc20V2Vesting(params.vesting) ? addresses.derc20V2Factory : addresses.tokenFactory);
7835
+ if (!resolvedTokenFactory || resolvedTokenFactory === ZERO_ADDRESS2) {
7836
+ throw new Error(
7837
+ "Token factory address not configured. Provide an explicit address or ensure chain config includes a valid factory."
7838
+ );
7839
+ }
7840
+ this.assertStandardTokenFactoryCompatibility({
7841
+ token: params.token,
7842
+ vesting: params.vesting,
7843
+ tokenFactory: resolvedTokenFactory,
7844
+ addresses
7845
+ });
7545
7846
  let tokenFactoryData;
7546
7847
  if (this.isDoppler404Token(params.token)) {
7547
7848
  const token404 = params.token;
@@ -7556,41 +7857,17 @@ var DopplerFactory = class {
7556
7857
  [token404.name, token404.symbol, token404.baseURI, unit]
7557
7858
  );
7558
7859
  } 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
- ]
7860
+ const standardTokenFactoryData = this.buildStandardTokenFactoryData({
7861
+ token: params.token,
7862
+ sale: params.sale,
7863
+ vesting: params.vesting,
7864
+ userAddress: params.userAddress,
7865
+ airlock: params.modules?.airlock ?? addresses.airlock,
7866
+ tokenFactory: resolvedTokenFactory,
7867
+ addresses
7868
+ });
7869
+ tokenFactoryData = this.encodeStandardTokenFactoryData(
7870
+ standardTokenFactoryData
7594
7871
  );
7595
7872
  }
7596
7873
  const governanceFactoryData = (() => {
@@ -7619,12 +7896,6 @@ var DopplerFactory = class {
7619
7896
  );
7620
7897
  })();
7621
7898
  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
7899
  const resolvedInitializer = (() => {
7629
7900
  if (useDopplerHookInitializer) {
7630
7901
  return params.modules?.dopplerHookInitializer ?? addresses.dopplerHookInitializer;
@@ -7877,6 +8148,49 @@ var DopplerFactory = class {
7877
8148
  const rounded = Math.floor(MAX_TICK / tickSpacing) * tickSpacing;
7878
8149
  return rounded;
7879
8150
  }
8151
+ validateVestingConfig(sale, vesting) {
8152
+ if (!vesting) {
8153
+ return;
8154
+ }
8155
+ const cliffDuration = vesting.cliffDuration ?? 0;
8156
+ const duration = vesting.duration ?? 0;
8157
+ if (cliffDuration < 0) {
8158
+ throw new Error("Vesting cliff duration cannot be negative");
8159
+ }
8160
+ if (duration < 0) {
8161
+ throw new Error("Vesting duration cannot be negative");
8162
+ }
8163
+ if (cliffDuration > duration) {
8164
+ throw new Error("Vesting cliff duration cannot exceed vesting duration");
8165
+ }
8166
+ if (cliffDuration > 0 && duration > 0 && duration < DERC20_V2_MIN_VESTING_DURATION) {
8167
+ throw new Error(
8168
+ `Vesting duration must be 0 or at least ${DERC20_V2_MIN_VESTING_DURATION} seconds when using cliffs`
8169
+ );
8170
+ }
8171
+ if (vesting.recipients && vesting.amounts) {
8172
+ if (vesting.recipients.length !== vesting.amounts.length) {
8173
+ throw new Error(
8174
+ "Vesting recipients and amounts arrays must have the same length"
8175
+ );
8176
+ }
8177
+ if (vesting.recipients.length === 0) {
8178
+ throw new Error("Vesting recipients array cannot be empty");
8179
+ }
8180
+ const totalVested = vesting.amounts.reduce((sum, amt) => sum + amt, 0n);
8181
+ const availableForVesting = sale.initialSupply - sale.numTokensToSell;
8182
+ if (totalVested > availableForVesting) {
8183
+ throw new Error(
8184
+ `Total vesting amount (${totalVested}) exceeds available tokens (${availableForVesting})`
8185
+ );
8186
+ }
8187
+ return;
8188
+ }
8189
+ const vestedAmount = sale.initialSupply - sale.numTokensToSell;
8190
+ if (vestedAmount <= 0n) {
8191
+ throw new Error("No tokens available for vesting");
8192
+ }
8193
+ }
7880
8194
  validateStaticAuctionParams(params) {
7881
8195
  if (!params.token.name || params.token.name.trim().length === 0) {
7882
8196
  throw new Error("Token name is required");
@@ -7914,33 +8228,8 @@ var DopplerFactory = class {
7914
8228
  if (params.sale.numTokensToSell > params.sale.initialSupply) {
7915
8229
  throw new Error("Cannot sell more tokens than initial supply");
7916
8230
  }
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
- }
8231
+ this.validateVestingConfig(params.sale, params.vesting);
8232
+ this.validateVestingConfig(params.sale, params.vesting);
7944
8233
  if (params.migration.type === "dopplerHook") {
7945
8234
  throw new Error(
7946
8235
  "dopplerHook migration is only supported for dynamic auctions"
@@ -8005,6 +8294,7 @@ var DopplerFactory = class {
8005
8294
  if (params.sale.numTokensToSell > params.sale.initialSupply) {
8006
8295
  throw new Error("Cannot sell more tokens than initial supply");
8007
8296
  }
8297
+ this.validateVestingConfig(params.sale, params.vesting);
8008
8298
  if (params.auction.duration <= 0) {
8009
8299
  throw new Error("Auction duration must be positive");
8010
8300
  }
@@ -8233,28 +8523,7 @@ var DopplerFactory = class {
8233
8523
  throw new Error("Cannot sell more tokens than initial supply");
8234
8524
  }
8235
8525
  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
- }
8526
+ this.validateVestingConfig(params.sale, params.vesting);
8258
8527
  if (params.pool.beneficiaries && params.pool.beneficiaries.length > 0) {
8259
8528
  const beneficiaries = params.pool.beneficiaries;
8260
8529
  const totalShares = beneficiaries.reduce((sum, b) => sum + b.shares, 0n);
@@ -8654,37 +8923,9 @@ var DopplerFactory = class {
8654
8923
  ],
8655
8924
  [t.name, t.symbol, t.baseURI, t.unit ?? 1000n]
8656
8925
  );
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
- })();
8926
+ })() : this.encodeStandardTokenFactoryData(
8927
+ params.tokenFactoryData
8928
+ );
8688
8929
  let tokenInitHash;
8689
8930
  if (params.tokenVariant === "doppler404") {
8690
8931
  const { name, symbol, baseURI } = params.tokenFactoryData;
@@ -8707,47 +8948,45 @@ var DopplerFactory = class {
8707
8948
  )
8708
8949
  );
8709
8950
  } 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
- );
8951
+ const standardTokenFactoryData = params.tokenFactoryData;
8952
+ if (standardTokenFactoryData.kind === "v2") {
8953
+ tokenInitHash = this.computeStandardTokenInitHash(
8954
+ standardTokenFactoryData,
8955
+ params.tokenFactory
8956
+ );
8957
+ } else {
8958
+ const initHashData = viem.encodeAbiParameters(
8959
+ [
8960
+ { type: "string" },
8961
+ { type: "string" },
8962
+ { type: "uint256" },
8963
+ { type: "address" },
8964
+ { type: "address" },
8965
+ { type: "uint256" },
8966
+ { type: "uint256" },
8967
+ { type: "address[]" },
8968
+ { type: "uint256[]" },
8969
+ { type: "string" }
8970
+ ],
8971
+ [
8972
+ standardTokenFactoryData.name,
8973
+ standardTokenFactoryData.symbol,
8974
+ standardTokenFactoryData.initialSupply,
8975
+ standardTokenFactoryData.airlock,
8976
+ standardTokenFactoryData.airlock,
8977
+ standardTokenFactoryData.yearlyMintRate,
8978
+ standardTokenFactoryData.vestingDuration,
8979
+ standardTokenFactoryData.recipients,
8980
+ standardTokenFactoryData.amounts,
8981
+ standardTokenFactoryData.tokenURI
8982
+ ]
8983
+ );
8984
+ const isTokenFactory802 = params.tokenFactory.toLowerCase() === TOKEN_FACTORY_80_ADDRESS2;
8985
+ const bytecode = isTokenFactory802 ? derc2080_default : params.customDerc20Bytecode ?? derc20_default;
8986
+ tokenInitHash = viem.keccak256(
8987
+ viem.encodePacked(["bytes", "bytes"], [bytecode, initHashData])
8988
+ );
8989
+ }
8751
8990
  }
8752
8991
  const flags = BigInt(
8753
8992
  1 << 13 | // BEFORE_INITIALIZE_FLAG
@@ -13028,6 +13267,108 @@ var Derc20 = class _Derc20 {
13028
13267
  );
13029
13268
  }
13030
13269
  };
13270
+
13271
+ // src/evm/entities/token/derc20/Derc20V2.ts
13272
+ var Derc20V2 = class extends Derc20 {
13273
+ async getVestingScheduleCount() {
13274
+ return await this.rpc.readContract({
13275
+ address: this.address,
13276
+ abi: derc20V2Abi,
13277
+ functionName: "vestingScheduleCount"
13278
+ });
13279
+ }
13280
+ async getVestingSchedule(scheduleId) {
13281
+ const result = await this.rpc.readContract({
13282
+ address: this.address,
13283
+ abi: derc20V2Abi,
13284
+ functionName: "vestingSchedules",
13285
+ args: [scheduleId]
13286
+ });
13287
+ return {
13288
+ cliffDuration: BigInt(result[0]),
13289
+ duration: BigInt(result[1])
13290
+ };
13291
+ }
13292
+ async getScheduleIdsOf(beneficiary) {
13293
+ const result = await this.rpc.readContract({
13294
+ address: this.address,
13295
+ abi: derc20V2Abi,
13296
+ functionName: "getScheduleIdsOf",
13297
+ args: [beneficiary]
13298
+ });
13299
+ return Array.from(result);
13300
+ }
13301
+ async getTotalAllocatedOf(beneficiary) {
13302
+ return await this.rpc.readContract({
13303
+ address: this.address,
13304
+ abi: derc20V2Abi,
13305
+ functionName: "totalAllocatedOf",
13306
+ args: [beneficiary]
13307
+ });
13308
+ }
13309
+ async getAvailableVestedAmountForSchedule(beneficiary, scheduleId) {
13310
+ return await this.rpc.readContract({
13311
+ address: this.address,
13312
+ abi: derc20V2Abi,
13313
+ functionName: "computeAvailableVestedAmount",
13314
+ args: [beneficiary, scheduleId]
13315
+ });
13316
+ }
13317
+ async getVestingDataForSchedule(beneficiary, scheduleId) {
13318
+ const result = await this.rpc.readContract({
13319
+ address: this.address,
13320
+ abi: derc20V2Abi,
13321
+ functionName: "vestingOf",
13322
+ args: [beneficiary, scheduleId]
13323
+ });
13324
+ return {
13325
+ totalAmount: result[0],
13326
+ releasedAmount: result[1]
13327
+ };
13328
+ }
13329
+ async releaseSchedule(scheduleId, options) {
13330
+ if (!this.walletClient) {
13331
+ throw new Error("Wallet client required for write operations");
13332
+ }
13333
+ const { request } = await this.rpc.simulateContract({
13334
+ address: this.address,
13335
+ abi: derc20V2Abi,
13336
+ functionName: "release",
13337
+ args: [scheduleId],
13338
+ account: this.walletClient.account
13339
+ });
13340
+ return await this.walletClient.writeContract(
13341
+ options?.gas ? { ...request, gas: options.gas } : request
13342
+ );
13343
+ }
13344
+ async releaseFor(beneficiary, scheduleId, options) {
13345
+ if (!this.walletClient) {
13346
+ throw new Error("Wallet client required for write operations");
13347
+ }
13348
+ if (scheduleId === void 0) {
13349
+ const { request: request2 } = await this.rpc.simulateContract({
13350
+ address: this.address,
13351
+ abi: derc20V2Abi,
13352
+ functionName: "releaseFor",
13353
+ args: [beneficiary],
13354
+ account: this.walletClient.account
13355
+ });
13356
+ return await this.walletClient.writeContract(
13357
+ options?.gas ? { ...request2, gas: options.gas } : request2
13358
+ );
13359
+ }
13360
+ const { request } = await this.rpc.simulateContract({
13361
+ address: this.address,
13362
+ abi: derc20V2Abi,
13363
+ functionName: "releaseFor",
13364
+ args: [beneficiary, scheduleId],
13365
+ account: this.walletClient.account
13366
+ });
13367
+ return await this.walletClient.writeContract(
13368
+ options?.gas ? { ...request, gas: options.gas } : request
13369
+ );
13370
+ }
13371
+ };
13031
13372
  var Eth = class {
13032
13373
  publicClient;
13033
13374
  get rpc() {
@@ -15155,6 +15496,13 @@ var DopplerSDK = class {
15155
15496
  getDerc20(tokenAddress) {
15156
15497
  return new Derc20(this.publicClient, this.walletClient, tokenAddress);
15157
15498
  }
15499
+ /**
15500
+ * Get a DERC20 V2 token instance for interacting with cliffed / multi-schedule vesting tokens
15501
+ * @param tokenAddress The address of the DERC20 V2 token
15502
+ */
15503
+ getDerc20V2(tokenAddress) {
15504
+ return new Derc20V2(this.publicClient, this.walletClient, tokenAddress);
15505
+ }
15158
15506
  /**
15159
15507
  * Get information about a static auction pool
15160
15508
  * @param poolAddress The address of the pool
@@ -15277,6 +15625,7 @@ exports.DOPPLER_FLAGS = DOPPLER_FLAGS;
15277
15625
  exports.DOPPLER_MAX_TICK_SPACING = DOPPLER_MAX_TICK_SPACING;
15278
15626
  exports.DYNAMIC_FEE_FLAG = DYNAMIC_FEE_FLAG;
15279
15627
  exports.Derc20 = Derc20;
15628
+ exports.Derc20V2 = Derc20V2;
15280
15629
  exports.DopplerBytecode = doppler_default;
15281
15630
  exports.DopplerDN404Bytecode = dopplerDN404_default;
15282
15631
  exports.DopplerFactory = DopplerFactory;
@@ -15347,6 +15696,7 @@ exports.createAirlockBeneficiary = createAirlockBeneficiary;
15347
15696
  exports.decayMulticurveInitializerHookAbi = decayMulticurveInitializerHookAbi;
15348
15697
  exports.decodeBalanceDelta = decodeBalanceDelta;
15349
15698
  exports.derc20Abi = derc20Abi;
15699
+ exports.derc20V2Abi = derc20V2Abi;
15350
15700
  exports.dopplerHookAbi = dopplerHookAbi;
15351
15701
  exports.dopplerHookInitializerAbi = dopplerHookInitializerAbi;
15352
15702
  exports.dopplerLensAbi = dopplerLensAbi;