How Does an IEO Platform Work?
Every IEO platform faces three critical challenges: fair allocation distribution, protection from manipulation, and regulatory compliance. How you solve these determines investor trust and project success. We develop IEO platforms—full solutions for Initial Exchange Offering that don't just sell tokens but ensure project verification, fair allocation distribution, and exchange integration. Binance Launchpad and KuCoin Spotlight are examples of such systems. A custom platform gives you full control over fees, sale conditions, and liquidity. We help guide you from concept to launch, including smart contract audit. We have been on the market for over 5 years and have delivered more than 15 launchpad projects, so we know all the pitfalls.
Platform Components
| Component | Responsibility |
|---|---|
| Project Registry | Verification and storage of project data |
| Allocation Engine | Distribution of lots among participants |
| KYC/AML Gateway | Integration with verification provider |
| Token Sale Contract | On-chain sale execution |
| Staking Contract | Platform token staking for tier system |
| Distribution Contract | Vesting and token claim |
| Admin Dashboard | Management of projects, sale parameters |
How Allocation Distribution Works
There are two main approaches.
Guaranteed Allocation
Each participant gets a guaranteed allocation proportional to their tier. This is a simple and predictable method, but some tokens may remain unsold.
contract GuaranteedSale {
mapping(address => uint256) public maxAllocation;
mapping(address => uint256) public purchased;
function buy(uint256 amount) external payable {
require(saleActive(), "Sale not active");
require(purchased[msg.sender] + amount <= maxAllocation[msg.sender], "Exceeds allocation");
uint256 cost = amount * price;
require(msg.value >= cost, "Insufficient ETH");
purchased[msg.sender] += amount;
totalSold += amount;
if (msg.value > cost) payable(msg.sender).transfer(msg.value - cost);
}
}
Lottery with Oversubscription
A fairer approach when demand is high. Participants register, then a random selection of winners proportional to their tier is made. In practice, a lottery using Chainlink VRF generates 3 times fewer complaints about unfairness compared to guaranteed allocation under oversubscription. This is confirmed by data from major launchpads—Polkastarter and TrustPad switched to lottery for this reason.
Why Chainlink VRF Is Mandatory
For a fair on-chain lottery, verifiable randomness is essential. blockhash or block.timestamp can be manipulated by validators, so we use Chainlink VRF—the security standard for launchpad platforms.
contract LotteryAllocation is VRFConsumerBaseV2Plus {
mapping(uint256 => address[]) public tierParticipants;
mapping(address => bool) public isWinner;
uint256 public randomSeed;
function register() external {
require(registrationActive(), "Registration closed");
StakeInfo memory info = staking.stakes(msg.sender);
require(info.tier > 0, "No tier");
tierParticipants[info.tier].push(msg.sender);
}
function requestRandomness() external onlyOwner {
uint256 requestId = s_vrfCoordinator.requestRandomWords(
VRFV2PlusClient.RandomWordsRequest({
keyHash: keyHash,
subId: subscriptionId,
requestConfirmations: 3,
callbackGasLimit: 500000,
numWords: 1,
extraArgs: VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
)
})
);
}
function fulfillRandomWords(uint256, uint256[] calldata randomWords) internal override {
randomSeed = randomWords[0];
_selectWinners();
}
function _selectWinners() internal {
uint256 seed = randomSeed;
for (uint8 tier = 5; tier >= 1; tier--) {
uint256 winnersForTier = tierWinners[tier];
address[] storage participants = tierParticipants[tier];
uint256 shuffleLen = participants.length;
for (uint256 i = 0; i < winnersForTier && i < shuffleLen; i++) {
uint256 j = i + (uint256(keccak256(abi.encodePacked(seed, tier, i))) % (shuffleLen - i));
(participants[i], participants[j]) = (participants[j], participants[i]);
isWinner[participants[i]] = true;
seed = uint256(keccak256(abi.encodePacked(seed, i)));
}
}
}
}
How to Set Up a Tier System
Most successful platforms (Polkastarter, TrustPad) use a model: the more platform tokens a user has staked, the higher their allocation priority. Typical tiers: 100 tokens—Bronze, 1000—Silver, 5000—Gold. Each tier gives an allocation multiplier: x1, x3, x10. Such a system increases user engagement by 2 times compared to fixed allocations.
contract TierStaking {
struct Tier {
uint256 minStake;
uint256 multiplier;
uint256 poolWeight;
}
Tier[] public tiers;
struct StakeInfo {
uint256 amount;
uint256 stakedAt;
uint256 lockEnd;
uint8 tier;
}
mapping(address => StakeInfo) public stakes;
function stake(uint256 amount, uint256 lockDuration) external {
require(lockDuration >= MIN_LOCK, "Lock too short");
token.safeTransferFrom(msg.sender, address(this), amount);
uint8 tier = calculateTier(amount);
stakes[msg.sender] = StakeInfo({
amount: amount,
stakedAt: block.timestamp,
lockEnd: block.timestamp + lockDuration,
tier: tier
});
emit Staked(msg.sender, amount, tier);
}
function calculateTier(uint256 amount) public view returns (uint8) {
for (uint8 i = uint8(tiers.length - 1); i >= 0; i--) {
if (amount >= tiers[i].minStake) return i;
}
return 0;
}
}
KYC/AML Integration
An IEO platform must comply with regulatory requirements. We use SaaS providers: Fractal ID, Synaps, or Sumsub. After verification, the address is added to an on-chain whitelist. An alternative approach is Soulbound tokens (EIP-5484), where KYC status is represented as a non-transferable NFT. Contact us to select the optimal KYC solution.
Escrow and Fund Distribution
Sale proceeds should not go directly to the project—standard buyer protection. We use escrow with milestones:
contract IEOEscrow {
struct Milestone {
string description;
uint256 releasePercent;
uint256 releaseTime;
bool approved;
uint256 approvalVotes;
uint256 rejectionVotes;
}
Milestone[] public milestones;
uint256 public totalRaised;
address public project;
function voteMilestone(uint256 milestoneId, bool approve) external {
require(projectToken.balanceOf(msg.sender) > 0, "Must hold tokens");
}
function releaseFunds(uint256 milestoneId) external {
Milestone storage ms = milestones[milestoneId];
require(ms.approved, "Not approved");
require(block.timestamp >= ms.releaseTime, "Too early");
uint256 amount = (totalRaised * ms.releasePercent) / 100;
payable(project).transfer(amount);
}
}
Listing and Post-Sale Liquidity
A portion of raised funds is automatically added to a DEX to provide initial liquidity. LP tokens are then locked for 180 days.
function finalizeAndAddLiquidity() external onlyOwner {
require(saleFinished(), "Sale not finished");
uint256 liquidityETH = (totalRaised * liquidityPercent) / 100;
uint256 liquidityTokens = calculateLiquidityTokens(liquidityETH);
token.approve(address(uniswapRouter), liquidityTokens);
uniswapRouter.addLiquidityETH{value: liquidityETH}(
address(token),
liquidityTokens,
0,
0,
address(this),
block.timestamp + 3600
);
lpLockEnd = block.timestamp + 180 days;
}
Typical Mistakes in Launchpad Development
- Using simple
blockhashfor lottery—this allows validators to manipulate the outcome. Instead, use provably fair randomness (Chainlink VRF): a lottery with VRF is 3 times more effective in preventing disputes. - Incorrect vesting setup—if project tokens can be withdrawn instantly, it increases the risk of dumping. Set vesting with a linear distribution over 6–12 months.
- No escrow—investor funds go directly to the project, and if conditions are not met, they cannot be recovered. Escrow with milestones is mandatory.
- Insufficient gas optimization testing—unoptimized contracts can cost users extra fees (for a large sale, commissions can exceed $50,000). Conduct thorough testing and optimization.
What Is Included
- Requirements audit and technical specification
- Development of smart contracts for staking, sale, escrow
- Backend API and admin panel
- KYC/AML integration
- Frontend for users
- Security audit of contracts by third-party teams (costs start from $30k)
- Testing and deployment
Development Timeline
| Component | Timeline |
|---|---|
| Smart contracts (staking, sale, escrow, distribution) | 6–8 weeks |
| Backend API + admin panel | 4–6 weeks |
| KYC integration | 1–2 weeks |
| Frontend (user interface) | 4–6 weeks |
| Smart contract audit | 3–4 weeks |
| Testing + QA | 2–3 weeks |
The full cycle from specification to launch takes 4–5 months. The audit budget depends on complexity and chosen team. Contact us for an evaluation of your project. Get a consultation on the architecture.







