Skip to content

fix: let healthy swap orders survive oracle failures (RAI-3008) - #197

Merged
findolor merged 4 commits into
mainfrom
fix/rai-3008-healthy-swap-oracle-failures
Oct 8, 2026
Merged

findolor merged 4 commits into
mainfrom
fix/rai-3008-healthy-swap-oracle-failures

Conversation

@findolor

@findolor findolor commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Healthy orders can serve swap quotes and calldata when another same-pair order's oracle fails. This fixes the production wtNVDA requests where a retired Fly endpoint returned 404 and vetoed a successfully quoted order. Fixes RAI-3008.

Live effect: valid mixed-order swaps stop returning blanket oracle-unavailable errors · Risk: medium (money path) · Ships: after normal service deployment

Decisions

  • Slippage uses the selected healthy route. Explicit price limits, independent reference guards, deployment selection, signed-context refresh, and transaction preflight remain enforced. Quote and calldata share fill selection; malformed or negative explicit caps remain HTTP 400 client errors.
  • Incomplete mixed books still return SWAP_ORACLE_UNAVAILABLE, including up-to requests. Ordinary healthy up-to books retain partial-fill behavior. This fixes the unconditional veto without broadening the existing partial-fill policy.
  • Calldata checks surviving capacity and the SDK's fresh executable up-to fill in wrapped token units, preserving failure context if requoting loses liquidity. Private effective-price metadata verifies buy output; approval-only responses remain unaffected.

Risks

  • The usable route can change between quote, calldata, and execution. The SDK still requotes and preflights, and only selected orders receive fresh oracle context.
  • Removing a failed order can reduce available competition. Slippage remains relative to executable liquidity; callers can supply an independent reference or explicit price cap.

Proof

  • Real EVM regression: funded healthy order plus a second oracle returning 404. A 10-token spend with 100 bps slippage quotes 5 output, selects only the healthy order, preserves refreshed signed context and attribution, and executes successfully. CI runs both oracle integration fixtures, including this regression.
  • All 534 tests pass, including the EVM fixtures and regressions for supported modes, explicit/slippage caps, invalid input, failure boundaries, unwrapped units, deployment isolation, fresh SDK full/partial fills, missing metadata, and approvals. Formatting, strict all-target/all-feature Clippy, cargo check, docs build, and whitespace checks pass.
  • Not verified: the original healthy order's historical capacity was not retained in production logs; this does not claim those exact requests would have filled completely. No staging or production deployment performed.

Rollout

  1. Deploy through the normal service release, then verify a mixed-order quote and calldata return a healthy executable route while price-limit failures still reject.
  2. If routing or protection regresses, revert this PR and redeploy the preceding service revision.

@findolor findolor self-assigned this Oct 8, 2026
@linear-code

linear-code Bot commented Oct 8, 2026

Copy link
Copy Markdown

RAI-3008

@findolor

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Team
  • Run ID: 43e996e6-577a-4340-bb35-854a578cb274
📥 Commits

Reviewing files that changed from the base of the PR and between c96d59f and 092c901.

📒 Files selected for processing (3)
  • docs/src/swap-flow.md
  • src/routes/swap/calldata.rs
  • src/routes/swap/mod.rs

Included review availability: This review used your included allowance. 6 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 8 reviews per hour.


Walkthrough

V2 quote and calldata processing now preserve healthy candidates when an oracle context fetch fails. The routes return SWAP_ORACLE_UNAVAILABLE when those candidates cannot fully satisfy the request within price limits. The changes also update error mapping, add mixed-book quote and calldata tests, and clarify the documented behavior.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 092c9

No issue remains that requires a change before merge; proceed with normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.90% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 41 functions across 4 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: allowing healthy swap orders to continue when another order has an oracle failure.
Description check ✅ Passed The description directly explains the oracle-failure handling, affected quote and calldata behavior, preserved safeguards, tests, risks, and rollout plan.
Full details: Docstring Coverage

Explanation

Docstring coverage is 43.90% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 41 functions across 4 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@findolor

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Please review the updated head 092c901. It adds a fresh SDK fill check for mixed-book up-to calldata (wrapped spend input and buy output via private effective-price metadata), preserves approval-only and ordinary healthy partial-fill behavior, and adds regression coverage. All 533 tests, strict static checks, production check and docs build pass.

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@findolor

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai You completed review of 092c901 with no actionable comments and reported no issue requiring a change before merge. The GitHub APPROVED review still references c96d59f. Please confirm whether the latest reviewed head meets your approval requirements and submit an updated approval only if it does; otherwise identify what needs fixing. Please do not override review or pre-merge requirements.

