White-label launchpad development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
White-label launchpad development
Medium
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1238
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    867
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1080
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    829

White-Label Launchpad Development

White-label launchpad—not "make Polkastarter but with your logo". Clients coming with this brief usually miss main point: Polkastarter and TrustPad work because behind them stands liquidity and community. Technically reproducing platform—not hard. But white-label launchpad valuable only when there's incoming stream of projects wanting to conduct IDO and community ready to participate. Therefore technical solution must be flexible—so owner can differentiate not via features but via exclusive projects and deal flow.

White-label Solution Architecture

Right architecture built around parametrization, not forks. Each client gets:

  • Own set of smart contracts (doesn't share contracts with other clients)
  • Customizable frontend with branding
  • Admin panel for managing pools and tier system
  • Own platform token (optionally)

Alternative—SaaS model on shared infrastructure with data isolation, but that's not full white-label.

Core Contract System

// Pool factory—central platform contract
contract LaunchpadFactory is AccessControl, Pausable {
    bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
    
    // Registry of all pools created via this factory
    address[] public allPools;
    mapping(address => bool) public isValidPool;
    mapping(address => address[]) public projectPools; // project → their pools
    
    // Platform parameters
    address public feeRecipient;
    uint256 public platformFee;  // basis points (200 = 2% of raise)
    
    // Whitelist approved sale token
    mapping(address => bool) public approvedTokens;
    
    event PoolCreated(
        address indexed pool,
        address indexed saleToken,
        address indexed creator,
        PoolType poolType
    );
    
    enum PoolType { FIXED_PRICE, DUTCH_AUCTION, OVERFLOW }
    
    function createPool(
        PoolType poolType,
        bytes calldata poolParams
    ) external onlyRole(OPERATOR_ROLE) whenNotPaused returns (address pool) {
        if (poolType == PoolType.FIXED_PRICE) {
            FixedPricePool.Config memory config = abi.decode(poolParams, (FixedPricePool.Config));
            require(approvedTokens[address(config.saleToken)], "Token not approved");
            pool = address(new FixedPricePool(config, feeRecipient, platformFee));
        } else if (poolType == PoolType.DUTCH_AUCTION) {
            pool = address(new DutchAuctionPool(abi.decode(poolParams, (DutchAuctionPool.Config)), feeRecipient, platformFee));
        } else {
            pool = address(new OverflowPool(abi.decode(poolParams, (OverflowPool.Config)), feeRecipient, platformFee));
        }
        
        allPools.push(pool);
        isValidPool[pool] = true;
        emit PoolCreated(pool, address(0), msg.sender, poolType);
        return pool;
    }
}

Tier System with Platform Token

Staking platform token—main mechanism retaining users and creating value for launchpad's own token:

contract LaunchpadStaking is ReentrancyGuard, Ownable {
    IERC20 public immutable platformToken;
    
    struct TierConfig {
        string name;           // "Bronze", "Silver", "Gold", "Diamond"
        uint256 minStake;      // minimum stake in platform token
        uint256 weight;        // weight in allocation distribution (basis points)
        bool guaranteed;       // guaranteed allocation or lottery
        uint256 multiplier;    // allocation multiplier (10000 = 1x)
    }
    
    TierConfig[] public tiers;
    
    struct StakeInfo {
        uint256 amount;
        uint256 stakedAt;
        uint256 lockUntil;    // lock period before IDO snapshots
    }
    
    mapping(address => StakeInfo) public stakes;
    uint256 public snapshotBlock; // block for snapshot before IDO
    mapping(uint256 => mapping(address => uint256)) public snapshotStakes;
    
    // snapshot tier for specific IDO
    function takeSnapshot(uint256 poolId) external onlyOwner {
        // Fix balances at snapshot moment
        // Further changes don't affect allocation in this IDO
        snapshotBlock = block.number;
        emit SnapshotTaken(poolId, block.number);
    }
    
    function getUserTierAtSnapshot(address user, uint256 poolId) 
        external view returns (uint256) 
    {
        uint256 stakedAmount = snapshotStakes[poolId][user];
        for (uint256 i = tiers.length; i > 0; i--) {
            if (stakedAmount >= tiers[i-1].minStake) return i - 1;
        }
        return type(uint256).max;
    }
}

Lottery for Lower Tiers

For Tier 1/2 (low stake) usually can't give everyone guaranteed allocation. Use lottery:

contract AllocationLottery {
    // Chainlink VRF for verifiable randomness
    VRFCoordinatorV2Interface public coordinator;
    bytes32 public keyHash;
    uint64 public subscriptionId;
    
    mapping(uint256 => address[]) public lotteryParticipants; // poolId → participants
    mapping(uint256 => uint256) public requestToPool;
    
    function requestLotteryResult(uint256 poolId) external onlyOwner returns (uint256 requestId) {
        requestId = coordinator.requestRandomWords(
            keyHash,
            subscriptionId,
            3,    // confirmations
            100000, // gas limit for callback
            1     // numWords
        );
        requestToPool[requestId] = poolId;
    }
    
    function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
        uint256 poolId = requestToPool[requestId];
        address[] storage participants = lotteryParticipants[poolId];
        
        uint256 winners = winnersCount[poolId];
        uint256 rand = randomWords[0];
        
        // Fisher-Yates shuffle for fair winner selection
        for (uint256 i = 0; i < winners && i < participants.length; i++) {
            uint256 j = i + (rand % (participants.length - i));
            (participants[i], participants[j]) = (participants[j], participants[i]);
            rand = uint256(keccak256(abi.encode(rand, i)));
        }
        
        // First `winners` addresses—winners
        emit LotteryCompleted(poolId, winners);
    }
}

