oracle support#438
Conversation
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
|
Warning Review limit reached
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 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (22)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
hardyjosh
left a comment
There was a problem hiding this comment.
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
OracleErrorwith categorization is clean - Health/cooloff tracking is well-implemented
- Test coverage is thorough (~1,290 lines covering edge cases, timeouts, cooloff, validation)
fetchOracleContextbound toSharedStatevia.call()is a clean pattern- Oracle URL extraction from CBOR meta with magic number search works correctly
|
@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:
Review Effort: Would have taken 5-10 minutes Examples:
Medium (M)Characteristics:
Review Effort: Would have taken 15-30 minutes Examples:
Large (L)Characteristics:
Review Effort: Would have taken 45+ minutes Examples:
Additional Factors to ConsiderWhen deciding between sizes, also consider:
Notes:
|
Motivation
Solution
Checks
By submitting this for review, I'm confirming I've done the following: