> ## Documentation Index
> Fetch the complete documentation index at: https://docs.redpotion.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Oracle

> Oracle is the fund's NAV/price reporting and batch clock. It:

> Source: [`src/Oracle.sol`](https://github.com/zentryHQ/red-potion-contract/blob/main/src/Oracle.sol)

## Responsibility

`Oracle` is the fund's **NAV/price reporting and batch clock**. It:

* Defines **batches**: time windows separated by `nextCutoffTime`. Deposit/redeem requests are grouped by batch id, and each batch is priced by exactly one accepted report per asset.
* Receives **price reports** (asset price per share, 1e18-scaled) from an off-chain reporter, holds them as *pending* through a review window, and flags **suspicious** prices using configurable safety bounds.
* Releases accepted prices to the [Fund](/developers/contract-reference/fund) during settlement and stores `lastAcceptedPrice` per asset.

Prices use the convention `shares = amount × 1e18 / price` — `price` is the amount of that asset corresponding to one share. The accept functions are `onlyFund` — reachable only through `Fund.acceptReport` / `Fund.acceptSuspiciousReport`. Other admin/reporter functions authorize against the Fund's access control (spoke pattern).

## Batch semantics

* `currentBatchId` is the batch awaiting a report; `getCurrentBatchId()` returns `currentBatchId + 1` once `block.timestamp >= nextCutoffTime`, so **new requests automatically roll into the next batch** while the closed batch is priced.
* Accepting a report **advances** `currentBatchId` and requires a new future `nextCutoffTime` in the same call.

## Report lifecycle

```mermaid theme={"dark"}
sequenceDiagram
    actor R as SUBMIT_REPORT_ROLE
    actor A as ACCEPT_REPORT_ROLE
    participant O as Oracle
    participant F as Fund

    Note over O: batch closes (block.timestamp ≥ nextCutoffTime)
    R->>O: submitReport([{asset, price}, ...])
    O->>O: price-safety check → suspicious flag per asset
    Note over O: pending report — must wait minAcceptReportDelay
    alt price looks wrong
        A->>O: rejectReport(assets) — pending cleared, resubmit
    else within [min, max] accept window
        A->>F: Fund.acceptReport(nextCutoffTime)
        F->>O: acceptReport(assets, nextCutoffTime)
        O->>O: consume pending → lastAcceptedPrice, batchId++, set next cutoff
        O-->>F: (batchId, prices) → Fund settles queues
    end
```

## Timing rules

| Rule                                                        | Effect                                              |
| ----------------------------------------------------------- | --------------------------------------------------- |
| `block.timestamp >= nextCutoffTime`                         | Batch must be closed before submit/accept.          |
| `elapsed >= minAcceptReportDelay` (default 1 hour)          | Mandatory review window between submit and accept.  |
| `elapsed <= maxAcceptReportDelay` (default 7 days)          | Stale reports cannot be accepted; resubmit instead. |
| Both delays capped at 30 days; min ≤ max; neither can be 0. |                                                     |

## Price safety

Each check is optional; `0` disables it.

| Field                   | Suspicious when                                           |
| ----------------------- | --------------------------------------------------------- |
| `minPrice` / `maxPrice` | Reported price outside the absolute bounds.               |
| `maxAbsoluteDelta`      | Change vs `lastAcceptedPrice` exceeds the absolute delta. |
| `maxDeviationBps`       | Change vs `lastAcceptedPrice` exceeds the bps deviation.  |

A suspicious report is **not rejected** — it stays pending but can only be consumed via `Fund.acceptSuspiciousReport` (a stronger role), or replaced after rejection.

## Function reference

### Reporter / reviewer

Roles are checked on the Fund.

| Function                  | Role                 | Description                                                                                                                                                                                                                                                   |
| ------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `submitReport(reports[])` | `SUBMIT_REPORT_ROLE` | Submit `{asset, price}` pairs for the closed batch. Runs safety checks, stores pending reports with a `suspicious` flag. Reverts on zero price, batch not closed, or already-accepted report. Re-submitting overwrites a pending report and resets its timer. |
| `rejectReport(assets[])`  | `REJECT_REPORT_ROLE` | Deletes pending reports for the listed assets so they can be resubmitted.                                                                                                                                                                                     |

### Fund-only

Reached via `Fund.acceptReport*`.

| Function                                           | Access     | Description                                                                                                                                                                                                            |
| -------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `acceptReport(assets[], nextCutoffTime)`           | `onlyFund` | Verifies batch closed, no suspicious pending report, every asset inside its accept window; consumes pending reports, updates `lastAcceptedPrice`, advances the batch, sets next cutoff. Returns `(batchId, prices[])`. |
| `acceptSuspiciousReport(assets[], nextCutoffTime)` | `onlyFund` | Same, but skips the suspicious check.                                                                                                                                                                                  |

### Admin setters

Roles are checked on the Fund.

| Function                                                            | Role                               | Description                                                                              |
| ------------------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- |
| `setPriceSafety(asset, safety)` / `setPriceSafetyBatch(safeties[])` | `SET_PRICE_SAFETY_ROLE`            | Per-asset safety bounds. `maxDeviationBps ≤ 10000`, `minPrice ≤ maxPrice` when both set. |
| `setNextCutoffTime(t)`                                              | `SET_NEXT_CUTOFF_TIME_ROLE`        | Move the current batch's cutoff (must be future).                                        |
| `setMinAcceptReportDelay(d)`                                        | `SET_MIN_ACCEPT_REPORT_DELAY_ROLE` | Adjust the review window (≤ 30 days, ≤ max).                                             |
| `setMaxAcceptReportDelay(d)`                                        | `SET_MAX_ACCEPT_REPORT_DELAY_ROLE` | Adjust the staleness limit (≤ 30 days, ≥ min).                                           |

## Views

`getCurrentBatchId()`, `currentBatchId`, `nextCutoffTime`, `getReport(asset, batchId)`, `getPendingReport(asset, batchId)`, `lastAcceptedPrice(asset)`, `priceSafety(asset)`, `minAcceptReportDelay`, `maxAcceptReportDelay`, `fund()`.

## Related

[Fund](/developers/contract-reference/fund) · [DepositQueue](/developers/contract-reference/deposit-queue) · [RedeemQueue](/developers/contract-reference/redeem-queue)