Multi-chain Support

Modern white-label launchpad should support multiple networks—EVM-compatible (Ethereum, BNB Chain, Polygon, Arbitrum, Avalanche) at minimum. Architectural approach:

  • Same contract codebase deployed to each network
  • Frontend switches networks via wagmi chain config
  • Subgraph (The Graph) deployed separately per network
  • Backend API aggregates data across networks via multicall
// wagmi config for multi-chain
import { createConfig, http } from "wagmi";
import { mainnet, polygon, bsc, arbitrum, avalanche } from "wagmi/chains";

export const config = createConfig({
    chains: [mainnet, polygon, bsc, arbitrum, avalanche],
    transports: {
        [mainnet.id]: http(process.env.ETH_RPC),
        [polygon.id]: http(process.env.POLYGON_RPC),
        [bsc.id]: http(process.env.BSC_RPC),
        [arbitrum.id]: http(process.env.ARB_RPC),
        [avalanche.id]: http(process.env.AVAX_RPC),
    },
});

KYC/AML Integration

Most jurisdictions require KYC for token sale participation. Integration with Sumsub or Synaps:

// API endpoint for KYC status
app.get("/api/kyc/status/:address", async (req, res) => {
    const { address } = req.params;
    
    // Check status in database
    const kycRecord = await db.kyc.findOne({ walletAddress: address.toLowerCase() });
    
    if (!kycRecord || kycRecord.status !== "approved") {
        return res.json({ approved: false, reason: kycRecord?.rejectionReason });
    }
    
    // Optionally: record on-chain via verified backend
    // for platforms with on-chain KYC verification
    
    res.json({ approved: true, tier: kycRecord.accreditationLevel });
});

Admin Panel

Platform operator functionality:

Section Features
Pool management Create/edit/close pools
Project KYC Verify projects requesting IDO
Whitelist Upload and manage whitelists
Allocation Manual allocation adjustment
Tier config Configure levels and minimum stakes
Analytics Raised by pools, active users, conversions
Fee management Configure platform commissions

Monetization Models

White-label launchpad can monetize several ways:

  • Platform fee: 1.5–3% of raised amount on successful IDO
  • Token allocation: 3–5% of sale tokens for platform services
  • Staking APY: staker yields partially financed from platform fees
  • Premium listing: increased visibility for paying projects
  • White-label licensing: if selling platform to other operators