Skip to content

[PROPOSAL] RFP-019 - On-Chain TWAP Oracle for LEZ #70

@bristinWild

Description

@bristinWild

RFP ID

RFP-019

Your Project Name

On-Chain TWAP Oracle

Team or Organization Name

Independent

Primary Contact

Email - bristineth@gmail.com
telegram- bristinborah


Team Members

Member 1
Name or pseudonym: Bristin Borah
Social links: GitHub: https://github.com/bristinWild  ·  X/other: https://x.com/borah_bristin
Role: Solo Founder / Full stack web3 engineer
Status: Full-time

Project Summary

LEZ DeFi has a pricing problem that external oracles cannot solve. LEZ-native
assets - LGS and the reflexive stablecoin (RFP-013) - trade only on a LEZ DEX,
so no off-chain publisher has data to sign for them. The single honest price
source is the DEX itself, read through an on-chain time-weighted average. This
proposal delivers that missing tier: an on-chain TWAP oracle program for LEZ
plus the canonical price-account standard that lets multiple price sources
coexist for the same pair, so consuming protocols (RFP-008 lending, RFP-013
stablecoin, RFP-004 DEX) integrate once and stay agnostic to the source.

The build follows the design the RFP lays out: geometric-mean TWAP over
tick-based accumulators (Uniswap v3 model), per-block tick-delta truncation
(Uniswap v4 truncated-oracle-hook, default MAX_TICK_DELTA = 9,116,
governable per pool), a configurable observation ring buffer from cardinality 1
up to 65,535, and a query interface that returns the TWAP and its observation
timestamps with a consumer-supplied maxAge staleness bound. The oracle program
is the writer; cross-source policy stays with consumers. We deliver the standard
as a standalone, importable SPEL IDL artefact so RFP-020 (RedStone) and a future
Pyth adaptor can populate the same struct without depending on the TWAP program.

Two facts about the current LEZ codebase shape our plan and de-risk it. First,
the twap_oracle program already carries a scaffolded OraclePriceAccount
matching hard requirement (base_asset, quote_asset, price: u128,
timestamp: u64, source_id, confidence_interval), annotated #[account_type]
so it already flows into the SPEL IDL - the standard is seeded, the engine behind
it is not. Second, the in-repo amm program is a complete constant-product AMM
with full swap/add/remove/sync logic and an extensive test suite, which means the
entire observation/accumulator/TWAP/truncation/query stack can be built and tested
against a real pool today, ahead of RFP-004's privacy DEX landing.

The hardest part of this work is not the AMM mathematics, which is well
documented; it is reconciling a TWAP's need for trusted, block-boundary
timestamps with the LEZ execution model, where a RISC Zero guest is a pure
function of committed inputs and binds time through validity windows rather than
reading an ambient clock. That execution-model problem is the core of our
technical approach and the area we are strongest in. We propose to ship the
unblocked majority of the work first (standard, accumulator engine, truncation,
manipulation analysis, tooling) and gate only the final privacy-DEX integration
on RFP-004 availability.


Technical Approach

Architecture and stack

  • Language / runtime: Rust on the RISC Zero zkVM, the existing LEZ program
    model (nssa_core accounts, AccountWithMetadata inputs, AccountPostState
    outputs, PDAs, borsh).
  • Framework: SPEL - #[lez_program] / #[instruction] for the guest,
    #[account_type] for the price account and oracle state, generate_idl! for
    IDL, and the spel CLI for transaction submission, dry-runs, and account
    inspection.
  • Crate layout: the established three-crate pattern already present in the
    repo - twap_oracle_core (shared types: instruction enum, OraclePriceAccount,
    oracle/observation state), methods/guest (the on-chain program), and the
    parent crate / examples for IDL generation and the CLI wrapper.
  • Data source: the in-repo constant-product amm. The oracle reads pool
    reserves and, because a v2-style pool exposes no native tick accumulator,
    derives the spot tick from log(reserve_b / reserve_a) and advances its own
    tickCumulative under truncation. (See "Anticipated challenges" for the
    v2-vs-v3 reconciliation.)

Time and block-boundary sampling (the central design problem)

A LEZ guest cannot read "now": execution is a pure function of its inputs, and
the AMM precedent binds time via with_timestamp_validity_window(..deadline) and
the SpelOutput block_validity_window / timestamp_validity_window constraints
that the sequencer enforces - not via an ambient clock read. Our accumulator
update therefore treats the observation timestamp as a committed input bound to a
block through the validity-window mechanism, so that "sample at the block boundary
before same-block trades" (Oracle Security ) becomes "record an observation as a
function of the pre-trade pool state, bound to a verified block." The first
implementation task is to confirm the exact time/block primitive the LEZ guest is
given (committed block context vs. validity-window binding only) and lock the
observation-timestamp design around it; the manipulation analysis and staleness
(maxAge) semantics both depend on this being precise.

