Skip to content

oracle support#438

Merged
rouzwelt merged 20 commits into
masterfrom
2026-04-03-oracle-support
Jun 15, 2026
Merged

oracle support#438
rouzwelt merged 20 commits into
masterfrom
2026-04-03-oracle-support

Conversation

@rouzwelt

@rouzwelt rouzwelt commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Solution

Checks

By submitting this for review, I'm confirming I've done the following:

  • made this PR as small as possible
  • unit-tested any new functionality
  • linked any relevant issues or PRs
  • included screenshots (if this involves a front-end change)

Josh Hardy and others added 13 commits February 23, 2026 20:21
1. Add meta field to subgraph queries for order discovery
2. Create oracle module with:
   - extractOracleUrl() placeholder for meta parsing
   - fetchSignedContext() for batch oracle requests
   - Support for batch format (array of contexts)
3. Wire oracle into quoting logic:
   - Extract oracle URL from order meta before quote2
   - Fetch signed context and inject into takeOrder struct
   - Graceful fallback on oracle failures
4. Ensure signed context flows through to takeOrdersConfig

The solver now automatically fetches oracle data for orders that
specify an oracle-url, enabling external data integration.
- Fix ethers v6 → v5 APIs (defaultAbiCoder, arrayify)
- Use ABI.Orderbook.V5.OrderV4 constant instead of hardcoded tuple string
- Add 5s timeout on oracle fetch via AbortController
- Validate SignedContextV1 shape on each response entry
- Extract fetchOracleContext helper to deduplicate quote logic
- Remove noisy console.warn from stub extractOracleUrl
- Type OracleOrderRequest.order properly instead of any
Replace ethers.utils.defaultAbiCoder/arrayify with viem's
encodeAbiParameters/hexToBytes. Use proper viem ABI parameter
definitions instead of string-based encoding.
- Up to 2 retries with exponential backoff (500ms, 1s)
- After 3 consecutive failures, oracle URL enters 5min cooloff
- During cooloff, requests to that URL are skipped immediately
- Cooloff resets on first successful response
- Invalid responses (bad shape, wrong length) also count as failures
- All configurable via module constants
No retries, no delays in the loop. Single attempt with 5s timeout —
if it fails, record the failure and move on. After 3 consecutive
failures the URL enters a 5min cooloff where it's skipped immediately
(no network call at all). This way one bad oracle can't block the
processing of other orders.
…ager

Extract oracle cooloff tracking from module-level singleton into an
OracleManager class. Instance lives on OrderManager, threaded through
to quote functions. This makes it properly scoped to the solver
instance lifecycle and testable.

- OracleManager class in src/oracle/manager.ts
- fetchSignedContext takes OracleManager as parameter
- OrderManager creates and owns the OracleManager instance
- OracleManager is optional in quote functions for backward compat
Follow codebase conventions:
- Oracle health map lives on SharedState.oracleHealth
- fetchOracleContext is a standalone fn with this: SharedState,
  called via .call(state) like processOrder/findBestTrade
- Health helpers (isInCooloff, recordOracleSuccess/Failure) are
  plain exported functions operating on the health map
- No new classes, no module-level singletons
- quoteSingleOrder receives SharedState to thread through
- fetchSignedContext returns Result<SignedContextV1[], string>
- fetchOracleContext returns Result<void, string>
- Callers check .isErr() instead of try/catch
- Follows codebase convention for error handling
…terface

- OracleOrderRequest.order uses Order.V3 | Order.V4 from order/types
- OracleOrderRequest.counterparty typed as 0x
- Drop custom SignedContextV1 interface — signed context is already
  typed as any[] on TakeOrderV3/V4, and the response validation
  ensures the right shape at runtime
- fetchSignedContext returns Result<any[], string> matching the
  existing signedContext field type
- extractOracleUrl: implement CBOR meta parsing (was a stub returning null)
- Add oracleUrl field to PairBase, thread through V3/V4 fromArgs
- Add meta field to SgOrder type (already in subgraph query)
- fetchOracleContext: use pair.oracleUrl instead of dead (pair as any).meta
- Switch from batch to single request encoding to match oracle server spec
- Restrict oracle requests to V4 orders only
- Strip internal type discriminant before ABI encoding
@coderabbitai

coderabbitai Bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@rouzwelt, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 57 minutes. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: dc0b2db9-ce6e-44f9-bc4f-933277865617

📥 Commits

Reviewing files that changed from the base of the PR and between b586282 and 1b9df75.

📒 Files selected for processing (22)
  • lib/sushiswap
  • src/common/abis/orderbook.ts
  • src/core/process/order.ts
  • src/core/process/round.ts
  • src/oracle/error.ts
  • src/oracle/fetch.test.ts
  • src/oracle/fetch.ts
  • src/oracle/index.test.ts
  • src/oracle/index.ts
  • src/oracle/types.ts
  • src/order/index.test.ts
  • src/order/index.ts
  • src/order/quote.test.ts
  • src/order/quote.ts
  • src/order/types/index.ts
  • src/order/types/v3.ts
  • src/order/types/v4.test.ts
  • src/order/types/v4.ts
  • src/router/router.ts
  • src/state/index.ts
  • src/subgraph/query.ts
  • src/subgraph/types.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2026-04-03-oracle-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@hardyjosh hardyjosh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: Oracle Signed Context Support

