Bybit Whitelist Onboarding (Risk 2 SOP)
When to run: Before any new (asset, chain, destination address, tag) tuple is referenced by a Bybit movement template. Why it’s manual: Bybit V5 does not expose an address-book write API. Whitelist entries are added only via the Bybit web UI, and every new entry triggers a 24-hour cooldown during which the address cannot receive withdrawals. The 24h timer is enforced server-side; there is no operator override.Source: Bybit V5 docs/v5/asset/withdraw/query-addressonly — nocreatecompanion. Verified 2026-05-12.
1. Pre-onboarding checklist
Before touching the Bybit UI:- Destination address is already an active QTG
allowed_addressesrow for the target venue (so on-chain executor preflight will accept it later). - Operator has logged Bybit address-book entries that already exist via
bybit_readonly_smoke --include-whitelist(requires Withdraw-scope key) — confirm the new entry is genuinely new and not a duplicate. - Memo/tag policy decided per asset:
- XRP / EOS / XLM: tag REQUIRED. Mismatched tag = funds permanently misrouted on Bybit’s side.
- ERC-20 / TRC-20 / BEP-20 stables: tag must be empty (Bybit rejects with field validation error if present).
- Network code in the QTG template matches the Bybit chain code (e.g. QTG
ethereum→ BybitETH, QTGtron→ BybitTRX). Mapping table:src/qtg/infrastructure/executors/cex/adapters/bybit/bybit_transfer_constants.py:NETWORK_TO_CHAIN.
2. UI registration steps
- Sign in to Bybit web UI (mainnet or testnet — drill differs from live, don’t cross them).
- Navigate: Assets → Withdraw → Address Book → Add Address.
- Fill:
- Coin: the asset symbol (
USDT,XRP, etc.). Bybit forces case-uppercase. - Network: the chain code matching
NETWORK_TO_CHAIN[<qtg_network>]. Do not select “internal transfer” / “UID” — QTG observe path requires on-chain txID. - Address: the destination wallet/exchange deposit address. Paste, do not retype.
- Tag/Memo: per the asset rule above.
- Address Type (if asked): always pick On-chain (not Universal, not Internal). QTG filter (
ADDRESS_TYPE_ON_CHAIN = 1) drops the other two. - Label: a short operator-readable name, format
qtg-<env>-<dest_venue>-<asset>-<chain>(e.g.qtg-prod-upbit-usdt-trx). Bybit truncates to ~32 chars.
- Coin: the asset symbol (
- Complete Bybit’s 2FA + email confirmation (typically email link + Google Authenticator code).
- Record the registration timestamp (UTC) in the drill log.
3. 24-hour cooldown window
- After successful UI registration, Bybit marks the entry as
pendingfor 24h. GET /v5/asset/withdraw/query-addresswill return the entry but aPOST /v5/asset/withdraw/createto that address will fail with retCode131098(new-address 24h cooldown).- QTG mapping (
bybit_transfer_constants.py:ERROR_CODE_MAP):131098→TRANSFER_ERROR;131083/131093→ADDRESS_NOT_WHITELISTED, meaning the address is absent from the address book. The node terminatesFAILEDin both cases — the dispatcher does not retry. 131086is a risk-limit rejection. It is neither a whitelist nor a cooldown signal, and waiting does not clear it. Do not diagnose it with this page.- During the window, run
bybit_readonly_smoke --include-whitelist --asset <coin>to verify the entry is visible. The entry being visible ≠ entry being usable; only the 24h timer makes it usable.
4. Post-cooldown verification
After 24h has elapsed:-
bybit_readonly_smoke --include-whitelist --asset <coin>returns the entry inget_whitelisted_addressessummary. - Optional sanity: a tiny test movement (
bybit_tiny_withdrawal_drillplan) submits without131098.
5. Common failure modes
6. Hard rules
- Never edit a whitelist entry to “fix” an address. Editing restarts the 24h cooldown and during that window the entry is unusable — this leaves any in-flight movement template referencing the entry stuck in
FAILED. Delete and re-register instead, knowing the new entry also has 24h cooldown. - Never use Bybit’s “Internal Transfer” address type for QTG movements. Internal transfers produce no on-chain txID, and QTG’s
deposit_observematches by txID — the deposit-side node would hang indefinitely. - Whitelist scope is per-API-key-pair if 2FA is bound. A whitelist entry registered under one Bybit account is not visible to another account, even within the same legal entity.