# 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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#state-variables" id="state-variables"></a>

#### [ILK\_INDEX](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#ilk_index" id="ilk_index"></a>

```
uint8 public immutable ILK_INDEX;
```

#### [QUORUM](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#quorum" id="quorum"></a>

```
uint8 public immutable QUORUM;
```

#### [MAX\_CHANGE](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#max_change" id="max_change"></a>

```
uint256 public immutable MAX_CHANGE;
```

#### [FEED0](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#feed0" id="feed0"></a>

```
IReserveFeed public immutable FEED0;
```

#### [FEED1](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#feed1" id="feed1"></a>

```
IReserveFeed public immutable FEED1;
```

#### [FEED2](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#feed2" id="feed2"></a>

```
IReserveFeed public immutable FEED2;
```

#### [currentExchangeRate](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#currentexchangerate" id="currentexchangerate"></a>

```
uint256 public currentExchangeRate;
```

#### [lastUpdated](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#lastupdated" id="lastupdated"></a>

```
uint256 public lastUpdated;
```

### [Functions](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#functions" id="functions"></a>

#### [constructor](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#initializeexchangerate" id="initializeexchangerate"></a>

Initializes the `currentExchangeRate` state variable.

*Called once during construction.*

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

#### [updateExchangeRate](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <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](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#events" id="events"></a>

#### [UpdateExchangeRate](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#updateexchangerate-1" id="updateexchangerate-1"></a>

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

### [Errors](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#errors" id="errors"></a>

#### [InvalidQuorum](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#invalidquorum" id="invalidquorum"></a>

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

#### [InvalidFeedLength](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#invalidfeedlength" id="invalidfeedlength"></a>

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

#### [InvalidMaxChange](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#invalidmaxchange" id="invalidmaxchange"></a>

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

#### [InvalidMinMax](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#invalidminmax" id="invalidminmax"></a>

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

#### [InvalidInitialization](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#invalidinitialization" id="invalidinitialization"></a>

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

#### [UpdateCooldown](https://docs.ionprotocol.io/devs/smart-contract-architecture/oracles/reserve/broken-reference) <a href="#updatecooldown" id="updatecooldown"></a>

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