For the complete documentation index, see llms.txt. This page is also available as Markdown.

Fee Rehypothecation

Create Multicurve pools with RehypeDopplerHook for advanced fee distribution and buyback mechanisms

Rehype Pools use the RehypeDopplerHookInitializer to distribute trading fees across beneficiaries, LPs, and buyback destinations.

Fee distribution model

Fees are split into four categories (must sum to 100%):

Category
Description

Asset Buyback

Buy back the token

Numeraire Buyback

Buy back the quote token

Beneficiary

Stream to configured addresses

LP

Distribute to liquidity providers


Basic example

import { DopplerSDK, getAddresses } from '@whetstone-research/doppler-sdk';
import { parseEther, createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';

const privateKey = process.env.PRIVATE_KEY as `0x${string}`;
const rpcUrl = process.env.RPC_URL ?? 'https://mainnet.base.org';

async function main() {
  const account = privateKeyToAccount(privateKey);
  const addresses = getAddresses(base.id);

  const publicClient = createPublicClient({
    chain: base,
    transport: http(rpcUrl),
  });

  const walletClient = createWalletClient({
    chain: base,
    transport: http(rpcUrl),
    account,
  });

  const sdk = new DopplerSDK({
    publicClient,
    walletClient,
    chainId: base.id,
  });

  // Get protocol owner for beneficiary requirement (min 5%)
  const protocolOwner = await sdk.getAirlockBeneficiary();

  // Beneficiaries receive the beneficiaryPercentWad portion of fees
  const beneficiaries = [
    protocolOwner, // 5% to protocol (minimum required)
    { beneficiary: account.address, shares: parseEther('0.95') }, // 95% to creator
  ];

  const BUYBACK_DESTINATION = account.address; // receives bought-back tokens

  const params = sdk
    .buildMulticurveAuction()
    .tokenConfig({
      name: 'Rehype Token',
      symbol: 'RHT',
      tokenURI: 'https://example.com/metadata.json',
    })
    .saleConfig({
      initialSupply: parseEther('1000000000'),
      numTokensToSell: parseEther('1000000000'),
      numeraire: addresses.weth,
    })
    .withCurves({
      numerairePrice: 3000, // ETH = $3000 USD
      curves: [
        { marketCap: { start: 500_000, end: 1_500_000 }, numPositions: 10, shares: parseEther('0.3') },
        { marketCap: { start: 1_000_000, end: 5_000_000 }, numPositions: 15, shares: parseEther('0.4') },
        { marketCap: { start: 4_000_000, end: 50_000_000 }, numPositions: 10, shares: parseEther('0.3') },
      ],
      beneficiaries,
    })
    .withRehypeDopplerHook({
      hookAddress: addresses.rehypeDopplerHookInitializer!,
      buybackDestination: BUYBACK_DESTINATION,
      customFee: 3000, // 0.3% swap fee
      // Distribution must sum to WAD (100%)
      assetBuybackPercentWad: parseEther('0.20'),      // 20%
      numeraireBuybackPercentWad: parseEther('0.20'), // 20%
      beneficiaryPercentWad: parseEther('0.30'),       // 30%
      lpPercentWad: parseEther('0.30'),                // 30%
    })
    .withGovernance({ type: 'noOp' })
    .withMigration({ type: 'noOp' })
    .withUserAddress(account.address)
    .withDopplerHookInitializer(addresses.dopplerHookInitializer!)
    .withNoOpMigrator(addresses.noOpMigrator!)
    .build();

  const result = await sdk.factory.createMulticurve(params);

  console.log('Pool:', result.poolId);
  console.log('Token:', result.tokenAddress);
}

main();

Fee distribution strategies

Heavy buyback (price support)

LP-first (attract liquidity)

Treasury-building


Configuring and updating fee distribution

After configuring the token, sale, and curves, set the Rehype fee beneficiaries and an optional durable fee controller. Beneficiaries receive the config's beneficiary allocations according to their shares. The controller can replace the config after launch, or it can be assigned to addresses such as 0xdead to make the config immutable.

Beneficiary shares must sum to WAD. The controller is fixed at pool creation, so use an operational wallet or multisig that will remain available to sign updates.

buybackDestination is an alternative builder input for the same overloaded onchain buybackDst field, so do not set both. That field receives proceeds when no feeBeneficiaries are configured and/or the directBuyback routing mode is used.

Connect the SDK to the controller wallet to replace the pool's complete fee distribution config:

setFeeDistribution replaces all eight values; it is not a partial update. The four assetFeesTo* values must sum to WAD, and the four numeraireFeesTo* values must separately sum to WAD. The update does not change the fee schedule, routing mode, or beneficiary shares.

Read the active config with:


Atomic dev buys

Use withDevBuy to create the pool and execute an exact-input purchase in the same transaction:

The SDK uses the chain's configured Bundler by default. Use .withBundler(address) only for a compatible custom deployment.

For compatible Rehype pools, initialization grants that Bundler a pool-specific exemption for its first swap in the launch transaction. The dev buy still pays the protocol's share of the Rehype fee.

Native numeraires send exactly exactAmountIn with the bundle. ERC-20 numeraires require sufficient balance and Bundler allowances. createMulticurve submits an approval first when needed.

Omit vesting to send purchased tokens directly to recipient. When supplied, vestingDuration must be at least one day, cliffDuration cannot exceed it, and permissionless claims can trigger delivery but cannot change the recipient.


Collecting fees

Anyone can trigger fee collection; fees are distributed automatically to the initializer, but each address listed as a beneficiary must then claim their own fees from the initializer:


Configuration reference

RehypeDopplerHookConfig

Parameter
Type
Description

hookAddress

Address

Deployed RehypeDopplerHookInitializer (must be whitelisted)

buybackDestination

Address

Receives buyback tokens

customFee

number

Swap fee in bps (3000 = 0.3%)

feeDistributionInfo

object

Separate four-way WAD splits for asset and numeraire fees

assetBuybackPercentWad

bigint

% for asset buyback (in WAD)

numeraireBuybackPercentWad

bigint

% for numeraire buyback (in WAD)

beneficiaryPercentWad

bigint

% for beneficiaries (in WAD)

lpPercentWad

bigint

% for LPs (in WAD)

graduationCalldata

Hex

Optional calldata on graduation


Rules

  • Distribution sum: All four percentages must equal WAD (1e18)

  • Distribution updates: Only the fixed fee distribution controller can replace the eight-value config

  • Beneficiary shares: Must sum to WAD; protocol owner needs at least 5%

    • Note: each beneficiary must collect their own fees by calling collectFees

  • Hook whitelisting: hookAddress must be enabled in DopplerHookInitializer

  • Migration: Use noOp - rehype pools don't migrate liquidity

  • Dev buys: Supported by compatible DopplerHookInitializer and Rehype initializer deployments

  • Pool status: Enters "Locked" (status = 2)

Last updated