Good work overall — well-structured module separation, strong test coverage, and correct error handling patterns. A few things to address before merge:

Bug: Empty array response passes validation

SignedContextV2.isValidList() uses .some() which returns false for empty arrays:

static isValidList(value: unknown): value is SignedContextV2[] {
    if (!Array.isArray(value)) return false;
    return !value.some((v) => !SignedContextV2.isValid(v));  // empty array -> true
}

An empty [] response passes validation, then response.data[0] is undefined, which gets set as the signed context. This will cause downstream failures when the solver tries to submit a tx with signedContext = [undefined].

Fix: add value.length === 0 check, or use .every() with a length guard.

Hardcoded KnownUrls is fragile

export const KnownUrls = ["https://st0x-oracle-server.fly.dev/context"] as const;

Any new oracle deployment (e.g. /context/v1, a different domain, or a third-party oracle) requires a code change and redeployment. Consider making this configurable via the YAML config, or removing the check entirely -- the URL comes from on-chain order meta which the order owner controls. If someone puts a bad URL in their own order's meta, they only hurt their own order.

SignedContextV1 -> SignedContextV2 rename

The ABI rename from SignedContextV1 to SignedContextV2 across orderbook.ts is cosmetic -- the struct shape (address signer, bytes32[] context, bytes signature) is identical. Creates unnecessary diff noise in a PR that's already 1700+ lines. Consider splitting it out or reverting if the on-chain struct name hasn't actually changed.

Order type discriminant passed to ABI encoding

order: request.order,  // includes { type: Order.Type.V4, ...}

The TypeScript discriminant type: Order.Type.V4 is passed through to encodeAbiParameters. Viem silently ignores extra fields not in the ABI spec, so this works, but it's imprecise. Stripping it explicitly would prevent surprises if viem ever becomes strict about extra fields.

Minor: typos

  • "orcale" -> "oracle" in several JSDoc comments (fetch.ts)
  • "sucess" -> "success"

What's good

  • Oracle failure correctly blocks quoting (prevents gas waste on guaranteed-revert txs)
  • Typed OracleError with categorization is clean
  • Health/cooloff tracking is well-implemented
  • Test coverage is thorough (~1,290 lines covering edge cases, timeouts, cooloff, validation)
  • fetchOracleContext bound to SharedState via .call() is a clean pattern
  • Oracle URL extraction from CBOR meta with magic number search works correctly

@rouzwelt rouzwelt changed the base branch from 2026-03-27-v6-calldata-fix to master June 15, 2026 16:22
@rouzwelt rouzwelt merged commit c0d7d49 into master Jun 15, 2026
4 of 13 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment:

S/M/L PR Classification Guidelines:

This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed.

Small (S)

Characteristics:

  • Simple bug fixes, typos, or minor refactoring
  • Single-purpose changes affecting 1-2 files
  • Documentation updates
  • Configuration tweaks
  • Changes that require minimal context to review

Review Effort: Would have taken 5-10 minutes

Examples:

  • Fix typo in variable name
  • Update README with new instructions
  • Adjust configuration values
  • Simple one-line bug fixes
  • Import statement cleanup

Medium (M)

Characteristics:

  • Feature additions or enhancements
  • Refactoring that touches multiple files but maintains existing behavior
  • Breaking changes with backward compatibility
  • Changes requiring some domain knowledge to review

Review Effort: Would have taken 15-30 minutes

Examples:

  • Add new feature or component
  • Refactor common utility functions
  • Update dependencies with minor breaking changes
  • Add new component with tests
  • Performance optimizations
  • More complex bug fixes

Large (L)

Characteristics:

  • Major feature implementations
  • Breaking changes or API redesigns
  • Complex refactoring across multiple modules
  • New architectural patterns or significant design changes
  • Changes requiring deep context and multiple review rounds

Review Effort: Would have taken 45+ minutes

Examples:

  • Complete new feature with frontend/backend changes
  • Protocol upgrades or breaking changes
  • Major architectural refactoring
  • Framework or technology upgrades

Additional Factors to Consider

When deciding between sizes, also consider:

  • Test coverage impact: More comprehensive test changes lean toward larger classification
  • Risk level: Changes to critical systems bump up a size category
  • Team familiarity: Novel patterns or technologies increase complexity

Notes:

  • the assessment must be for the totality of the PR, that means comparing the base branch to the last commit of the PR
  • the assessment output must be exactly one of: S, M or L (single-line comment) in format of: SIZE={S/M/L}
  • do not include any additional text, only the size classification
  • your assessment comment must not include tips or additional sections
  • do NOT tag me or anyone else on your comment

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