# Audit note: v18 smart trades bypass wallet controls ## Finding 1 — Smart trades ignore the emergency token lock **Severity:** Medium; higher if a registered passkey is compromised. **Affected contract:** `SPV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RCJDC22.fakfun-wallet-v18`. The v18 smart-trade authorization path does not check `token-lock-enabled`. `authorize-smart` checks that the router is approved, then accepts either a WebAuthn signature or an admin caller (`fakfun-wallet-v18.clar`, lines 1220–1277). All four new public smart-trade entries call it and proceed to a router call. For example, `smart-buy-stx` at lines 1306–1330 transfers `amount` STX under `with-stx`; `smart-buy-sbtc` at lines 1279–1303 does the same for sBTC. Neither path checks the lock. The sell entries at lines 1333–1390 also call the router without a lock check. This differs from existing signed asset movement: `stx-transfer` checks `token-lock-enabled` in its signature arm at lines 757–760, and `extension-call` does likewise at lines 847–849. `toggle-token-lock(true, none, none)` can enable the lock from an admin call (lines 350–398). With the lock enabled, a still-valid authorized passkey signature can therefore execute a smart trade through an approved router, despite the wallet's emergency lock. **Reproduction sequence:** 1. Use a funded v18 wallet with a registered passkey and an approved smart router such as the seeded `b-smart-faktory`. 2. Have an admin enable the lock with `toggle-token-lock(true, none, none)` and verify `get-token-lock-enabled` returns `true`. 3. Produce a valid, unused smart-trade signature for that wallet and router using `build-smart-execute-hash` with `op = 0x01` and the desired STX amount, minimum output, ratio, and flag. 4. Call `smart-buy-stx` with that signature. The seeded approved `b-smart-faktory.buy-with-stx` calls `stx-transfer?` from the wallet to the router (deployed router source, line 90); no v18 code reads the lock before this transfer. The analogous `smart-buy-sbtc` and both sell entries also lack the lock guard. The authorization signature is still required; this is a bypass of the wallet's post-compromise emergency control, not an unauthenticated call. No live transaction was sent. ## Finding 2 — Smart buys bypass and do not account for spending thresholds The wallet has rolling `stx-threshold` and `sbtc-threshold` settings in `wallet-config` (lines 111–120) and tracks period spending in `spent-this-period` (lines 128–174). `stx-transfer` queues an over-limit transfer instead of executing it and calls `add-spent-stx` on immediate transfers (lines 783–804). `sip010-transfer` performs the corresponding check and accounting for sBTC (lines 927–944). The new `smart-buy-stx` and `smart-buy-sbtc` entries call neither `would-exceed-stx-threshold` / `would-exceed-sbtc-threshold` nor `add-spent-stx` / `add-spent-sbtc`. They pass the full requested amount directly to the approved router under `with-stx` or `with-ft`. A valid signature can thus trade above the configured cap; repeated trades also leave `spent-this-period` unchanged, so the cumulative cap never catches them. Selling tokens is not covered by these spend counters, but the buy paths spend the capped assets directly. **Reproduction sequence:** 1. Use a funded v18 wallet with `spent-this-period.stx = 0` and an approved smart router. The default `stx-threshold` is `u100000000`; the default `sbtc-threshold` is `u100000` (lines 111–120). 2. With the lock disabled, call `stx-transfer` for `u100000001` (100.000001 STX); it creates a pending transfer rather than moving the STX immediately. The analogous SBTC case is `u100001`. 3. Sign a valid `smart-buy-stx` request for the same amount and call it through the approved router. It reaches the router immediately, with no threshold check and no update to `spent-this-period.stx`. 4. Repeat with `smart-buy-sbtc` and the corresponding sBTC cap. **Suggested fix:** apply the token-lock guard to the signed smart authorization branch, preserving the existing admin behavior. Route smart buys through the same threshold accounting as direct transfers. If an over-limit smart trade must be delayed, store its router and all signed trade parameters in an immutable pending operation and execute it only after the normal cooldown; otherwise the cap must at least count the amount spent so later calls cannot evade the cumulative limit. ## Validation and scope - The source fetched from the public mainnet Hiro API exactly matches the repository's cleaned v18 source at commit `ba432a89f2be97c96e623333e727be369b90112b` (SHA-256 `051dc7e2160148fc4d54ef62fa2476b9b8cd76fe192360cf0621e325cee50e16`). - The seeded router `b-smart-faktory` is approved by the registry and its deployed source exposes `buy-with-stx` and `buy-with-sbtc`. - This is source-only validation. I did not compile or run a Clarinet/Stxer simulation, and did not interact with live contracts.