# AggregatorOracle

AggregatorOracle is a smart contract that provides aggregated price feeds from multiple oracle sources.

### Functions

#### \_setPrimarySources

{% code overflow="wrap" %}

```solidity
function _setPrimarySources(address token, uint256 maxPriceDeviation, IBaseOracle[] memory sources) internal
```

{% endcode %}

This function sets the primary oracle sources for a given token.

**Parameters:**

<table><thead><tr><th width="222.33333333333331">Name</th><th width="111">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>token</code></td><td>address</td><td>address of the token for which the primary oracle sources are being set</td></tr><tr><td><code>maxPriceDeviation</code></td><td>uint256</td><td>maximum price deviation allowed for the token's price feed</td></tr><tr><td><code>sources</code></td><td>array</td><td>an array of <code>IBaseOracle</code> contracts representing the primary oracle sources for the token</td></tr></tbody></table>

**Events:**

* `SetPrimarySources`: emitted after the primary oracle sources have been set successfully. The event contains the following parameters:
  * `token`: address of the token for which the primary oracle sources have been set.
  * `maxPriceDeviation`: maximum price deviation allowed for the token's price feed.
  * `oracles`: an array of `IBaseOracle` contracts representing the primary oracle sources for the token.

**Requirements:**

* The `token` parameter must not be the zero address.
* The `maxPriceDeviation` parameter must not be greater than `Constants.MAX_PRICE_DEVIATION` (a constant defined in `BlueBerryConst.sol`).
* The length of the `sources` array must be less than or equal to 3.
* The address of each `IBaseOracle` contract in the `sources` array must not be the zero address.

#### setPrimarySources

{% code overflow="wrap" %}

```solidity
function setPrimarySources(address token, uint256 maxPriceDeviation, IBaseOracle[] memory sources) external onlyOwner
```

{% endcode %}

This function sets the primary oracle sources for a given token, and can only be called by the owner of the contract

**Parameters:**

<table><thead><tr><th width="222.33333333333331">Name</th><th width="111">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>token</code></td><td>address</td><td>address of the token for which the primary oracle sources are being set</td></tr><tr><td><code>maxPriceDeviation</code></td><td>uint256</td><td>maximum price deviation allowed for the token's price feed</td></tr><tr><td><code>sources</code></td><td>array</td><td>an array of <code>IBaseOracle</code> contracts representing the primary oracle sources for the token</td></tr></tbody></table>

**Events**:

* `SetPrimarySources`: emitted after the primary oracle sources have been set successfully. The event contains the following parameters:
  * `token`: address of the token for which the primary oracle sources have been set.
  * `maxPriceDeviation`: maximum price deviation allowed for the token's price feed.
  * `oracles`: an array of `IBaseOracle` contracts representing the primary oracle sources for the token.

**Requirements:**&#x20;

* This function has the same requirements as the `_setPrimarySources` function.

#### setMultiPrimarySources

{% code overflow="wrap" %}

```solidity
function setMultiPrimarySources(address[] memory tokens, uint256[] memory maxPriceDeviationList, IBaseOracle[][] memory allSources) external onlyOwner
```

{% endcode %}

This function sets multiple primary oracle sources for multiple tokens. This function first validates the inputs by ensuring that the length of all arrays is the same. It then calls the internal function \_setPrimarySources() for each token to set its primary sources.

**Parameters:**

<table><thead><tr><th width="260.3333333333333">Name</th><th width="90">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>tokens</code></td><td>array</td><td>an array of addresses of the token for which the primary oracle sources are being set</td></tr><tr><td><code>maxPriceDeviationList</code></td><td>array</td><td>an array of maximum price deviations in base 10000 allowed for the token's price feed</td></tr><tr><td><code>allSources</code></td><td>array</td><td>a 2D array of primary oracle sources for each token</td></tr></tbody></table>

#### \_isValidPrices

{% code overflow="wrap" %}

```solidity
function _isValidPrices(uint256 price0, uint256 price1, uint256 maxPriceDeviation) internal pure returns (bool)
```

{% endcode %}

This is an internal function used to validate the deviation of two given prices.

**Parameters:**

<table><thead><tr><th width="221.33333333333331">Name</th><th width="160">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>price0</code></td><td>uint256</td><td>the first price in base 1e18</td></tr><tr><td><code>price1</code></td><td>uint256</td><td>the second price in base 1e18</td></tr><tr><td><code>maxPriceDeviation</code></td><td>uint256</td><td>the maximum price deviation in base 10000</td></tr></tbody></table>

#### getPrice

{% code overflow="wrap" %}

```solidity
function getPrice(address token) external view override returns (uint256)
```

{% endcode %}

This function returns the USD price of a given token. The price is multiplied by 10^18. It also supports at most 3 oracle sources per token.

**Parameters:**

* `token` (address): The address of the token to get the price of

**Return:**

* `uint256`: The USD price of the token, multiplied by 10^18

**Logic**:

1. Check if there is at least one primary oracle source for the token. If there isn't, revert with the NO\_PRIMARY\_SOURCE error.
2. Create a dynamic array of uint256 called prices with a length of candidateSourceCount, which is the number of primary oracle sources for the token.
3. Loop through each primary oracle source for the token and try to get the price. If successful, add the price to the prices array and increment the validSourceCount.
4. If there are no valid prices, revert with the NO\_VALID\_SOURCE error.
5. Sort the prices in ascending order.
6. Get the max price deviation for the token.
7. Depending on the number of valid sources, calculate the price using one of the following methods:
   * If there is only one valid source, return the price.
   * If there are two valid sources, check if the prices are within the max price deviation. If they are, return the average price. If not, revert with the EXCEED\_DEVIATION error.
   * If there are three valid sources, check if each pair of prices is within the max price deviation. If all pairs are within the deviation threshold, return the median price. If one pair is within the deviation threshold, return the average of that pair. If none of the pairs are within the deviation threshold, revert with the EXCEED\_DEVIATION error.
