Withdrawals
How withdrawals flow through the protocol - standard vs boosted paths, fee handling
Withdrawal Flow Overview
Two-Phase Execution
Phase 1: Synchronous (Atomic)
All state changes happen atomically before any async work:
- Verify signature
- Sync pool indices
- Burn supply shares
- Check health factor - if too low, rollback share burn and return error
- Schedule async withdrawal
Phase 2: Asynchronous (WAL-backed)
The actual withdrawal executes in the background via the Write-Ahead Log. The WAL handles retries on failure and ensures the operation eventually completes.
Outflow Subaccounts
When the pool receives a withdrawal request, it transfers funds to an outflow subaccount:
| Pool | Encoding | Description |
|---|---|---|
| BTC | Mapped index | Bitcoin addresses mapped to u128 indices |
| ERC | Direct encoding | Ethereum addresses (20 bytes) fit directly |
| IC Principal | Native format | For transfers to IC principals |
Standard vs Boosted Withdrawals (BTC)
The BTC Pool uses two withdrawal paths based on amount:
Standard Withdrawal (Over 50,000 sats)
Direct ckBTC burn via the minter:
Characteristics:
- 1:1 economic efficiency
- User receives BTC after ~6 confirmations
- Higher effective fee ratio for small amounts
Boosted Withdrawal (Under 50,000 sats)
Batched withdrawal for fee efficiency:
Characteristics:
- Pool fronts BTC from its UTXOs
- Multiple withdrawals batched into one transaction
- Lower effective fees (shared across batch)
- 0.3% boost fee deducted
- Faster user experience
Decision Logic
If amount is under or equal to 50,000 sats, use boosted path (transfer to boost subaccount, add to queue). Otherwise, use standard path (direct ckBTC burn).
ERC Withdrawals with Gas Fee Fronting
ERC-20 withdrawals require Ethereum gas fees. The pool:
- Gets current ETH gas price from oracle
- Converts to pool token equivalent
- Fronts ckETH gas from FEE_SUBACCOUNT
- Deducts fee from withdrawal amount
- Burns both ckETH (gas) and ckToken (withdrawal)
- Sends native token to user on Ethereum
Idempotency
Withdrawals have multiple deduplication layers:
- Request ID tracking - each withdrawal has a unique ID
- WAL operation ID - unique OpId per operation
- Ledger timestamp - ICRC-1 transfers include timestamps for duplicate detection
Error Handling
| Error | Cause | Recovery |
|---|---|---|
| Health factor violation | Withdrawal would make position liquidatable | Rollback share burn, return error |
| Insufficient liquidity | Pool doesn't have enough funds | WAL retries when liquidity available |
| Network failures | Inter-canister call fails | WAL retries with exponential backoff |
Withdrawals may reduce your health factor. Ensure you maintain adequate collateral to avoid liquidation.