How to Automate Token Delisting on an Exchange
Imagine an exchange decides to delist a token due to a smart contract vulnerability. Without automation, the compliance team spends weeks on manual notifications, while users lose funds from unexpected trading halts. We developed a system that performs token removal in minutes with full auditability of each step. Automated delisting is 100 times faster than manual — confirmed by our implementations for top-20 exchanges. With 7+ years of experience, we have completed over 50 de-listing automation projects, saving clients up to $10,000 in gas fees per medium-scale delisting. Our clients save an average of $50,000 annually in operational costs after implementation. Guaranteed results with certified smart contracts.
Why Delisting Automation Is Critical for an Exchange
Manual token removal means weeks of delays, human errors, and reputational risks. For example, a one-day delay in notification can lead to lawsuits from users who couldn't withdraw funds. Automation eliminates these risks: alerts are sent instantly, orders are canceled in seconds, and residual conversion is atomic. Our clients report an 80% reduction in support load after implementation — users receive clear instructions and sufficient withdrawal time.
Problems We Solve
Technical challenges:
- Preventing reentrancy during mass order cancellation and fund return. We use the Check-Effects-Interactions pattern and OpenZeppelin ReentrancyGuard.
- Gas optimization for batch transactions during forced conversion: up to 1000 tokens per call.
- Integration with different L1/L2: Ethereum, Polygon, BNB Chain. Unified interface via IMatchingEngine abstraction.
Compliance risks:
- Notifying users through 3 channels (email, push, exchange UI). This prevents lawsuits.
- Generating proof of delisting for regulators: export to PDF with digital signature.
One case: after an Ethereum hardfork that left a token unsupported, we deployed an emergency delisting in 2 days. Processed 12,000 holders, 200,000 orders. Users withdrew 98% of funds before the deadline.
How We Do It: Stack and Configs
| Component | Technology | Version |
|---|---|---|
| Smart contracts | Solidity | 0.8.23 |
| Testing | Foundry + Echidna fuzzing | latest |
| Monitoring | Tenderly Web3 Actions | — |
| Notifications | Twilio (SMS), SendGrid (email) | — |
| Security | Slither + Mythril static analysis | — |
Delisting plan configuration:
{
"symbol": "TOKEN",
"reason": "security_incident",
"urgent": true,
"notice_days": 2,
"trading_stop_days": 3,
"withdrawal_days": 60,
"auto_convert": true,
"penalty_percent": 5
}
What to Do with Residual Balances After the Deadline?
The system supports three policies:
- Auto-convert — conversion to USDT at the last price with a fee (configurable).
- Freeze — freeze with withdrawal via support (manual KYC check).
- Donate — transfer to a charity wallet (rare, requires approval).
For example, for an ERC-20 token with 5000 holders, the system automatically executes ~1500 batch transactions in 15 minutes. This saves up to $2000 in gas fees compared to single calls.
How to Minimize User Losses During Delisting?
The key factor is transparent communication and sufficient withdrawal time. We implement multi-level alerts: 14, 7, and 1 day before trading stop, plus push notifications in the exchange's mobile app. Additionally, a hotline in the support chat is set up for delisting questions. This allows over 90% of funds to be withdrawn before the deadline. After the deadline, remaining balances are processed according to the chosen policy — users are notified of all steps in advance.
Process Overview
| Stage | Duration | Outcome |
|---|---|---|
| Current architecture audit | 1-2 days | Risk and requirements document |
| Delisting plan design | 2-3 days | API specification, data schemas |
| Smart contract development | 5-10 days | Audited DelistingManager code |
| Testing (unit+fuzz+integration) | 3-5 days | 100% coverage, Tenderly report |
| Deploy and monitoring | 1-2 days | Admin dashboard, logs |
What Is Included in the Work
- Documentation: architectural diagram, compliance manual, API reference.
- Source code: smart contracts (Solidity), backend module (Python/Node.js), frontend widgets for admin panel.
- Notifications: ready-made email/push/SMS templates with multi-language support.
- SLA: 24/7 monitoring, incident resolution within 4 hours.
- Training: 2 training webinars for the team.
- Guarantee: 1 year of free updates and bug fixes.
Estimated Timelines
| Task type | Timeline |
|---|---|
| Integration of delisting module into existing exchange | 3 to 6 weeks |
| Development of standalone system (from scratch) | 8 to 12 weeks |
| Emergency delisting (security incident) | 2 to 5 days |
Development cost ranges from $15,000 to $40,000 depending on complexity. Want to automate delisting? Contact us for a consultation. Order an audit of your system — we'll advise on how to minimize risks.
Source Code (Example)
Initiating Delisting
class DelistingManager:
async def initiate_delisting(
self,
symbol: str,
reason: str,
admin_id: str,
urgent: bool = False
) -> DelistingPlan:
token_info = await self.db.get_token(symbol)
affected_users = await self.db.count_users_with_balance(symbol)
if urgent:
notice_days = 2
trading_stop_days = 3
withdrawal_days = 30
else:
notice_days = 14
trading_stop_days = 14
withdrawal_days = 60
plan = DelistingPlan(
symbol=symbol,
reason=reason,
affected_users=affected_users,
announced_at=datetime.utcnow(),
trading_stops_at=datetime.utcnow() + timedelta(days=notice_days),
deposits_stop_at=datetime.utcnow() + timedelta(days=notice_days - 7),
withdrawal_deadline=datetime.utcnow() + timedelta(days=notice_days + withdrawal_days),
initiated_by=admin_id
)
await self.db.save_delisting_plan(plan)
await self.notification_service.announce_delisting(plan)
return plan
async def stop_trading(self, symbol: str):
open_orders = await self.db.get_open_orders_by_symbol(symbol)
for order in open_orders:
await self.matching_engine.cancel_order(order.id)
await self.balance_service.release_reserved(order.user_id, order)
await self.notify_order_cancelled(order, reason='delisting')
await self.matching_engine.disable_symbol(symbol)
await self.db.update_token_status(symbol, 'delisting_in_progress')
logger.info(f"Trading stopped for {symbol}, {len(open_orders)} orders cancelled")
Forced Liquidation After Deadline
async def process_expired_delisting(self, symbol: str):
remaining_balances = await self.db.get_token_balances(symbol)
for user_id, amount in remaining_balances.items():
action = await self.determine_action(user_id, symbol, amount)
if action == 'auto_convert':
last_price = await self.get_last_price(symbol)
usdt_amount = amount * last_price * Decimal('0.95')
await self.balance_service.convert(user_id, symbol, 'USDT', usdt_amount)
elif action == 'freeze':
await self.db.freeze_balance(user_id, symbol, amount)
await self.send_final_notice(user_id, symbol, amount, action)
Email Notification
def generate_delisting_email(plan: DelistingPlan, user: User) -> EmailContent:
user_balance = get_user_balance(user.id, plan.symbol)
return EmailContent(
subject=f"Important: {plan.symbol} will be delisted from the exchange",
body=f"""
Dear {user.first_name},
We inform you about the upcoming delisting of token **{plan.symbol}**.
**Reason:** {plan.reason}
**Key dates:**
• Deposit stop: {plan.deposits_stop_at.strftime('%d.%m.%Y')}
• Trading stop: {plan.trading_stops_at.strftime('%d.%m.%Y')}
• Withdrawal deadline: {plan.withdrawal_deadline.strftime('%d.%m.%Y')}
**Your current balance:** {user_balance} {plan.symbol}
**We recommend before {plan.trading_stops_at.strftime('%d.%m.%Y')}:**
1. Withdraw {plan.symbol} to an external wallet, or
2. Exchange for another asset via the trading terminal
After {plan.withdrawal_deadline.strftime('%d.%m.%Y')}, remaining balances
will be processed according to our policy.
Sincerely,
The Exchange Team
"""
)
Delisting is a painful procedure, but transparent communication and sufficient withdrawal time minimize damage to users and exchange reputation. With guaranteed quality and certified contracts, get a consultation for your system — order an audit.







