# ReserveOracle

[Git Source](https://github.com/Ion-Protocol/ion-protocol/blob/88cc595825f1dc2eb738fb93e172a3e8ab7a5c43/src/oracles/reserve/ReserveOracle.sol)

Reserve oracles are used to determine the LST provider exchange rate and is utilizated by Ion's liquidation module. Liquidations will only be triggered against this exchange rate and will be completely market-price agnostic. Importantly, this means that liquidations will only be triggered through lack of debt repayment or slashing events.

*In order to protect against potential provider bugs or incorrect one-off values (malicious or accidental), the reserve oracle does not use live data. Instead it will query the exchange every intermittent period and persist the value and this value can only move up or down by a maximum percentage per query. If additional data sources are available, they can be involved as `FEED`s. If other `FEED`s are provided to the reserve oracle, a mean of all the `FEED`s is compared to the protocol exchange rate and the minimum of the two is used as the new exchange rate. This final value is subject to the bounding rules.*

### [State Variables](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#state-variables" id="state-variables"></a>

#### [ILK\_INDEX](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#ilk_index" id="ilk_index"></a>

```
uint8 public immutable ILK_INDEX;
```

#### [QUORUM](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#quorum" id="quorum"></a>

```
uint8 public immutable QUORUM;
```

#### [MAX\_CHANGE](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#max_change" id="max_change"></a>

```
uint256 public immutable MAX_CHANGE;
```

#### [FEED0](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#feed0" id="feed0"></a>

```
IReserveFeed public immutable FEED0;
```

#### [FEED1](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#feed1" id="feed1"></a>

```
IReserveFeed public immutable FEED1;
```

#### [FEED2](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#feed2" id="feed2"></a>

```
IReserveFeed public immutable FEED2;
```

#### [currentExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#currentexchangerate" id="currentexchangerate"></a>

```
uint256 public currentExchangeRate;
```

#### [lastUpdated](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#lastupdated" id="lastupdated"></a>

```
uint256 public lastUpdated;
```

### [Functions](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#functions" id="functions"></a>

#### [constructor](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#constructor" id="constructor"></a>

Creates a new `ReserveOracle` instance.

```
constructor(uint8 _ilkIndex, address[] memory _feeds, uint8 _quorum, uint256 _maxChange);
```

**Parameters**

| Name         | Type        | Description                                                  |
| ------------ | ----------- | ------------------------------------------------------------ |
| `_ilkIndex`  | `uint8`     | of the associated collateral.                                |
| `_feeds`     | `address[]` | Alternative data sources to be used for the reserve oracle.  |
| `_quorum`    | `uint8`     | The number of feeds to aggregate.                            |
| `_maxChange` | `uint256`   | Maximum percent change between exchange rate updates. \[RAY] |

#### [\_getProtocolExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the protocol exchange rate.

*Must be implemented in the child contract with LST-specific logic.*

```
function _getProtocolExchangeRate() internal view virtual returns (uint256);
```

**Returns**

| Name     | Type      | Description                 |
| -------- | --------- | --------------------------- |
| `<none>` | `uint256` | The protocol exchange rate. |

#### [getProtocolExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#getprotocolexchangerate" id="getprotocolexchangerate"></a>

Returns the protocol exchange rate.

```
function getProtocolExchangeRate() external view returns (uint256);
```

**Returns**

| Name     | Type      | Description                 |
| -------- | --------- | --------------------------- |
| `<none>` | `uint256` | The protocol exchange rate. |

#### [\_aggregate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#aggregate" id="aggregate"></a>

Queries values from whitelisted data feeds and calculates the mean. This does not include the protocol exchange rate.

```
function _aggregate(uint8 _ILK_INDEX) internal view returns (uint256 val);
```

**Parameters**

| Name         | Type    | Description                   |
| ------------ | ------- | ----------------------------- |
| `_ILK_INDEX` | `uint8` | of the associated collateral. |

#### [\_bound](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#bound" id="bound"></a>

Bounds the value between the min and the max.

```
function _bound(uint256 value, uint256 min, uint256 max) internal pure returns (uint256);
```

**Parameters**

| Name    | Type      | Description              |
| ------- | --------- | ------------------------ |
| `value` | `uint256` | The value to be bounded. |
| `min`   | `uint256` | The minimum bound.       |
| `max`   | `uint256` | The maximum bound.       |

#### [\_initializeExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#initializeexchangerate" id="initializeexchangerate"></a>

Initializes the `currentExchangeRate` state variable.

*Called once during construction.*

```
function _initializeExchangeRate() internal;
```

#### [updateExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#updateexchangerate" id="updateexchangerate"></a>

Updates the `currentExchangeRate` state variable.

*Takes the minimum between the aggregated values and the protocol exchange rate, then bounds it up to the maximum change and writes the bounded value to the state. NOTE: keepers should call this update to reflect recent values*

```
function updateExchangeRate() external;
```

### [Events](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#events" id="events"></a>

#### [UpdateExchangeRate](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#updateexchangerate-1" id="updateexchangerate-1"></a>

```
event UpdateExchangeRate(uint256 exchangeRate);
```

### [Errors](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#errors" id="errors"></a>

#### [InvalidQuorum](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidquorum" id="invalidquorum"></a>

```
error InvalidQuorum(uint8 invalidQuorum);
```

#### [InvalidFeedLength](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidfeedlength" id="invalidfeedlength"></a>

```
error InvalidFeedLength(uint256 invalidLength);
```

#### [InvalidMaxChange](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidmaxchange" id="invalidmaxchange"></a>

```
error InvalidMaxChange(uint256 invalidMaxChange);
```

#### [InvalidMinMax](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidminmax" id="invalidminmax"></a>

```
error InvalidMinMax(uint256 invalidMin, uint256 invalidMax);
```

#### [InvalidInitialization](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#invalidinitialization" id="invalidinitialization"></a>

```
error InvalidInitialization(uint256 invalidExchangeRate);
```

#### [UpdateCooldown](broken://pages/k2Rk8fFJPV5ruyirxs6s) <a href="#updatecooldown" id="updatecooldown"></a>

```
error UpdateCooldown(uint256 lastUpdated);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/reserveoracle.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
