Deposits
How deposits flow through the protocol - inflow detection, subaccounts, and share minting
Deposit Flow Overview
Step 1: User Sends Native Asset
The user sends assets to their unique deposit address:
Bitcoin Deposits
- User sends BTC to their Bitcoin deposit address
- Address derived from pool's threshold ECDSA key
- Requires 4 confirmations (~40 minutes)
Deposit addresses are currently only available for Bitcoin. Other assets must be supplied directly from a linked wallet.
Step 2: ckAsset Minting
Once the native transaction is confirmed:
- ckAsset minter detects the confirmed transaction
- Minter mints ckAsset tokens (ckBTC, ckETH, etc.)
- Tokens credited to user's inflow subaccount
Inflow Subaccount Encoding
Each user has a unique deposit subaccount derived from their principal:
- Prefix byte
0x1indicates deposit type - Followed by principal length and bytes
- Padded to 32 bytes
Step 3: Inflow Detection
The pool scans for new deposits every 60 seconds by querying the ledger for transactions since the last seen index. For each transaction to a pool subaccount, it decodes the subaccount type and schedules processing.
Key Features:
- Batch processing: Up to 10,000 transactions per scan
- Archive support: Fetches from ledger archives if needed
- Debouncing: Each subaccount processed once per scan
- Persistent tracking: Last seen index stored in stable storage
Step 4: Transfer to Treasury
After detection, funds are transferred from the user's subaccount to the pool treasury. The treasury is the pool's main account with no subaccount - all pool liquidity is held here.
Step 5: Treasury Movement Detection
The pool monitors treasury for incoming transfers every 60 seconds. When it detects a transfer from an inflow subaccount, it decodes the source to identify the user and creates a DepositConfirmed event.
Step 6: Event Notification
Queued events are sent to the lending canister. The event queue is persistent (survives canister upgrades), retries on failure, and processes up to 100 events per tick.
Step 7: Share Minting
The lending canister processes the deposit event:
- Checks idempotency (skip if already processed)
- Syncs pool indices
- Validates supply cap
- Mints shares:
shares = deposit_amount / lending_index
Example: User deposits 1.0 BTC at lending_index = 1.05 → 0.952 shares minted. Later, when index = 1.10: Balance = 0.952 × 1.10 = 1.0472 BTC (earned 4.72%)
Timing Summary
| Step | Trigger | Latency |
|---|---|---|
| Native tx confirmation | Blockchain | Varies by chain |
| ckAsset minting | Minter | Immediate |
| Inflow detection | Timer | ~60 sec |
| Treasury transfer | WAL | ~30 sec |
| Treasury detection | Timer | ~60 sec |
| Event notification | Timer | ~60 sec |
| Share minting | Event | Immediate |
Total (after blockchain confirmation): ~3-4 minutes
Error Handling
Multiple layers prevent double-crediting:
- Ledger index tracking: Each transaction processed once
- PROCESSED_INFLOWS set: Event deduplication
- Subaccount debouncing: One job per subaccount per scan
Deposits are automatically detected. Users just need to send assets to their deposit address - no additional action required.