Factory-based token migration dApp for BNB Chain with on-chain Merkle verification and delayed claims.
- Deploys per-project
Migratorcontracts fromMigratorFactory. - Lets holders prove eligibility from snapshot data and migrate via
approve -> migrate -> claim. - Supports CSV-based snapshots, optional Moralis holder fetch, and optional IPFS snapshot sharing.
- Includes owner-only project admin actions for funding and token withdrawals.
Token migrations need a deterministic way to map holders to allocations, collect old tokens, and release new tokens on a schedule.
MigrateFlow implements this with Merkle proofs on-chain and a web flow for project owners and holders.
- Token project teams migrating from a legacy token contract.
- Token holders claiming allocations from a published snapshot.
MigratorFactory.createMigrationdeploys migration contracts and assigns ownership to the caller.Migrator.migrateverifies Merkle proofs and records user allocations after old-token deposit.Migrator.claimunlocks new-token claims afterclaimStartTime.- Owner controls:
updateMerkleRoot,withdrawOldTokens,withdrawRemainingTokens. /createroute for migration creation and snapshot processing./project/[address]route for eligibility check, approval, deposit, and claim./api/snapshotintegration with Moralis and a 5,000-holder auto-fetch cap.- Optional IPFS snapshot upload/load using Pinata + gateway URLs.
- Smart contracts: Solidity
^0.8.20, Foundry, OpenZeppelin. - Frontend: Next.js (App Router), React, TypeScript, Tailwind CSS.
- Web3 client: wagmi, viem, ethers.
- Services: Moralis API, Pinata IPFS.
- Project owner opens
/create. - Enters old/new token addresses and claim delay.
- Builds a Merkle root from CSV data or Moralis holder data.
- Optionally uploads snapshot JSON to IPFS.
- Deploys a new migration contract through the factory.
- Holder opens
/project/[address](optionally with?snapshot=<cid>). - Loads snapshot from IPFS or uploads local snapshot JSON.
- Checks wallet eligibility and retrieves proof + amount.
- Approves old token allowance to the migration contract.
- Holder calls
migrate(amount, proof)to deposit old tokens and lock allocation. - After
claimStartTime, holder callsclaim()to receive new tokens. - Owner can fund reward pool and manage withdrawals from the project admin panel.
contracts/
src/ Core contracts (Migrator, MigratorFactory, mocks)
test/ Foundry tests
script/ Foundry deployment/admin scripts
broadcast/ Recorded script execution artifacts
frontend/
src/app/ Next.js routes and API route
src/components/ UI and owner admin panel
src/hooks/ Migration, vesting, snapshot hooks
src/utils/ Merkle, Moralis, IPFS utilities
scripts/
Local Merkle/hash debugging scripts
- Node.js 18+
- Foundry
cd contracts
forge install
forge build
forge test -vvvcd frontend
npm install
cp .env.example .env.local
npm run devcd scripts
npm install
node generateMerkle.js
node debugHash.js
node debugFullTree.js| Variable | Purpose |
|---|---|
NEXT_PUBLIC_RPC_URL |
BSC RPC URL used by wagmi transport |
NEXT_PUBLIC_PINATA_JWT |
Pinata JWT used for client-side IPFS upload |
NEXT_PUBLIC_GATEWAY_URL |
Base URL for IPFS snapshot retrieval |
MORALIS_API_KEY |
Key used by /api/snapshot route |
| Variable | Purpose |
|---|---|
PRIVATE_KEY |
Deployer key for Foundry broadcast scripts |
RPC_URL |
RPC URL used by script execution |
- Foundry scripts are included for factory deploy, migrator deploy, test token deploy, and Merkle root updates.
- Broadcast artifacts include:
- Chain 56 factory:
0x4c33aef2a64a1a91adb398a80a68858368441d34 - Chain 97 factory:
0xb39a6d3c95821f127220d3a33cbde5b59fe8ccd6
- Chain 56 factory:
- Frontend constants target the chain 56 factory.
- UI enforces BNB Chain for interactive flows.
- Auto-fetch is capped at 5,000 holders; larger sets require CSV import.
- Snapshot amount parsing assumes 18 decimals in current frontend paths.
- Claims require owner-funded new-token liquidity in each migration contract.
- Merkle root is owner-updatable.
- Snapshot persistence is localStorage-based per project address when not loaded by CID.
This repository currently has mixed SPDX headers (MIT and UNLICENSED) and no root LICENSE file.
- Broadcast
run-latest.jsonfiles are repository records and should be treated as deployment artifacts, not live-state guarantees.