Migration pools are standalone token conversion facilities on Solana. They let projects swap users from an old token to a new one — or raise SOL for a new launch — with configurable rules around timing, caps, vesting, and referral incentives.
Unlike a regular AMM swap (which prices dynamically), migration pools have fixed conversion rules set by the pool creator. The authority deposits new tokens into a vault, users send old tokens in, and get new tokens out at the configured rate. Each pool is a 512-byte PDA on-chain. No off-chain servers, no centralized custody.
| Feature | DEX / AMM | Migration Pool |
|---|---|---|
| Price | Dynamic (supply/demand) | Fixed (authority-set rate) |
| Slippage | Yes | No (rate is constant) |
| Liquidity | Both sides deposited | Only new tokens deposited |
| Duration | Permanent | Time-bounded (start → end) |
| Direction | Bidirectional | One-way (old → new) |
| Vesting | No | Optional (Types 3, 10, 11) |
| Caps | No | Optional (Types 7, 9) |
| Access Control | Open to all | Optional whitelist (Type 8) |
| Referrals | No | Built-in multi-level system |
| Old Token | Stays in pool | Stored in vault OR burned |
Send 1 old token, get 1 new token. Token rebrands, contract upgrades, mint rotations.
Convert at a fixed ratio (e.g., 10 old = 1 new). Handles decimal differences. Token consolidation.
Fixed ratio with an authority fee deducted from output. Revenue-generating migrations.
New tokens unlock gradually over time with periodic claims. Prevents post-migration dumps.
Early birds get a bonus that shrinks over time. Creates FOMO and rewards early adopters.
Old tokens permanently destroyed via CPI burn. Irreversible. Deflationary upgrades.
Merge multiple old tokens into one new token. Separate pools per old token, each with own ratio.
Global cap on total distributed. First-come, first-served. Partial fills at the cap boundary.
Authority must co-sign every swap. Only pre-approved wallets can migrate. Real-time gating.
Each wallet has a cumulative limit. Anti-whale fairness mechanism for fair distribution.
Time-decay bonus combined with gradual vesting. Rush for bonus, then tokens unlock over time.
Old tokens burned immediately, new tokens vest gradually. Strongest commitment mechanism.
Send SOL (not SPL tokens) to buy new tokens at a fixed rate. Direct lamport-to-token sale.
The TUI (aex tui) is a read-only dashboard — it shows live pool data, progress bars, referral configs, and stats. All actual operations go through CLI commands.
$ aex tui ← Launch TUI Press [8] ← DeFi composite panel Press [i] ← Migration sub-tab [j/k] ← Navigate up/down [Enter] ← View pool details [d] ← Deposit hint [p] ← Pause/Unpause hint [x] ← Close hint [b] or [Esc] ← Back to list
| Type | Swap Command | After Swap | Key Flag |
|---|---|---|---|
| 0 (1:1) | aex migrate swap <pool> <amt> | Nothing | — |
| 1 (Ratio) | aex migrate swap <pool> <amt> | Nothing | — |
| 2 (Ratio+Fee) | aex migrate swap <pool> <amt> | Nothing | — |
| 3 (Vest) | aex migrate swap <pool> <amt> | claim periodically | VEST |
| 4 (Decay) | aex migrate swap <pool> <amt> --min-out | Nothing | DECAY |
| 5 (Burn) | aex migrate swap <pool> <amt> | Nothing | BURN |
| 6 (Merge) | aex migrate swap <pool> <amt> (per pool) | Nothing | — |
| 7 (Capped) | aex migrate swap <pool> <amt> --min-out | Nothing | — |
| 8 (Gated) | Requires authority co-sign | Nothing | GATED |
| 9 (WlCap) | aex migrate swap <pool> <amt> | Nothing | WLCAP |
| 10 (Vest+Bonus) | aex migrate swap <pool> <amt> | claim periodically | VEST+DECAY |
| 11 (Burn+Vest) | aex migrate swap <pool> <amt> | claim periodically | BURN+VEST |
| 12 (SOL) | aex migrate swap <pool> <lamports> | Nothing | SOL |
--referrer <pubkey> to any swap command for referral rewards.Swap old tokens for new tokens at a 1:1 rate. The simplest migration — send 1000 old, get 1000 new. No vesting, no bonus, no catches.
Token rebrands (ALPHA → OMEGA), contract upgrades, mint rotations after security incidents.
$ aex tui
[8] → DeFi panel
[i] → Migration sub-tab
[j/k] → Navigate to your pool
[Enter] → View details
$ aex balance --keypair wallet.json
Amounts are in raw units (including decimals). For 6 decimals: 1,000 tokens = 1,000,000,000 raw.
$ aex migrate swap 7xKq...3nPd 5000000000 --keypair wallet.json
Migration swap submitted!
Pool: 7xKq...3nPd
Sent: 5,000.000000 ALPHA
Received: 5,000.000000 OMEGA
TX: 5Uxj...7kPm
Go back to the TUI (auto-refreshes every 5 seconds). Confirm your migration was counted in the stats.
$ aex migrate swap 7xKq...3nPd 5000000000 --referrer <referrer_pubkey> --keypair wallet.json
You get the same 5,000 OMEGA. The referrer gets a bonus from the vault (e.g., 250 OMEGA at 5% referral rate).
| Error | Cause | Fix |
|---|---|---|
| ERR_PAUSED (6000) | Pool is paused | Wait for authority to unpause |
| ERR_MIG (6031) | Pool ended or not started | Check time window in TUI |
| ERR_ZERO (6003) | Amount too small | Increase swap amount |
| SPL transfer failed | Vault empty | Authority needs to deposit more |
Convert old tokens at a fixed ratio (e.g., 10 old = 1 new). The ratio is set in the pool's param0 (numerator) and param1 (denominator) fields.
output = input_amount * param0 / param1
Example: param0=1, param1=10
Send 10,000 old → get 1,000 new (10:1 consolidation)
$ aex migrate swap <pool> <amount_raw> --keypair wallet.json
Token consolidation (reduce circulating supply), decimal changes (e.g., 9 decimals → 6 decimals), cross-chain parity adjustments.
Fixed ratio conversion with an authority fee deducted from the output. The fee (in param2 as bps) lets the authority earn revenue from the migration.
gross_output = input * param0 / param1
fee = gross_output * param2 / 10000
net_output = gross_output - fee
Example: ratio 1:1, fee 200 bps (2%)
Send 1,000 → gross 1,000 → fee 20 → receive 980
$ aex migrate swap <pool> <amount> --keypair wallet.json
--min-out to protect against unexpected fee levels.Swap old tokens for new tokens, but the new tokens are locked and unlock gradually over time. You come back periodically to claim unlocked portions.
Projects preventing post-migration dumps, loyalty rewards, token launches with gradual distribution.
Type: 3 (Vesting)
Flags: VEST
Vest Duration: 2592000s (30 days)
Claim Interval: 604800s (7 days)
Ratio: 1:1
Tokens vest over 30 days. Claim once per week. Each claim: ~23.3% of total.
$ aex migrate swap <pool> 10000000000000 --keypair wallet.json
This creates a MigrationClaimPDA linked to your wallet. You're entitled to 10,000 new tokens, but they're locked.
$ aex migrate claim <pool> --keypair wallet.json
Vesting claim submitted!
Entitled: 10,000.000000 V2
Already claimed: 0.000000
Now claimable: 2,333.333333 V2
elapsed = min(now - first_deposit, vest_duration)
intervals_passed = floor(elapsed / claim_interval)
total_intervals = vest_duration / claim_interval
unlocked = total_entitled * intervals_passed / total_intervals
claimable = unlocked - already_claimed
# crontab -e
0 12 * * 1 /path/to/aex migrate claim <pool> --keypair /path/to/wallet.json
Early migrants get a bonus that shrinks over time. The bonus starts at param2 bps and linearly decays to 0 by the pool's end time.
remaining = end_time - now
total_window = end_time - start_time
bonus_pct = param2 * remaining / total_window
output = input * (10000 + bonus_pct) / 10000
Day 1 of 30-day pool (bonus=2000 bps):
bonus = 2000 * 29/30 = 1933 bps (19.33%)
Send 1,000 → receive 1,193
Day 29:
bonus = 2000 * 1/30 = 66 bps (0.66%)
Send 1,000 → receive 1,006
--min-out to lock in your expected bonus rate. The rate changes every second.Old tokens are permanently destroyed via CPI burn. The program calls the SPL Token burn instruction directly. This is irreversible — there is no old_vault to reclaim from.
Normal migration: old tokens go into old_vault (authority can reclaim later). Burn migration: old tokens are burned on the spot. Total old supply decreases permanently.
$ aex migrate swap <pool> <amount> --keypair wallet.json
Deflationary token upgrades, security incident remediation (destroy compromised mint supply), permanent token retirement.
Merge multiple old token communities into one new token. The authority creates separate migration pools per old token, each with its own conversion ratio.
Pool A: OLD_A → NEW (ratio 1:1) p0=1, p1=1
Pool B: OLD_B → NEW (ratio 2:1) p0=1, p1=2
Pool C: OLD_C → NEW (ratio 5:1) p0=1, p1=5
Each pool is independent. Users migrate from whichever old token they hold.
First-come, first-served migration with a global cap on total tokens distributed. Once the cap is hit, the pool stops accepting swaps.
cap = param2 (raw token units)
If total_distributed + output > cap:
output = cap - total_distributed (partial fill)
Next swap after cap: ERR_CAP
--min-out to reject partial fills below your threshold.The authority must co-sign every swap transaction. Only wallets the authority approves can migrate. There's no on-chain whitelist — the authority's bot gates access in real-time.
1. User requests migration via off-chain channel
2. Authority's bot verifies eligibility
3. Bot co-signs the transaction
4. User submits the co-signed TX
KYC-gated migrations, holder snapshots (only snapshot holders approved), geographic restrictions, tiered access.
Each wallet has a cumulative limit on how much they can migrate. Tracked via the MigrationClaimPDA. Anti-whale mechanism for fair distribution.
max_per_wallet = param2 (raw token units)
On each swap:
if user_total_migrated + amount > max_per_wallet:
ERR_CAP
Multiple swaps are fine as long as total stays under the cap. The claim PDA tracks cumulative amount.
Combines time-decay bonus (Type 4) with vesting (Type 3). Rush to lock in the early-bird bonus, then claim tokens gradually as they vest.
param2 = bonus_bps (e.g., 2000 = 20% max bonus)
param3 = vest_duration (seconds)
param4 = claim_interval (seconds)
Example: 20% bonus, 28-day vest, daily claims
Day 1: swap 1000 → entitled to 1190 (19% bonus)
Day 2+: claim ~42.5 tokens per day for 28 days
Old tokens burned immediately, new tokens vest gradually. The strongest commitment mechanism — irreversible destruction + illiquid new tokens.
param2 = vest_duration (seconds)
param3 = claim_interval (seconds)
Example: 60-day vest, weekly claims
Swap: 5000 old tokens burned forever
Week 1: claim ~583 new tokens
Week 8+: claim final remainder
Send SOL (lamports, not SPL tokens) to buy new tokens at a fixed rate. Direct SOL-to-token sale.
param0 = tokens_per_sol (in raw units per 1 SOL)
param2 = cap (optional, total tokens to sell)
Example: param0 = 1000000000 (1000 tokens per SOL, 6 decimals)
Send 5 SOL → receive 5,000 tokens
# Amount is in lamports (1 SOL = 1,000,000,000 lamports)
$ aex migrate swap <pool> 5000000000 --keypair wallet.json
Set up a referral link for any migration pool with the REF flag, share it with others, earn rewards when they migrate, and claim your accumulated rewards.
$ aex migrate ref-init <pool_address> --keypair your_wallet.json
Referral link created!
Pool: <pool_address>
Your RefLink PDA: 4Kxp...7mNq
Level: 0 (direct)
Your referral "link" is just your public key. Share it — friends add --referrer <your_pubkey> to their swap.
$ aex migrate swap <pool> 5000000000 --referrer <your_pubkey> --keypair friend.json
Friend gets full 5,000 tokens.
You get credited: 5,000 * 5% = 250 tokens (from vault).
$ aex migrate ref-show <pool> --keypair your_wallet.json
$ aex migrate ref-claim <pool> --keypair your_wallet.json
Alice (L3) → Bob (L2) → Carol (L1) → User Dave
$ aex migrate ref-init <pool> --keypair alice.json
$ aex migrate ref-init <pool> --parent <alice_pubkey> --keypair bob.json
$ aex migrate ref-init <pool> --parent <bob_pubkey> --keypair carol.json
Dave swaps 10,000 tokens:
Carol (L1): 10,000 * 5% = 500 tokens
Bob (L2): 500 * 50% = 250 tokens
Alice (L3): 250 * 25% = 62 tokens
| Pool Config | Per $10K Migration | Your L1 Earning |
|---|---|---|
| 300 bps (3%) | $10,000 | $300 |
| 500 bps (5%) | $10,000 | $500 |
| 800 bps (8%) | $10,000 | $800 |
| 1000 bps (10%) | $10,000 | $1,000 |
| 1500 bps (15%) | $10,000 | $1,500 |
The complete guide for pool creators: create a pool, deposit tokens, monitor, handle emergencies, close, and reclaim.
$ aex migrate create <old_mint> <new_mint> --type 0 \
--start $(date -d '+1 hour' +%s) \
--end $(date -d '+30 days' +%s) \
--name "ALPHA to OMEGA" \
--desc "Token rebrand migration" \
--keypair authority.json
$ aex migrate deposit <pool> <amount_raw> --keypair authority.json
$ aex tui → [8] → [i] → [Enter]
Watch: Migrated count, Users, Remaining balance, Progress bar.
$ aex migrate pause <pool> --keypair authority.json
$ aex migrate close <pool> --keypair authority.json
Remaining new tokens returned to your wallet.
Collected old tokens returned to your wallet.
$ aex migrate auth <pool> --step init --new-auth <pubkey> --keypair authority.json
$ aex migrate auth <pool> --step complete --keypair new_authority.json
Predefined configurations combining migration types with referral settings. Use aex migrate templates to list all templates in the CLI.
On-chain referral tracking via RefLink PDAs (128 bytes). Enabled by setting the REF flag (0x40) on a migration pool. Supports up to 3 levels with configurable decay.
Multi-level reward flow: User swaps 10,000 tokens (pool: 5% L1, 50% L2 decay, 25% L3 decay) Carol (L1 referrer): 10,000 * 5% = 500 tokens Bob (L2 parent): 500 * 50% = 250 tokens Alice (L3 grandparent): 250 * 25% = 62 tokens Total referral cost: 812 tokens (from vault) User receives full 10,000 tokens (referral does NOT reduce output)
Key rules: Self-referral prevention (ERR_AUTH). Max referral cap: 2000 bps (20%). Referral rewards are never vested. Vault sufficiency checked before crediting.
| Code | Name | Description |
|---|---|---|
| 6000 | ERR_PAUSED | Pool is paused by authority |
| 6003 | ERR_ZERO | Amount too small or nothing to claim |
| 6010 | ERR_AUTH | Unauthorized (wrong authority, self-referral) |
| 6015 | ERR_DISC | Invalid account discriminator (wrong PDA type) |
| 6031 | ERR_MIG | Migration error (pool ended, not started, invalid type) |
| 6032 | ERR_CAP | Migration cap exceeded (global or per-wallet) |
| 6033 | ERR_CLOSED | Migration pool is closed |