Skip to content
Tessera

Oracle & pricing

Tessera reads prices for all collateral (tAAPL, tTSLA, tSPY) and the debt asset (USDC) through a dedicated oracle router contract called PriceGuard. This separation of concerns — prices are managed in their own contract, not in the vault — means oracle policy can evolve without ever touching the vault's funds-holding code.

How prices are read

When you borrow or liquidate, the vault calls PriceGuard.getPrice(token), which returns an 8-decimal USD price (Chainlink convention: 1e8 = $1.00). PriceGuard internally: (1) Reads the primary oracle feed (e.g., Chainlink's AAPL / USD feed on mainnet). (2) Optionally checks a secondary feed and halts if they deviate too sharply. (3) Validates that the price is not stale (within a freshness window, e.g., < 15 minutes old). (4) If the market is closed (weekend / holiday), notes this state so the vault can haircut new borrows. (5) Returns the price, or reverts if any check fails.

This design is conservative: the vault does not have to know about freshness, deviation, or market hours. It just asks PriceGuard for a price; if the price isn't defensible, it doesn't get one.

Staleness: fails closed

If a price feed hasn't updated in too long (default: 15 minutes on testnet), PriceGuard considers it stale and reverts. This happens in the vault's borrow() and liquidate() calls — they will not execute if the price is stale.

Why fail closed? Because a stale price is worse than no action. If you could borrow at a stale price, you might borrow too much and not realize it. If you could liquidate at a stale price, you might liquidate in the wrong direction. Failing closed (reverting the transaction) forces the oracle to update or the action to wait.

Note: reading your health factor via the Lens (a read-only oracle wrapper) does not fail closed; it returns the best price it can. This is intentional — you should always be able to check your health, even if the oracle is slightly stale. But state-changing actions (borrow, liquidate) require a fresh price.

Testnet mock oracle

On Robinhood Chain testnet (chain 46630), Tessera uses a mock oracle for tAAPL, tTSLA, and tSPY. This is a simple ERC-20-style price feed that the operator can update. It is not a real Chainlink feed.

Why a mock? Chainlink oracle infrastructure for Robinhood Chain does not yet exist (the chain itself is testnet). We use a mock so we can test the full stack without waiting for Chainlink's infrastructure team. At mainnet, we will deploy a real Chainlink oracle or an equivalent licensed feed.

The testnet oracle can be updated by the operator in seconds. Prices are not validated against real-world data. This is fit-for-testing, not fit-for-production. At mainnet, a real oracle (Chainlink or equivalent) is a non-negotiable gate.

Market-closed haircut

When the US equity market is closed (nights, weekends, holidays), the PriceGuard sets a market_closed flag. The vault reads this flag and applies a haircut to new borrows.

Example: tAAPL normally supports 50% LTV. When the market closes at 4pm ET Friday, new borrows are haircut to 42.5% LTV (85% of 50%). This prices in the overnight/weekend gap risk — you can still borrow, but you're borrowing less against the same collateral.

The haircut is applied only to new borrows; existing loans are not affected. The price itself is still the last trade price from market close, not a predicted Monday open. So if a stock gaps hard at Monday open, your position can still be underwater at the old price.

Dual-feed deviation check

On mainnet, PriceGuard can be configured with a secondary oracle feed as a sanity check. If the secondary feed deviates sharply from the primary (e.g., > 5% difference), PriceGuard sets a halted flag.

When halted is true, the vault blocks new risk (borrow and withdraw operations), but allows debt reduction (repay and liquidate). This protects lenders: if the oracle is acting weird, we stop new borrowing but let existing debt be repaid and underwater positions be liquidated.

Price precision

All prices are 8-decimal USD (Chainlink standard). Collateral tokens (tAAPL, tTSLA, tSPY) are 18 decimals; USDC is 6 decimals. The interest-model and liquidation math handles the decimals correctly, so you don't have to think about it — the numbers just work.

Frequency of price updates

The vault does not poll prices. Prices are read on demand whenever you execute an action (borrow, repay, liquidate, lend, withdraw). Between actions, the last price on the oracle is the current price — it may be stale if the market just moved.

The agent (the Watcher) reads prices ~every 10 seconds via RPC to check your health and decide whether to liquidate or repay. But the on-chain prices are only snapshotted when you submit a transaction.