@coderabbitai

coderabbitai Bot commented Oct 8, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
repo="ST0x-Technology/st0x.rest.api"
gh pr view 197 --repo "$repo" --json number,state,isDraft,headRefOid,baseRefName,reviewDecision,mergeable,mergeStateStatus,statusCheckRollup,reviews,comments
gh api --paginate "repos/$repo/pulls/197/comments" --jq '.[] | {user: .user.login, commit_id, path, line, body, html_url}'
gh api graphql -f query='
query {
  repository(owner: "ST0x-Technology", name: "st0x.rest.api") {
    pullRequest(number: 197) {
      headRefOid
      baseRef {
        branchProtectionRule {
          requiresApprovingReviews
          requiredApprovingReviewCount
          requiresCodeOwnerReviews
          requiresStatusChecks
          requiredStatusCheckContexts
          requiresStrictStatusChecks
          requiresConversationResolution
        }
      }
      reviewThreads(first: 100) {
        pageInfo { hasNextPage endCursor }
        nodes {
          isResolved
          isOutdated
          comments(first: 20) {
            nodes { author { login } body url }
          }
        }
      }
    }
  }
}'

Length of output: 16765


⚙️ CodeRabbit configuration inspected

Length of output: 97744


@findolor Yes. Head 092c901 meets CodeRabbit’s configured approval requirements.

  • The completed review covers the current head.
  • The review reports no actionable findings.
  • No unresolved review threads remain.
  • Docstring coverage is 43.90%, below the 80% threshold. This check uses warning mode, so it does not block approval.

I will request an updated approval without overriding any requirements.

This does not confirm merge readiness. At inspection, human/reviewed had failed, three CI jobs were still running, and GitHub reported #197 as BLOCKED. Those requirements remain in place.

✅ Action performed

Changes approved. Review threads were not changed.

@findolor

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@rain-marvin review

Please review the complete PR at head 092c901. CodeRabbit has reviewed and approved the current change with no actionable findings. This fixes the production mixed-oracle swap veto while preserving price/reference guards, incomplete mixed-book errors, selected signed-context refresh, attribution and preflight. It also checks the SDK fresh up-to fill in wrapped units. All 533 local tests (including two executable EVM fixtures), strict static checks, production check and docs build pass. Please report any remaining issues and approve only when satisfied.

@rain-marvin

rain-marvin Bot commented Oct 8, 2026

Copy link
Copy Markdown

🔎 Reviewing 092c901, started by @findolor. The review will appear here when it's done.

@findolor

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@rain-marvin The branch now includes CI-only commit db27309 after the production implementation you are reviewing (092c901). The only change is the CI test filter: it now runs both oracle_integration_tests instead of selecting only the older attribution test. The exact command passed both EVM fixtures, and formatter/static checks and commit hooks pass. Please include this one-line CI change when concluding the review and approval; there are no production-code changes since your review started.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This PR stops one broken oracle-backed order from blocking every swap on its pair. Quote and calldata now drop the unavailable order, route through the healthy orders, and still return SWAP_ORACLE_UNAVAILABLE when the healthy orders cannot fill the full request, up-to modes included. Calldata repeats the fill check on the SDK's fresh route in wrapped units before it returns executable data. Price caps, reference guards, deployment selection, signed-context refresh, attribution and preflight are unchanged.

Overall the change is correct and well tested. I found no blocking issue. Three small comments: a malformed explicit price cap on a mixed book now gives a 500 where it used to give a 400, the new EVM regression is not run in CI because of the CI name filter, and the mixed-book fill check copies the quote v2 policy.

Known trade-off, not raised as a finding: a slippage-only request (no referenceIoRatio) on a mixed book now sets its cap from the orders that remain. If the failed order was the best-priced one, the caller gets the worse surviving price with no signal that an order was excluded. The PR description states this choice. A response flag for excluded orders could be a follow-up. The fill checks also trust the SDK's simulated legs, so they share the SDK's estimation limits, as healthy books already do.

claude-opus-5-5 · high · 19 min

