We Build Launchpad Platforms for Token Sales
Launchpad platforms for token sales require a delicate balance: they must be open enough to attract participants while remaining resistant to MEV, sniping, and sybil attacks. Our team has spent over 7 years in DeFi and launched 15+ launchpad projects that collectively raised over $500 million. A typical launchpad attracts between $500,000 and $50 million, and our architecture reduces transaction costs by 25% through optimized smart contracts.
Why a Launchpad Is More Than Just a Contract
Smart contracts are only half the story. A production-grade launchpad includes a participant and admin frontend, KYC integration, Merkle tree generation for whitelists, a backend for monitoring, and a platform economy model. Every detail impacts security and user experience. According to our data, 70% of development time goes into backend and UX, not smart contracts.
Key Mechanics of Launchpad Platforms for Token Sales
Sale Structures
We implement three main sale models, each with its own mechanics:
Fixed Price Sale
The simplest model. Price is fixed, and the first X participants receive allocations. Problem: bots grab allocations in the first block. Our solution: Merkle whitelist and per-block limits.
Overflow / Oversubscription Model
Participants can contribute any amount, and the final price is determined by total volume. If the target is oversubscribed 3x, each participant receives 1/3 of their contribution back and the rest is converted to tokens. This model is used by platforms like Polkastarter and CoinList.
Dutch Auction
The price starts high and decreases until the entire supply is sold. This discovers the market's "fair price" and is resistant to sniping. Learn more on Wikipedia: Dutch auction.
// Dutch Auction sale
contract DutchAuctionSale {
uint256 public immutable startPrice;
uint256 public immutable endPrice;
uint256 public immutable startTime;
uint256 public immutable endTime;
uint256 public immutable totalTokensForSale;
uint256 public tokensSold;
mapping(address => uint256) public contributions;
function currentPrice() public view returns (uint256) {
if (block.timestamp <= startTime) return startPrice;
if (block.timestamp >= endTime) return endPrice;
uint256 elapsed = block.timestamp - startTime;
uint256 duration = endTime - startTime;
uint256 priceDrop = startPrice - endPrice;
return startPrice - (priceDrop * elapsed / duration);
}
function buy(uint256 tokenAmount) external payable nonReentrant {
require(block.timestamp >= startTime && block.timestamp <= endTime, "Not active");
uint256 price = currentPrice();
uint256 cost = tokenAmount * price / 1e18;
require(msg.value >= cost, "Insufficient ETH");
require(tokensSold + tokenAmount <= totalTokensForSale, "Exceeds supply");
tokensSold += tokenAmount;
contributions[msg.sender] += tokenAmount;
// Return excess
if (msg.value > cost) {
payable(msg.sender).transfer(msg.value - cost);
}
}
}
Comparison of Sale Models
| Model | Advantages | Disadvantages | When to Use |
|---|---|---|---|
| Fixed price | Simple implementation | Bots, unfair distribution | Early investors with whitelist |
| Overflow | Bot-resistant, fair distribution | Harder to understand | Mass IDOs |
| Dutch auction | Price discovery | Slow, complex implementation | Large projects |
Whitelist and Allocation
Merkle Tree Whitelist
The standard for gas-efficient whitelisting. The address list is stored off-chain; only the root is kept on-chain. A participant provides a proof when buying:
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
bytes32 public merkleRoot;
function buyWithWhitelist(
uint256 tokenAmount,
uint256 maxAllocation, // allocation for this address (from the list)
bytes32[] calldata merkleProof
) external payable {
// Verify that the address is in the whitelist with the specified allocation
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, maxAllocation));
require(
MerkleProof.verify(merkleProof, merkleRoot, leaf),
"Not whitelisted or wrong allocation"
);
require(
contributions[msg.sender] + tokenAmount <= maxAllocation,
"Exceeds allocation"
);
// ... purchase logic
}
Updating the Merkle root is cheaper than maintaining an on-chain mapping of all addresses.
Tiered Allocation
A model used by leading launchpads (DAO Maker, GameFi, RedKite): allocation size depends on the amount of platform tokens staked. Participants are divided into tiers (Bronze/Silver/Gold/Diamond), each with a guaranteed allocation proportional to their stake.
struct TierConfig {
uint256 minStake; // minimum stake to enter the tier
uint256 allocationMultiplier; // in basis points, 10000 = 1x
uint256 guaranteedSlots; // guaranteed slots (0 = lottery)
}
TierConfig[] public tiers;
function getUserTier(address user) public view returns (uint256) {
uint256 staked = stakingContract.stakedAmount(user);
for (uint256 i = tiers.length; i > 0; i--) {
if (staked >= tiers[i-1].minStake) return i-1;
}
return type(uint256).max; // not in a tier
}
function getUserAllocation(address user) public view returns (uint256) {
uint256 tierIndex = getUserTier(user);
if (tierIndex == type(uint256).max) return 0;
uint256 baseAllocation = totalSaleAmount / totalWhitelistedUsers;
return baseAllocation * tiers[tierIndex].allocationMultiplier / 10000;
}
Vesting and Claiming
After an IDO, tokens are typically not distributed immediately – it's an industry standard. Typical vesting for a launchpad: 20% at TGE, the rest linear over 6–12 months.
contract TokenVesting {
struct VestingSchedule {
uint256 totalAmount;
uint256 claimedAmount;
uint256 tgePercent; // % available immediately after TGE
uint256 cliffDuration; // delay before linear vesting
uint256 vestingDuration; // duration of linear vesting
uint256 tgeTimestamp;
}
mapping(address => VestingSchedule) public schedules;
function claimableAmount(address beneficiary) public view returns (uint256) {
VestingSchedule storage schedule = schedules[beneficiary];
if (schedule.totalAmount == 0) return 0;
uint256 tgeAmount = schedule.totalAmount * schedule.tgePercent / 10000;
if (block.timestamp < schedule.tgeTimestamp) {
return 0;
}
uint256 cliffEnd = schedule.tgeTimestamp + schedule.cliffDuration;
if (block.timestamp < cliffEnd) {
return tgeAmount > schedule.claimedAmount
? tgeAmount - schedule.claimedAmount
: 0;
}
uint256 vestingStart = cliffEnd;
uint256 vestingEnd = vestingStart + schedule.vestingDuration;
uint256 elapsed = min(block.timestamp, vestingEnd) - vestingStart;
uint256 vestedLinear = (schedule.totalAmount - tgeAmount)
* elapsed / schedule.vestingDuration;
uint256 totalVested = tgeAmount + vestedLinear;
return totalVested > schedule.claimedAmount
? totalVested - schedule.claimedAmount
: 0;
}
function claim() external nonReentrant {
uint256 amount = claimableAmount(msg.sender);
require(amount > 0, "Nothing to claim");
schedules[msg.sender].claimedAmount += amount;
saleToken.safeTransfer(msg.sender, amount);
emit TokensClaimed(msg.sender, amount);
}
}
How We Protect the Launchpad from Bots
Bots monitor the mempool and try to buy in the first block of a sale. We use a combination of defenses:
-
Commit-reveal– A participant first sendscommit = keccak256(amount, salt, address), then revealsamountandsaltin the next phase. Bots cannot know the exact amount until reveal. -
Randomized start– The exact start time is offset by a random delay (e.g., 0–300 seconds) using Chainlink VRF. -
Per-block limit– No more than X purchases per block, or a maximum amount per block:
uint256 public maxContributionPerBlock;
mapping(uint256 => uint256) public blockContributions;
function buy(uint256 amount) external payable {
require(
blockContributions[block.number] + amount <= maxContributionPerBlock,
"Block limit reached"
);
blockContributions[block.number] += amount;
// ...
}
Losses from bots can be up to $2 million per sale – our defenses are designed to prevent that.
KYC Integration
For regulated markets, we integrate with KYC providers. The frontend collects KYC data (via Sumsub, Onfido, or Synaps) and issues a signed JWT. Our backend verifies the JWT and adds the address to the whitelist via a transaction.
A more on-chain approach uses Verifiable Credentials: the KYC provider issues a VC, and the user provides a ZK-proof that they hold a valid VC without revealing personal data. Implementations include Polygon ID and Worldcoin (with privacy considerations).
How to Set Up a Merkle Whitelist in 5 Steps
- Collect the list of addresses and their allocations in a CSV.
- Generate a Merkle tree using a script (e.g., Node.js with ethers.js).
- Upload the root hash to the contract during deployment.
- For each participant, generate a proof (set of hashes) and pass it via the frontend.
- The participant calls
buyWithWhitelistwith the proof, amount, and allocation. The contract verifies the proof and allows the purchase.
Admin Panel and Listing Management
A launchpad is not just smart contracts. A complete product includes:
For projects (listing):
- Application form with token contract verification
- Admin workflow for approval/rejection
- Sale parameter configuration: price, hard cap, soft cap, dates, whitelist, vesting
- Upload whitelist CSV → Merkle tree generation
For participants:
- Dashboard with active and past sales
- KYC onboarding
- Whitelist registration with connected wallet
- Claim interface with vesting schedule
For admins:
- Real-time sale progress monitoring
- Emergency pause
- Whitelist management (add/remove)
- Withdrawal of raised funds after finalization
Platform Economics
Launchpads typically monetize through:
- A percentage of the raise – 3–8% of funds collected
- A token allocation – X% of the project's tokens
- Platform token – staking for allocations (ecosystem lock-in)
Development Phases
| Phase | Content | Duration |
|---|---|---|
| Design | Sale mechanics, vesting schedules, tier structure, tokenomics | 2–3 weeks |
| Core contracts | Sale, Vesting, Staking, Whitelist | 4–5 weeks |
| Testing | Unit, integration, fork tests, fuzz | 2–3 weeks |
| Backend | API, Merkle tree generation, KYC integration | 3–4 weeks |
| Frontend | Participant dashboard, admin panel | 4–5 weeks |
| Audit | Contracts + backend | 3–4 weeks |
| Testnet pilot | One test IDO | 2–3 weeks |
Total: 20–27 weeks. An audit is critical – launchpads hold participants' funds and are prime targets for attacks.
What's Included in Our Work
- Smart contracts with source code and documentation
- Architectural documentation and diagrams
- Frontend panel for participants and admins
- KYC provider integration
- Merkle tree setup for whitelist
- Deployment scripts and migrations
- Audit reports (external audit)
- 3 months of technical support after launch
Evaluate our expertise – order a consultation. Contact us to discuss your launchpad architecture. Order turnkey development with audit and technical support.







