Crypto Exchange Referral Program Development
A referral program is one of the most effective user acquisition channels for a crypto exchange. The mechanics are simple: user A brings user B, receives a % of B's trading fees. But implementation has several non-trivial aspects: multi-level structures, real-time commission calculation, fraud prevention, and transparent dashboards.
Referral Program Structure
Single-level vs Multi-level
Single-level: referrer gets % only from direct referrals. Simple to implement.
Multi-level: referrer gets % from referrals of referrals (tree structure). Binance uses two-level: 20% from tier-1, 10% from tier-2.
CREATE TABLE referrals (
referrer_id UUID NOT NULL,
referee_id UUID NOT NULL UNIQUE, -- each user has one referrer
created_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (referrer_id, referee_id)
);
-- For multi-level: recursive CTE to get tree
WITH RECURSIVE referral_tree AS (
-- Base case: direct referrals
SELECT referrer_id, referee_id, 1 AS level
FROM referrals
WHERE referrer_id = $user_id
UNION ALL
-- Recursion: referrals of referrals
SELECT r.referrer_id, r.referee_id, rt.level + 1
FROM referrals r
JOIN referral_tree rt ON r.referrer_id = rt.referee_id
WHERE rt.level < 3 -- Limit depth
)
SELECT * FROM referral_tree;
Referral Links and Codes
A referral code is a unique string (6-8 characters) associated with a user. A user can have multiple codes for different campaigns and different rates.
import secrets
import string
def generate_referral_code(user_id: str) -> str:
alphabet = string.ascii_uppercase + string.digits
code = ''.join(secrets.choice(alphabet) for _ in range(8))
# Check uniqueness in database
while self.db.code_exists(code):
code = ''.join(secrets.choice(alphabet) for _ in range(8))
return code
# Referral link: https://exchange.com/register?ref=ABCD1234
# UTM parameters for analytics: ?ref=ABCD1234&utm_source=referral&utm_medium=link
Commission Calculation and Accrual
Accrual Formula
On each trade:
def calculate_referral_reward(trade: Trade, referrer: User) -> Decimal:
# Base referral program rate
base_rate = Decimal('0.20') # 20% of collected fee
# Bonus for referral network volume
volume_bonus = get_volume_tier_bonus(referrer.referral_network_volume_30d)
# Rate can be customized for partners
effective_rate = referrer.custom_referral_rate or (base_rate + volume_bonus)
# Reward size = trader's fee × referral rate
taker_fee = trade.fee_amount # already calculated at execution
reward = taker_fee * effective_rate
return reward.quantize(Decimal('0.00000001')) # 8 decimal places
Asynchronous Accrual
Referral accruals should not block trade execution. Pattern: trade completes, event is published to Kafka, referral service consumes asynchronously:
# referral_worker.py
async def process_trade_event(self, trade_event: dict):
trade_id = trade_event['trade_id']
user_id = trade_event['user_id']
fee_amount = Decimal(trade_event['fee_amount'])
fee_currency = trade_event['fee_currency']
# Find referrer of the user
referrer = await self.db.get_referrer(user_id)
if not referrer:
return
reward = self.calculate_reward(referrer, fee_amount)
if reward <= 0:
return
# Atomically: create record + credit balance
async with self.db.transaction():
await self.db.create_referral_earning(
referrer_id=referrer.id,
referee_id=user_id,
trade_id=trade_id,
amount=reward,
currency=fee_currency
)
await self.db.credit_balance(referrer.id, reward, fee_currency)
Anti-Fraud
Typical Abuse Patterns
Self-referral: user registers a second account using their own link, trades on it, and gets referral % from themselves. Detection: check device fingerprint, IP, and payment methods at registration and KYC.
Wash trading: two accounts trade against each other, generating volume for referral payouts. Detection: analyze counterparties — if % of trades between two accounts is anomalously high, it's suspicious.
Referral farm: mass registration of accounts from one source. Solution: CAPTCHA, SMS verification, require KYC for referral payouts.
def check_self_referral_risk(referrer_id: str, new_user: NewUser) -> RiskScore:
referrer = db.get_user(referrer_id)
score = 0
# Same IP at registration
if referrer.registration_ip == new_user.registration_ip:
score += 50
# Same device fingerprint
if referrer.device_fingerprint == new_user.device_fingerprint:
score += 40
# Same phone or email domain
if referrer.phone_prefix == new_user.phone_prefix and same_carrier(referrer, new_user):
score += 20
return RiskScore(score, 'block' if score >= 70 else 'flag')
Partner Program (Subaffiliates)
Large exchanges highlight "partners" — KOLs, influencers, crypto channels — with elevated rates and separate management:
| Level | Requirements | Rate |
|---|---|---|
| Standard | None | 20% |
| Silver | 50 referrals + $10K volume/month | 25% |
| Gold | 200 referrals + $50K volume/month | 30% |
| Partner | Contract + $500K volume/month | 40-50% |
Partners get custom dashboard with detailed analytics on their referral network, API access to data for embedding in their own products.
Dashboard and Analytics
The referral dashboard should show:
- Number of referrals (total, active last 30 days)
- Accumulated earnings by period
- Table of top referrals by volume (without revealing email/name)
- Real-time earnings counter for today
- Payment history with CSV export option
interface ReferralDashboard {
stats: {
totalReferrals: number;
activeReferrals30d: number;
totalEarned: Record<string, string>; // currency → amount
earnedToday: Record<string, string>;
pendingPayout: Record<string, string>;
};
topReferees: {
rank: number;
userId: string; // masked: "user***1234"
volume30d: string;
yourEarnings30d: string;
}[];
earningsHistory: {
date: string;
amount: string;
currency: string;
tradeId: string;
}[];
}
Transparency of accruals is key to trust. Users should see each accrual tied to a specific referee's trade.
Payouts and Tax Implications
Referral payouts are credited in real-time to trading balance. Withdrawal is a standard exchange withdrawal process. Some exchanges add a minimum threshold for referral income withdrawal.
In some jurisdictions (US, EU), referral payouts qualify as taxable income. The exchange must maintain payment history and, when thresholds are exceeded (e.g., $600/year in the US), provide tax forms. This requires collecting TIN/tax identification numbers from high-earning partners.







