Skip to content

fix: address audit findings#50

Open
bangyro wants to merge 2 commits intorelease_0.2.2from
fix/audit-offside
Open

fix: address audit findings#50
bangyro wants to merge 2 commits intorelease_0.2.2from
fix/audit-offside

Conversation

@bangyro
Copy link
Collaborator

@bangyro bangyro commented Mar 18, 2026

Incomplete Verification of JUP_V6 Payload

Add these validations

  • root input (index 0) must be consumed (Enforce that the cumulative consumption percentage of input_index = 0 must be exactly 100)
  • prevent phantom input, a non-root input must have been produced by a prior step
  • cannot output to an index already used as input

@bangyro
Copy link
Collaborator Author

bangyro commented Mar 18, 2026

/bot review

@metoeraag-bot
Copy link

metoeraag-bot bot commented Mar 18, 2026

Bot Agent progress: /bot review

Progress:

  • Repo checks (4 ok, 1 failed)
  • Context build
  • [!] Codex review (OpenAI error: failed to parse SSE response)
  • [-] Buddy review (blocked by failure)
  • [-] Post review (blocked by failure)

@metoeraag-bot
Copy link

metoeraag-bot bot commented Mar 18, 2026

Bot Agent progress: /bot review

Progress:

  • Repo checks (5 ok, 0 failed)
  • Context build
  • Codex review (1 pass + first look)
  • Buddy review (agreed after 2/10)
  • Post review

Copy link

@metoeraag-bot metoeraag-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Kept both comments. They are distinct, well-supported by the described validation flow, and align with the current summary: one flags that the output_index check may reject valid split-route topologies, and the other notes that phantom-input validation depends on route steps being topologically ordered and should document that requirement.

Inline comments

See inline comments on the diff.

Claude (API) review

Rounds: 2 (min=1, max=10).
First look: Codex + Claude (API).
Agreement: yes (no new findings/questions).

Debate transcript

First look comparison

Codex (first look):

Summary:
No actionable issues found. The route-plan validation changes appear to match the stated audit fixes, and the added tests cover the new failure modes.

Inline comment highlights: (none)

Claude (API) (first look):

Summary:
The PR adds four new validations to validate_route_plan for JUP V6 payloads: root input (index 0) must be consumed, phantom inputs are rejected, outputs cannot target already-consumed input indices, and all paths must converge. The logic is mostly correct but has one notable issue with the output-to-input-index check, and test coverage for some edge cases could be improved.

Inline comment highlights:

  • protocol-zap/src/processors/jup_v6_zap.rs:68: Bug: The check input_indices_seen.contains(&step.output_index) fires even when output_index == input_index in the same step (self-loop), but more importantly it is order-dependent and overly strict in split scenarios. Consider the v
  • protocol-zap/src/processors/jup_v6_zap.rs:62: The phantom-input check uses output_indices which is populated after this check (line 77). This means the check validates that a non-root input was produced by a strictly prior step, which is the correct ordering semantics. However,
  • protocol-zap/src/tests/jup_v6_tests.rs:397: This test (test_validate_route_plan_failure_output_to_consumed_input) only tests the case where a later step outputs to an index already consumed as input. Consider also adding a test where output_index == 0 (outputting back to the root

Comparison notes:

Review synthesis

Top differences in emphasis

  1. Overall verdict: Review A found no actionable issues; Review B identified a likely bug in the output_index → consumed-input validation.
  2. Test coverage: Review A says the new tests sufficiently cover failure modes; Review B says coverage is incomplete, especially for split/self-loop behavior and output_index == 0.
  3. Depth/focus: Review A gives a high-level approval tied to the audit fixes; Review B focuses on specific graph/ordering semantics in validate_route_plan and how the current check may be order-dependent or overly strict.

Most important follow-up action

  • Revisit and correct the output_to_consumed_input validation logic in validate_route_plan, then add targeted regression tests (especially split routes, self-loop cases, and output back to root index 0) to confirm the intended semantics.

Round 1

Codex (primary):

Summary:
No actionable issues found. The route-plan validation changes appear to match the stated audit fixes, and the added tests cover the new failure modes.

Inline comment highlights: (none)

Claude (API):

Critique of the Primary Review

The primary review found no actionable issues and approved the PR. This is a false negative — there are at least two concerns worth raising:

1. output_index → consumed-input check is overly strict in edge cases

The check on line 68 (input_indices_seen.contains(&step.output_index)) rejects any step whose output_index matches any previously-seen input_index, including the current step's own input_index. This means:

  • A step with input_index == output_index is always rejected (which blocks cycles — good)
  • But a split like [{in:0, out:1}, {in:0, out:0}] is also rejected, because 0 was inserted into input_indices_seen by the first step

Whether this is a bug or intended behavior depends on the protocol's semantics, but either way it's worth flagging and testing explicitly.

2. Implicit topological ordering requirement

The phantom-input check on line 62 only works correctly if steps are provided in topological order. This is an implicit contract that should be documented.

3. Missing test coverage

The primary reviewer stated tests "cover the new failure modes" but there are no tests for:

  • Split routes where output_index collides with a prior input_index from a different step
  • output_index == 0 scenarios
  • Reordered (non-topological) step arrays

The primary review should have flagged at least the ambiguity in the output_index check and the missing edge-case tests.

Codex (response):

  • New findings applied: 2/2
  • Open questions kept for author: 2/2

Round 2

Codex (primary):

Summary:
Identified two actionable follow-ups in the route-plan validation changes: the output_index vs. previously seen input_index check may be stricter than intended for some split-route topologies, and the phantom-input validation implicitly requires topologically ordered steps and should document that contract.

Inline comment highlights:

  • protocol-zap/src/processors/jup_v6_zap.rs:68: input_indices_seen.insert(step.input_index) happens before this contains(&step.output_index) check, so any step that outputs to an index already used as input by an earlier step (or by itself) is rejected. That blocks cycles, but it als
  • protocol-zap/src/processors/jup_v6_zap.rs:62: Nit/doc: this phantom-input check only works if the route steps are already topologically ordered, because output_indices is populated later in the loop. If that ordering is guaranteed by Jupiter, please document it in the function commen

Claude (API):

Assessment

The primary reviewer's two findings from the prior critique round have been applied (2/2), and the two open questions have been kept for the author (2/2). The independent first-look review confirms the same issues at the same locations (lines 62 and 68 of jup_v6_zap.rs, plus the test coverage gap at line 397 of jup_v6_tests.rs).

All three reviews (primary after revision, prior critique, independent first-look) are now converged on the same set of concerns:

  1. The output_index → consumed-input check at line 68 is overly strict for certain split topologies.
  2. The phantom-input check at line 62 implicitly requires topological ordering and should document this.
  3. Test coverage for edge cases (output_index == 0, split routes with index collisions, non-topological ordering) is incomplete.

Since these are all already captured in the primary review's inline comments and the author's open questions, there are no new high-signal deltas to add, no false positives to retract, and no additional questions to raise.

Codex (response):

Agreement reached. No further changes.

Synthesis

Review synthesis

Top differences in emphasis

  1. Overall verdict: Review A found no actionable issues; Review B identified a likely bug in the output_index → consumed-input validation.
  2. Test coverage: Review A says the new tests sufficiently cover failure modes; Review B says coverage is incomplete, especially for split/self-loop behavior and output_index == 0.
  3. Depth/focus: Review A gives a high-level approval tied to the audit fixes; Review B focuses on specific graph/ordering semantics in validate_route_plan and how the current check may be order-dependent or overly strict.

Most important follow-up action

  • Revisit and correct the output_to_consumed_input validation logic in validate_route_plan, then add targeted regression tests (especially split routes, self-loop cases, and output back to root index 0) to confirm the intended semantics.
Repo checks

Repo Checks

  • LLM checks planner: added package install step before running JS commands.

  • rustup component add --toolchain 1.85.0-x86_64-unknown-linux-gnu rustfmt: ok

info: downloading component 'rustfmt'
info: installing component 'rustfmt'
  • cargo fetch --locked: ok
Updating git repository `https://github.com/MeteoraAg/damm-v2`
From https://github.com/MeteoraAg/damm-v2
 * [new ref]         58a13fcf45516a9f27f2bd2a2056fb66673454e0 -> refs/commit/58a13fcf45516a9f27f2bd2a2056fb66673454e0
  • pnpm install --frozen-lockfile: ok
Lockfile is up to date, resolution step is skipped
Progress: resolved 1, reused 0, downloaded 0, added 0
Packages: +1 -1
+-
Progress: resolved 1, reused 1, downloaded 0, added 1, done

devDependencies:
- @meteora-ag/cp-amm-sdk 1.2.3
+ @meteora-ag/cp-amm-sdk 1.3.7

╭ Warning ─────────────────────────────────────────────────────────────────────╮
│                                                                              │
│   Ignored build scripts: bigint-buffer@1.1.5, bufferutil@4.0.9,              │
│   utf-8-validate@5.0.10.                                                     │
│   Run "pnpm approve-builds" to pick which dependencies should be allowed     │
│   to run scripts.                                                            │
│                                                                              │
╰──────────────────────────────────────────────────────────────────────────────╯
Done in 651ms using pnpm v10.28.2

! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-10.28.2.tgz
  • cargo check --workspace: ok
Checking protocol-zap v0.1.0 (/data/workdir/MeteoraAg/zap-program/protocol-zap)
    Checking cp-amm v0.2.0 (https://github.com/MeteoraAg/damm-v2?rev=58a13fcf45516a9f27f2bd2a2056fb66673454e0#58a13fcf)
    Checking zap v0.2.2 (/data/workdir/MeteoraAg/zap-program/programs/zap)
warning: use of deprecated method `anchor_lang::prelude::AccountInfo::<'a>::realloc`: Use AccountInfo::resize() instead
  --> programs/zap/src/lib.rs:21:1
   |
21 | #[program]
   | ^^^^^^^^^^
   |
   = note: `#[warn(deprecated)]` on by default
   = note: this warning originates in the attribute macro `program` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused import: `liquidity_handler::LiquidityHandler`
 --> programs/zap/src/state/user_ledger.rs:2:45
  |
2 |     error::ZapError, get_liquidity_handler, liquidity_handler::LiquidityHandler,
  |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: `zap` (lib) generated 2 warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.54s
  • cargo fmt --check: ok

@bangyro bangyro marked this pull request as ready for review March 19, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant