Skip to Content

Traps

Places where the obvious search gives the wrong answer. This page exists because it was measured: an agent reading the codebase without it answers most questions correctly and stumbles on these predictably.

In the code

The trapWhat is actually true
“Debt appears on ITM” — grepping for долг/debt lands in the call branchDebt is call-only. A put’s collateral is K·q USDC, the (K−S)·q debit comes out of that same collateral and cannot exceed it. conversion-how-it-works.md:51
Looking for the sixth lock by the word schedulerBASE_SEND_LOCK_KEY lives in treasury/bridge-in.sender.ts:28, not in any *.scheduler.ts
“Deposit: the user sends to an HD address, we sweep it and bridge it”Backwards. The user themselves calls depositToAppChain on the source-chain vault; the bridge mints the wrapper already on Derive Chain; the sweep happens inside Derive Chain. There is no EIP-3009 in this project at all
getCollaterals and getMargin are different calls”The same private/get_subaccount, two projections of one response
Reading maintenanceMargin as a requirementIt is a buffer in USD. Liquidation happens when it goes negative. Live measurement: initial $14.81 below maintenance $15.80 — read as a “requirement” that is inverted
“The fee can be computed with a formula”Forbidden (P6). The fee and the settlement debit are taken from the exchange response. Your own arithmetic will disagree on rounding and alert on every ITM position
Money.gtThere is no such method. “a > b” is written b.lt(a)
dataSource.query() over a bare UPDATE returns rowsIt returns the tuple [rows, affectedCount]. See Architecture
A posting’s currency is the token tickerThe journal’s vocabulary is asset-level: ETH, not WETH. 'WETH' does not net against a recorded +ETH, and it zeroes a user’s entire totalUsd through UnsupportedAssetError
Looking for /subaccounts/:asset/release under SubaccountsModuleSubaccountsController and ReleaseService sit in the subaccounts/ folder but are registered by PositionsModule (positions/positions.module.ts:59) — releasing funds asks both subaccounts and position cycles, and leaving them in SubaccountsModule would have created a module cycle
Looking for usdRateFor in the prices moduleIt is in strategies/index-price.source.ts. The prices module is a separate, unrelated spot-price WebSocket relay
“There is a WebSocket client to Derive, so the trading path must use it”Two different things share the name. The gateway has none — orders and fills are polled (P3: the maker window is 20 minutes, a minute of lag costs nothing). But prices/derive-spot-stream.ts is a raw ws client to wss://api.lyra.finance/ws, subscribed to spot_feed. It feeds the browser’s price ticker and no money path reads it
import type for anything injectedErased at runtime, so design:paramtypes loses it and Nest DI fails. Bitten in auth/auth.guard.ts and again in the reconciliation module

Declared but not wired

Check before citing any of these as working.

WhatState
Platform feePlatformFee is provided and exported but injected by nobody; applyTo() is never called outside its own spec. platform:fee_revenue takes part in no posting rule. The rate is 0. Its only real use is display: GET /trading-config returns platformFeeRate for the frontend
ReconciliationWired, but defaults to observe: it compares and logs divergences, writing nothing to the journal and stopping nobody. RECONCILE_MODE=enforce turns on adjustments and stops. See Reconciliation
funding_paid, bridged, signal_received, stop_clearedEvent types declared, nobody writes them, no posting rules
Clearing a stopImplemented nowhere. Not one line clears cycles.stop_reason, and no code path returns subaccounts.status to 'active'. By design it is a manual admin action, and the admin panel does not exist
cycles.pending_withdrawalColumn created by a migration, read nowhere
AlertsThe Telegram channel exists but only activates when both TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID are set; without them it falls back to logger.warn
QuoteSource.estimateDead in production — its only caller is an integration test
Nonce cleanupauth_nonces_expires_idx was created for a sweeper that does not exist. The table grows without bound
Refresh tokensNot present in any form — no endpoint, no field in the JWT payload. A 7-day expiry means signing in through SIWE again
getBestRfqQuote drops invalid_reasonAcknowledged debt: the contract was not widened because the consumer (the wheel engine) did not exist when the comment was written

Stale specifications

The specs under docs/superpowers/specs/ are dated and were accurate when written. These had since drifted, and the drift is the kind that reads as current fact.

Each affected spec now carries a dated «⚠️ Что изменилось» block at the top listing exactly these rows, so the correction is visible at the source rather than only here. The dated measurements inside those specs were kept — they are evidence about Derive’s calendar and remain true for their date.

SpecWhat it saysWhat the code does
strategies-showcase-how-it-works.md §7, showcase-streaming-how-it-works.md §7The APR threshold only annotates — rejected candidates are returned with passesThreshold/rejectionReasonThe threshold filters. RejectionReason is a local type that never leaves buildCandidates, and the contract has no such fields
Both showcase specs §8hasSignal is always falseIt is really computed, through signals/signal-matcher.ts:28
Both showcase specsFive assets on the showcaseTwo: ETH and BTC. XAUT, HYPE and XRP were removed — no ERC20 collateral on the Derive bridge means no covered call, and “half a circle is not a product”
openapi-how-it-works.md:118“The client is not generated from the schema; there is no generation step in the frontend build”It is generated, via swagger-typescript-apipnpm --filter=@arkada/web build-api

A contradiction inside the code itself

derive/gateway/derive-gateway.interface.ts marks createSubaccount as never having been executed live (M4a), while the header comment of live-derive.gateway.ts states that subaccount 70021 was created live on 2026-08-21. Both cannot be true. Nothing depends on the answer today, but do not quote either one as settled.