Accumulator engine, truncation, cardinality

  • Tick accumulators in log-price space, geometric-mean TWAP between two
    observations (difference of tickCumulative over elapsed time), per the v3
    rationale in the RFP.
  • Per-block tick-delta truncation applied before the tickCumulative
    update: each update clamps the recorded delta against the previous block's tick
    to a per-pool, owner-governable MAX_TICK_DELTA (default 9,116). The
    manipulation-cost analysis reports figures both with and without truncation, as
    required.
  • Observation ring buffer with configurable cardinality (default 1,
    expandable to 65,535). Expansion is atomic - a partial failure leaves existing
    observations intact (Reliability).

Canonical price-account standard

We finish the seeded OraclePriceAccount: enforce reject-on-write for zero /
negative / invalid prices, populate base_asset / quote_asset as canonical IDs
(token mint IDs for LEZ tokens; agreed IDs such as USD otherwise), and publish
the price-account IDL as a standalone artefact importable without depending on
the TWAP program, so external adaptors (RFP-020, future Pyth) share it. The
struct stays append-friendly for forward evolution.

Query interface, registration, errors

  • observe(pool, window, maxAge) returns the TWAP price and the observation
    timestamps used; reads older than maxAge return an error, not a stale value
    (Functionality). A query is read-only and never mutates oracle state
    (Reliability ).
  • Owner-gated register / deregister of TWAP feed sources (pools). External
    sources publish their own price accounts directly and are not registered here
    (Functionality).
  • Per-pool isolation: one pool's failure (accumulator unavailable, cardinality
    exhausted) does not affect queries against other pools (Reliability ).
  • Actionable errors for every failure mode: stale price, no history for the
    window, cardinality too low for the window, zero/negative source price, and
    (base_asset, quote_asset) mismatch (Usability ).

Reference consumer + multi-source pattern

A minimal LEZ reference consumer demonstrating pair verification, reading
price/timestamp/confidence, maxAge rejection, and the safe "refuse, do not fall
back to an unsafe default" behaviour plus a worked multi-source example
(primary feed with staleness fallback and a divergence cross-check that logs but
does not gate), explicitly documented as illustrative since cross-source policy
belongs to the consumer. We also intend to ship the soft-requirement multi-source
helper SDK that packages this policy with diagnostic flags.

Tooling, app, docs