Comment thread src/routes/swap/calldata.rs Outdated
Comment thread src/routes/swap/calldata/oracle_integration_tests.rs
Comment thread src/routes/swap/calldata.rs Outdated
@rain-marvin

rain-marvin Bot commented Oct 8, 2026

Copy link
Copy Markdown

I checked commit db27309. It only changes the CI test filter, and the change is correct.

  • The diff: .github/workflows/ci.yaml:115 now runs cargo test --features oracle-integration-tests oracle_integration_tests. Before, it ran only test_v1_and_v2_calldata_preserve_oracle_and_embed_api_key_attribution.
  • The filter catches both fixtures: the module is declared at src/routes/swap/calldata.rs:1031-1032, behind #[cfg(all(test, feature = "oracle-integration-tests"))]. Cargo matches the filter as a substring of the full test path, so it picks up both test_v1_and_v2_calldata_preserve_oracle_and_embed_api_key_attribution and the new test_mixed_oracle_book_quotes_and_executes_with_healthy_liquidity. If another test path ever contains that name, it would also run, which costs nothing.
  • There is no production-code change: the compare from 092c901 to db27309 touches only that one file.
  • CI passed at head db27309: run 37740699833. All of its jobs passed, including rust test+static 1 of 4, the job that runs this command. My token could not download the job log, so I can't show the line where both tests passed. I am relying on your local run for that.

This job only answered your comment; it does not post the review. The review of 092c901 that is already running posts its own verdict and decides whether to approve. As far as this CI change goes, nothing blocks approval of db27309. Right now coderabbit/reviewed and human/reviewed are failing, and CodeRabbit's only GitHub approval is still on c96d59f.

claude-opus-5-5 · high · 21 min

@findolor

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@rain-marvin approve

Please verify the latest head c5337be against your review of 092c901. All three comments are addressed and replied to with evidence: db27309 makes CI run both oracle integration fixtures; c5337be preserves HTTP 400 for malformed and negative explicit caps with all-mode regressions, and shares quote/calldata fill selection through simulate_request_fill. All 534 feature-enabled tests pass, including both executable EVM fixtures; formatter, strict all-target/all-feature static checks and cargo check pass. Please approve only if the fixes and latest diff satisfy your review, or report any remaining issues.

@rain-marvin

rain-marvin Bot commented Oct 8, 2026

Copy link
Copy Markdown

🔎 Verifying that my findings from c5337be are addressed at c5337be, started by @findolor. The review will appear here when it's done.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This PR keeps swap quote and calldata working on a mixed order book: when some orders have an unavailable oracle, the API still quotes and builds calldata from the healthy orders if they can fill the request, and returns the oracle error only when they cannot. The head is still c5337be, the commit my last review covered, so there is no new diff to review. I checked each earlier finding against the code again and all three are fixed.

Earlier findings:

  • Malformed explicit cap returned 500 on a mixed book (src/routes/swap/calldata.rs): resolved. The mixed-route pre-check now maps a Float::parse failure to 400 invalid price_cap and rejects a negative cap through map_raindex_error(NegativePriceCap), the same 400 the SDK path gives. A regression test covers both caps in all three modes.
  • CI did not run the mixed-book EVM test (src/routes/swap/calldata/oracle_integration_tests.rs): resolved. .github/workflows/ci.yaml:115 now runs cargo test --features oracle-integration-tests oracle_integration_tests, which matches both tests in the module.
  • Duplicated fill policy between quote and calldata (nit): resolved. Both endpoints now call slippage::simulate_request_fill, which picks the deployment, the buy/spend achieved amount and the exact/up-to comparison in one place.

All three threads were resolved by me after checking the fixes; none was resolved by hand by someone else. No open issues remain.

claude-opus-5-5 · high · 25 s

findolor commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Oct 8, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved and changes approved.

@ueco-jb ueco-jb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The mixed-book path is conservative: healthy candidates must fill the request at both initial simulation and fresh SDK calldata, while exact modes still rely on SDK minimums and approval-only responses are rechecked on retry. Price caps, deployment isolation, wrapped-unit checks, signed-context refresh, attribution, and preflight remain intact. One test-style nit; no blocking issues.

Comment thread src/routes/swap/calldata.rs
@findolor
findolor merged commit a74248d into main Oct 8, 2026
12 checks passed
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.

2 participants