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

Using an LP Token or Child Token as the Dividend Token

This tutorial walks you through implementing a vault factory that uses a computed dividend token β€” a token whose address cannot be known before the tax token is deployed, such as a Uniswap/PancakeSwap LP pair or a child token deployed deterministically from the tax token address.

This feature was introduced in factory spec v2.3.


The Problem

When launching a token through VaultPortal, the caller must supply a dividendToken address β€” the ERC-20 token that vault holders receive as dividends. Most of the time this is straightforward (e.g. use WBNB, or USDT).

But some vault designs require a dividend token whose address depends on the tax token address itself:

  • LP pair tokens β€” the PancakeSwap pair for (taxToken, WBNB) has an address derived from taxToken.

  • Child tokens / receipt tokens β€” a token deployed via CREATE2 keyed on taxToken.

At launch time the tax token does not exist yet β€” VaultPortal predicts its address via CREATE2, but the actual deployment happens inside Portal. The dividendToken field is needed before that deployment, so there is no way to supply the real LP/child address upfront.


The Solution: MAGIC_DIVIDEND_COMPUTED

VaultPortal supports a special sentinel value for dividendToken:

// IPortal.sol
address constant MAGIC_DIVIDEND_COMPUTED =
    address(0xC0Dec0dec0DeC0Dec0dEc0DEC0DEC0DEC0DEC0dE);

When the launcher passes MAGIC_DIVIDEND_COMPUTED as dividendToken, VaultPortal will:

  1. Compute the CREATE2-predicted tax token address.

  2. Check that the selected vault factory implements spec v2.3 (factorySpecVersion() returns "v2.3" or higher).

  3. Call resolveDividendToken(predictedToken, launchVersion, launchParams) on the factory.

  4. Use the returned address as the actual dividendToken forwarded to Portal.

If the factory does not support v2.3, the launch reverts with FactoryDoesNotSupportComputedDividend().


Implementation Guide

Step 1 β€” Declare spec v2.3 in your factory

Your factory must extend VaultFactoryBaseV2 and override factorySpecVersion() to return "v2.3" (or higher):


Step 2 β€” Implement resolveDividendToken

IVaultFactoryDividendV23 requires a single function:

Parameter
Description

predictedToken

The CREATE2-predicted address of the tax token (not yet deployed)

launchVersion

DIVIDEND_TOKEN_LAUNCH_VERSION_V6 or DIVIDEND_TOKEN_LAUNCH_VERSION_V7 depending on the launch wrapper used

launchParams

ABI-encoded NewTokenV6WithVaultParams or NewTokenV7WithVaultParams

VaultPortal calls this as a staticcall, so the function must be view (no state writes).

Example β€” LP pair dividend

This example resolves the PancakeSwap V2 LP pair of (predictedToken, WBNB) as the dividend token:

Example β€” Child token dividend

If your vault deploys a child token deterministically from the tax token address:


Step 3 β€” Declare a policy so the UI pre-fills the sentinel

tokenCreationPolicies() lets the UI know that dividendToken must equal MAGIC_DIVIDEND_COMPUTED. The UI reads this policy and pre-fills (or locks) the field before the user submits the launch form.

Policies are advisory hints for the UI only β€” they do not enforce anything on-chain. Always pair a policy with the corresponding _validateBeforeLaunch check (Step 4) to enforce the rule on-chain.


Step 4 β€” Enforce the sentinel in _validateBeforeLaunch

Override _validateBeforeLaunch to reject any launch that does not carry MAGIC_DIVIDEND_COMPUTED. This is the on-chain enforcement that backs the UI policy declared above.

VaultPortal calls onBeforeLaunch(bytes) (which decodes into _validateBeforeLaunch) before it calls resolveDividendToken. This means the hook sees dividendToken == MAGIC_DIVIDEND_COMPUTED β€” the raw sentinel, not yet the resolved LP address. That is the correct value to check against.


Step 5 β€” Launch with MAGIC_DIVIDEND_COMPUTED

On the caller side, set dividendToken to the sentinel when building the launch params:

VaultPortal will call myLPVaultFactory.resolveDividendToken(...) and substitute the result before forwarding the launch to Portal.


What Happens On-Chain (Flow Summary)


Version Gating

factorySpecVersion()

MAGIC_DIVIDEND_COMPUTED supported?

"" (legacy / V1)

❌ reverts with FactoryDoesNotSupportComputedDividend

"v2.1", "v2.2"

❌ reverts

"v2.3" or higher

βœ… resolveDividendToken is called

Factories that do not implement v2.3 are completely unaffected β€” the new sentinel only triggers for launches that explicitly pass MAGIC_DIVIDEND_COMPUTED.


Checklist

Last updated