SDK for building Logos modules (query / expand cardinality / register), the
spel-based CLI, a Logos mini-app price-feed dashboard (live TWAP per pool,
side-by-side comparison against any other price account for the same pair,
observation history) loadable in Basecamp via git repo with build instructions
and downloadable assets, Figma designs for the dashboard, a README covering
end-to-end usage, and two doc packets (SDK - including the "Recommended Consumer
Pattern" section - and CLI).

Economic model

Pull-based, matching the RFP's framing: observation history is written as a side
effect of accumulator updates (cost borne by the actor triggering the update);
observe() is a read-only view with no metering; the only explicit cost is
cardinality-expansion rent, borne by the pool registrant choosing the lookback
depth they need. No ongoing protocol subsidy is required once LEZ reaches
moderate TVL.

Testing and performance

Every hard requirement gets at least one test, including the RFP-named cases:
TWAP correctness from known accumulator values, truncation (a synthetic excursion
beyond MAX_TICK_DELTA is clamped and the resulting TWAP matches the truncated
trajectory), maxAge staleness rejection, (base_asset, quote_asset) mismatch
rejection, and register/deregister state transitions. End-to-end tests run
against a LEZ sequencer in standalone mode in CI, kept green on the default
branch. We document the compute-unit cost of each operation (query, accumulator
update, cardinality expansion) and note where large-window proving cost is the
binding constraint.

Anticipated challenges

  1. The time/block primitive (above) is the main technical risk and is
    front-loaded into M1–M2.
  2. v2 source vs. v3 design. The RFP assumes v3 tick accumulators read from the
    DEX, but the available DEX is constant-product with no native accumulator. We
    resolve this by having the oracle maintain its own observation buffer derived
    from reserves; if RFP-004 ships native v3-style accumulators, the reader swaps
    to consume them directly without changing the price-account surface.
  3. RFP-004 dependency. Live integration against the privacy DEX is the only
    genuinely gated item; everything else is exercised against the in-repo AMM. The
    final milestone absorbs RFP-004 integration when it is available.
  4. Build environment. SPEL documents a ring/risc0 riscv32 cross-compilation
    failure (LEZ issue #468) requiring a temporary LEZ fork + [patch]; budgeted
    in M1 setup.

Out of scope (per the RFP)

External oracle adaptors (RFP-020 / future Pyth), confidential or shielded oracle
execution (oracles run public), the reflexive-stablecoin design (RFP-013), and
price-feed composition across chained denominations.


Milestones, Payout and Timeline

Milestone 1 - Setup, canonical standard, reference consumer
Payout: $7,000
Duration: 2 weeks
Deliverables:
  - Workspace + CI scaffolding; resolve the risc0/ring (#468) build issue
  - Finalised OraclePriceAccount: reject-on-write validation, canonical
    base/quote IDs, standalone importable price-account IDL artefact
  - Confirmed time/block-binding primitive design note
  - Reference consumer program (pair verification, maxAge, safe-refuse) +
    worked multi-source pattern, with tests

Milestone 2 - Observation engine, accumulators, truncation, registration
Payout: $12,000
Duration: 3 weeks
Deliverables:
  - Tick-based accumulator storage; configurable cardinality ring buffer
    (1 → 65,535) with atomic expansion
  - Per-block tick-delta truncation (governable MAX_TICK_DELTA), clamp applied
    before tickCumulative update
  - Block-boundary observation recording bound via the validity-window model
  - Owner-gated register / deregister of feed sources, with per-pool isolation
  - Built and unit-tested against the in-repo constant-product AMM

Milestone 3 - Query interface, geometric-mean TWAP, staleness, errors, CU costs
Payout: $9,000
Duration: 2 weeks
Deliverables:
  - observe(pool, window, maxAge) → TWAP price + observation timestamps
  - Geometric-mean computation; read-only query guarantee
  - All RFP error modes with actionable messages
  - Documented compute-unit cost per operation

Milestone 4 - SDK, CLI, mini-app dashboard, Figma, docs, multi-source helper
Payout: $9,000
Duration: 2 weeks
Deliverables:
  - SDK for Logos modules (query / expand cardinality / register)
  - spel-based CLI covering core operations
  - Mini-app price-feed dashboard (Basecamp-loadable) + Figma designs
  - README + SDK doc packet (incl. Recommended Consumer Pattern) + CLI doc packet
  - Soft requirement: multi-source consumer-pattern helper SDK

Milestone 5 - E2E tests, manipulation analysis, devnet/testnet deploy, RFP-004 integration
Payout: $6,000
Duration: 1.5 weeks
Deliverables:
  - Full test matrix (one+ test per hard requirement, incl. truncation,
    staleness, pair-mismatch, registration transitions)
  - E2E tests against a LEZ sequencer (standalone) in CI, green on default branch
  - Manipulation-cost analysis at $1M / $10M / $50M / $100M depth, with and
    without truncation; documented minimum window for lending use
  - Deployed and tested on LEZ devnet/testnet; program addresses documented
  - Integration against the RFP-004 privacy DEX when available (else documented
    against the in-repo AMM with a clearly specified swap-in path)

Milestone 6 - Security review and remediation (Audit)
Payout: $7,000
Duration: 1.5 weeks
Deliverables:
  - Security review focused on oracle manipulation, accumulator/truncation
    correctness, and time-binding soundness
  - Remediation of findings; final report

Total duration: ~12 weeks.

Total Requested Budget (USD)

$50,000 (= 7,000 + 12,000 + 9,000 + 9,000 + 6,000 + 7,000 )


Relevant Experience

  • LEZ programs, merged. LP-0012 - implemented and merged into the LEZ
    programs track. https://github.com/logos-co/lambda-prize/pull/14
  • LP-0013 - RISC Zero zkVM program submitted to logos-blockchain/lez-programs
    (built with RISC0_DEV_MODE=0), with demo video and evaluation note.
    https://github.com/logos-co/lambda-prize/pull/56
  • Confidential-compute research on LEZ - zkVM execution-model work
    (commitment binding, proof-based verification of private inputs) directly
    relevant to the time-binding design that is the core risk in this RFP.
    https://github.com/bristinWild/tuniq-experiments

Stack: Rust, RISC Zero zkVM, SPEL framework, Groth16, Solana/SVM program model,
integration testing, CLI + IDL tooling.


Post-Delivery Plan

bristinWild maintains the program, SDK, CLI, and mini-app after delivery. All
code ships under the MIT + Apache 2.0 dual license in a public repo with an issue
tracker. Because the oracle is consumed by RFP-008 (lending), RFP-013
(stablecoin), and RFP-004 (DEX), the post-delivery commitment includes
integration support for those teams adopting the canonical price-account standard
and the Recommended Consumer Pattern, plus tracking-issue triage and compatibility
fixes as LEZ's compute budget and sequencer interfaces evolve through testnet.


Permissions and Consent

  • I confirm Logos may contact me using the primary contact information
    provided above for follow-ups and next steps.
  • I consent to Logos using information from this proposal publicly such as
    blogs, case studies, social posts, or analytical reporting. Redactions can be
    requested at any time. (optional - uncheck if you prefer)

Program Requirements

  • We understand this project must be open-sourced under the MIT and Apache
    2.0 Licenses unless explicitly approved otherwise.
  • We are prepared to deliver milestone-based outcomes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions