Launch token through Portal

This page explains how to launch a token directly through Portal. The current launch entry points are:

  • newTokenV6 for TOKEN_V2_PERMIT and all currently supported tax-token versions (TOKEN_TAXED, TOKEN_TAXED_V2, TOKEN_TAXED_V3)

  • newTokenV7 for TOKEN_V3_PERMIT, the TokenV3-based non-tax flow used for CL-style migration

Legacy methods (newTokenV2, newTokenV3, newTokenV4, newTokenV5) remain available for backward compatibility.

TOKEN_TAXED_V3 (FlapTaxTokenV3) is the recommended token type for all new tax token launches. It supports asymmetric buy/sell tax rates, commission receivers, and bidirectional dynamic liquidation thresholds. Use newTokenV6 with tokenVersion = TOKEN_TAXED_V3 for new integrations.

TOKEN_V3_PERMIT is launched through newTokenV7, not newTokenV6. Use it when you want the TokenV3 non-tax path together with CL-style migration.

1) Prepare token metadata

Token metadata is stored on IPFS. You can upload your image and metadata JSON through the Flap upload API.

Example (TypeScript):

async function uploadTokenMeta(cfg: {
    buy: string | null;
    creator: string;
    description: string;
    sell: string | null;
    telegram: string | null;
    twitter: string | null;
    website: string | null;
    image_path: string;
}) {
    const form = new FormData();

    const MUTATION_CREATE = `
    mutation Create($file: Upload!, $meta: MetadataInput!) {
      create(file: $file, meta: $meta)
    }
    `;

    form.append(
        "operations",
        JSON.stringify({
            query: MUTATION_CREATE,
            variables: {
                file: null, meta: {
                    website: cfg.website,
                    twitter: cfg.twitter,
                    telegram: cfg.telegram,
                    description: cfg.description,
                    creator: "0x0000000000000000000000000000000000000000",
                }
            },
        })
    );

    form.append(
        "map",
        JSON.stringify({
            "0": ["variables.file"],
        })
    );

    const file = new File([fs.readFileSync(cfg.image_path)], "image.png", {
        type: "image/png",
    });
    form.append("0", file);

    const res = await axios.postForm(FlapConfig.api, form, {
        headers: {
            "Content-Type": "multipart/form-data",
        },
    });

    if (res.status !== 200) {
        throw new Error(`failed to upload the token meta: ${res.statusText}`);
    }

    const cid = res.data.data.create;
    return cid;
}

2) Call newTokenV6

newTokenV6 is the recommended unified entry point for all token types. The token implementation is selected via the tokenVersion field.

NewTokenV6Params covers all token types via tokenVersion:

Token version dispatch

The tokenVersion field controls which token implementation is created:

tokenVersion

Token type

Notes

TOKEN_V2_PERMIT

Standard ERC-20 with permit

Set both tax rates to 0, commissionReceiver must be address(0)

TOKEN_TAXED

FlapTaxToken V1

Legacy; symmetric rates only, mktBps must be 10000, no commission. Not recommended for new launches.

TOKEN_TAXED_V2

FlapTaxTokenV2

Legacy; symmetric rates only, mktBps must not be 10000, no commission. Not recommended for new launches.

TOKEN_TAXED_V3

FlapTaxTokenV3

Recommended. Asymmetric rates, commission supported.

TOKEN_V3_PERMIT is intentionally not part of newTokenV6. Use newTokenV7 for that launch path.

Set tokenVersion = TOKEN_TAXED_V3 and fill in the tax fields:

Key notes:

  • meta is the IPFS CID of your metadata JSON.

  • migratorType must be V2_MIGRATOR for tax tokens.

  • quoteToken = address(0) uses the native gas token.

  • salt must produce the required vanity suffix: 7777 for tax tokens, 8888 for standard tokens.

  • mktBps + deflationBps + dividendBps + lpBps must equal 10000.

  • dividendToken supports three modes: Case 10xfEEDFEEDfeEDFEedFEEdFEEDFeEdfEEdFeEdFEEd (MAGIC_DIVIDEND_SELF, distributes the launching token itself); Case 2address(0) or the quote token address (most common); Case 3 — any ERC-20 that has a registered swap path in SwapRegistry. See Tax Token V3 for full details.

  • Set commissionReceiver to your address to earn a protocol-calculated commission from every taxable transaction.

Launching a standard token

Set tokenVersion = TOKEN_V2_PERMIT and all tax fields to 0:

3) Call newTokenV7

newTokenV7 is the TokenV3-based launch entry point. It is intended for CL-style migration and introduces feeConfigs, which replace the old beneficiary + mktBps/deflationBps/dividendBps/lpBps split used by newTokenV6 tax launches.

Current newTokenV7 rollout details

The interface includes both TOKEN_V3_PERMIT and TOKEN_TAXED_V3 paths, but the current implementation is narrower:

  • Public newTokenV7 launches currently support TOKEN_V3_PERMIT only.

  • TOKEN_TAXED_V3 through newTokenV7 currently reverts with NewTokenV7RuleViolation(4).

  • For tax-token launches, keep using newTokenV6.

  • The current implementation accepts PCS_INFINITY_CL_MIGRATOR for the public TOKEN_V3_PERMIT path.

  • commissionReceiver must be address(0) for TOKEN_V3_PERMIT.

  • buyTaxRate and sellTaxRate must both be 0 for TOKEN_V3_PERMIT.

  • antiFarmerDuration must not exceed 365 days.

How feeConfigs work

feeConfigs has 4 fixed slots. General validation rules from the launcher are:

  • every slot with feeType != NONE must have bps > 0

  • duplicate fee types are not allowed

  • all active slots together must sum to exactly 10000 bps

  • MARKETING_OR_VAULT requires a non-zero marketingAddress

  • DIVIDEND uses dividendToken and minimumShareBalance

For the current public TOKEN_V3_PERMIT rollout, there are extra restrictions:

  • only one active fee mode is currently supported

  • supported mode A: a single MARKETING_OR_VAULT slot with bps = 10000

  • supported mode B: a single DIVIDEND slot with bps = 10000 and dividendToken == quoteToken

  • DEFLATION and LP_BPS are not enabled yet for TOKEN_V3_PERMIT and revert with UnsupportedV7TokenV3PermitFeeType(...)

There is no standalone beneficiary field in NewTokenV7Params. If you use MARKETING_OR_VAULT, the first such slot's marketingAddress becomes the primary beneficiary used by the launcher.

Example: zero-tax TOKEN_V3_PERMIT launch

If you use the dividend-only mode instead of the marketing mode, set exactly one DIVIDEND slot with bps = 10000, and set dividendToken to the same address as quoteToken.

4) Find the salt (vanity suffix)

Portal uses CREATE2 for deterministic deployments. The salt must produce a token address with the required suffix:

  • Non-tax token: address ends with 8888.

  • Tax token: address ends with 7777.

To find a valid salt, repeatedly hash a random seed and check the predicted address until it matches the suffix. You can predict the address using CREATE2 with the Portal address and the token implementation address for the token type you’re launching.

Example (TypeScript):

Use the correct tokenImpl and portal addresses for your network (see the deployed addresses page in this section).

Token implementation selection for launch methods:

  • TOKEN_V2_PERMIT (standard token): use the Standard Token Impl (tokenImplV2).

  • TOKEN_TAXED_V3 (recommended tax token): use the Tax Token V3 Impl (tokenImplTaxedV3).

  • TOKEN_TAXED (legacy V1, not recommended): use the Tax Token V1 Impl (tokenImplTaxed).

  • TOKEN_TAXED_V2 (legacy V2, not recommended): use the Tax Token V2 Impl (tokenImplTaxedV2).

  • TOKEN_V3_PERMIT via newTokenV7: use the Standard Token V3 Impl. It is still a non-tax launch, so the vanity suffix is 8888.

See deployed-contract-addresses.md for the exact implementation addresses.

5) Legacy methods

newTokenV2, newTokenV3, newTokenV4, and newTokenV5 are still supported for legacy integrations. They follow the same flow but provide fewer features than the current launch paths. New integrations should use newTokenV6 for tax tokens and TOKEN_V2_PERMIT, or newTokenV7 for TOKEN_V3_PERMIT.

IPortal.sol

Full interface reference for developers:

Last updated