# YieldOracle

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

**Inherits:** IYieldOracle, Ownable2Step

An on-chain oracle that provides the APY for each collateral type.

*This contract stores a history of the exchange rates of each collateral for the past `LOOK_BACK` days. Every time that `updateAll()` is called, it will update the value at `currentIndex` in the `historicalExchangeRates` with the current exchange rate and it will also calculate the APY for each collateral type based on the data currently in the buffer. The APY is calculated by taking the difference between the new element being added and the element being replaced. This provides a growth amount of `LOOK_BACK` days. This value is then projected out to a year. Similar to the `InterestRate` module, as the amount of collaterals added to the market increases, storage reads during interest accrual can become prohibitively expensive. Therefore, this contract is heavily optimized at the unfortunate cost of code-complexity.*

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

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

```
uint32[ILK_COUNT] public apys;
```

#### [historicalExchangeRates](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#historicalexchangerates" id="historicalexchangerates"></a>

```
uint64[ILK_COUNT][LOOK_BACK] public historicalExchangeRates;
```

#### [ADDRESS0](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#address0" id="address0"></a>

```
address public immutable ADDRESS0;
```

#### [ADDRESS1](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#address1" id="address1"></a>

```
address public immutable ADDRESS1;
```

#### [ADDRESS2](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#address2" id="address2"></a>

```
address public immutable ADDRESS2;
```

#### [ionPool](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#ionpool" id="ionpool"></a>

```
IonPool public ionPool;
```

#### [currentIndex](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#currentindex" id="currentindex"></a>

```
uint32 public currentIndex;
```

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

```
uint48 public lastUpdated;
```

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

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

Creates a new `YieldOracle` instance.

```
constructor(
    uint64[ILK_COUNT][LOOK_BACK] memory _historicalExchangeRates,
    address _weEth,
    address _stader,
    address _swell,
    address owner
)
    Ownable(owner);
```

**Parameters**

| Name                       | Type                           | Description                                                        |
| -------------------------- | ------------------------------ | ------------------------------------------------------------------ |
| `_historicalExchangeRates` | `uint64[ILK_COUNT][LOOK_BACK]` | An initial set of values for the historical exchange rates matrix. |
| `_weEth`                   | `address`                      | Address of the weETH contract.                                     |
| `_stader`                  | `address`                      | Address of the Stader deposit contract.                            |
| `_swell`                   | `address`                      | Address of the Swell Eth contract.                                 |
| `owner`                    | `address`                      | Admin address.                                                     |

#### [updateIonPool](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#updateionpool" id="updateionpool"></a>

Updates the `IonPool` reference.

```
function updateIonPool(IonPool _ionPool) external onlyOwner;
```

**Parameters**

| Name       | Type      | Description   |
| ---------- | --------- | ------------- |
| `_ionPool` | `IonPool` | pool instance |

#### [updateAll](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#updateall" id="updateall"></a>

Every update should also accrue interest on `IonPool`. This is because an update to the apy changes interest rates which means the previous interest rate must be accrued, or else its effect will be lost. NOTE: This contract should continue to function as normal even if `IonPool` is paused.

```
function updateAll() external;
```

#### [\_updateAll](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#updateall" id="updateall"></a>

Handles the logic for updating the APYs and the historical exchange rates matrix. If the last update was less than `UPDATE_LOCK_LENGTH` seconds ago, then this function will revert. If APY is ever negative, then it will simply be set to 0.

```
function _updateAll() internal;
```

#### [\_getExchangeRate](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#getexchangerate" id="getexchangerate"></a>

Returns the exchange rate for a given collateral.

```
function _getExchangeRate(uint256 ilkIndex) internal view returns (uint64 exchangeRate);
```

**Parameters**

| Name       | Type      | Description                  |
| ---------- | --------- | ---------------------------- |
| `ilkIndex` | `uint256` | The index of the collateral. |

**Returns**

| Name           | Type     | Description  |
| -------------- | -------- | ------------ |
| `exchangeRate` | `uint64` | exchangeRate |

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

#### [ApyUpdate](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#apyupdate" id="apyupdate"></a>

```
event ApyUpdate(uint256 indexed ilkIndex, uint256 newApy);
```

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

#### [InvalidExchangeRate](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#invalidexchangerate" id="invalidexchangerate"></a>

```
error InvalidExchangeRate(uint256 ilkIndex);
```

#### [InvalidIlkIndex](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#invalidilkindex" id="invalidilkindex"></a>

```
error InvalidIlkIndex(uint256 ilkIndex);
```

#### [AlreadyUpdated](broken://pages/Gmo2F6ZIPdQ0CvP3oBdI) <a href="#alreadyupdated" id="alreadyupdated"></a>

```
error AlreadyUpdated();
```


---

# 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/yieldoracle.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.
