From 2ca524fdf6e5f45e467f5bf819236fdd1bde5b7d Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Tue, 12 Sep 2023 20:04:36 +1000 Subject: [PATCH 01/23] Added AggregatorV3Interface diagram --- .../contracts/interfaces/chainlink/README.md | 3 ++ contracts/docs/AggregatorV3Interface.svg | 28 +++++++++++++++++++ contracts/docs/generate.sh | 5 ++++ 3 files changed, 36 insertions(+) create mode 100644 contracts/contracts/interfaces/chainlink/README.md create mode 100644 contracts/docs/AggregatorV3Interface.svg diff --git a/contracts/contracts/interfaces/chainlink/README.md b/contracts/contracts/interfaces/chainlink/README.md new file mode 100644 index 0000000000..456fa4c904 --- /dev/null +++ b/contracts/contracts/interfaces/chainlink/README.md @@ -0,0 +1,3 @@ +# Diagrams + +![AggregatorV3Interface](../../../docs/AggregatorV3Interface.svg) diff --git a/contracts/docs/AggregatorV3Interface.svg b/contracts/docs/AggregatorV3Interface.svg new file mode 100644 index 0000000000..061050d054 --- /dev/null +++ b/contracts/docs/AggregatorV3Interface.svg @@ -0,0 +1,28 @@ + + + + + + +UmlClassDiagram + + + +187 + +<<Interface>> +AggregatorV3Interface +../contracts/interfaces/chainlink/AggregatorV3Interface.sol + +External: +     decimals(): uint8 +     description(): string +     version(): uint256 +     getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) +     latestRoundData(): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) + + + diff --git a/contracts/docs/generate.sh b/contracts/docs/generate.sh index 7df12538a4..562f050219 100644 --- a/contracts/docs/generate.sh +++ b/contracts/docs/generate.sh @@ -22,6 +22,11 @@ sol2uml .. -v -hv -hf -he -hs -hl -b OETHHarvester -o OETHHarvesterHierarchy.svg sol2uml .. -s -d 0 -b OETHHarvester -o OETHHarvesterSquashed.svg sol2uml storage .. -c OETHHarvester -o OETHHarvesterStorage.svg + +# contracts/interfaces/chainlink + +sol2uml .. -b AggregatorV3Interface -o AggregatorV3Interface.svg + # contracts/governance sol2uml .. -v -hv -hf -he -hs -hl -b Governor -o GovernorHierarchy.svg sol2uml .. -s -d 0 -b Governor -o GovernorSquashed.svg From 876fd06b35d74ebb7dcf17a99654b8b8dcfdf66c Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Tue, 12 Sep 2023 20:47:17 +1000 Subject: [PATCH 02/23] Updated OETH Oracle contracts diagram --- contracts/docs/plantuml/oethOracles.png | Bin 52265 -> 57223 bytes contracts/docs/plantuml/oethOracles.puml | 84 ++++++++++++++++++----- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/contracts/docs/plantuml/oethOracles.png b/contracts/docs/plantuml/oethOracles.png index 05161a2e38ab78c104e66a7d4fc28c3f89e2b81a..2c173ccd1c3ed74dbeb7a4b7e189271a9b9987af 100644 GIT binary patch literal 57223 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 literal 52265 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 diff --git a/contracts/docs/plantuml/oethOracles.puml b/contracts/docs/plantuml/oethOracles.puml index 4747fab1fe..7ea90362d2 100644 --- a/contracts/docs/plantuml/oethOracles.puml +++ b/contracts/docs/plantuml/oethOracles.puml @@ -20,11 +20,19 @@ pairs: \trETH/ETH } -object "FrxEthFraxOracle" as fo <> { +object "OETHOracleUpdater" as oou <> #DeepSkyBlue { +pair: OETH/ETH +} + +object "frxETHOracleUpdater" as fou <> #DeepSkyBlue { pair: frxETH/ETH } -object "FrxEthEthDualOracle" as fdo <> { +object "OETHOracle" as oetho <> #DeepSkyBlue { +pair: OETH/ETH +} + +object "frxETHOracle" as frxo <> #DeepSkyBlue { pair: frxETH/ETH } @@ -36,35 +44,73 @@ object "External\nAccess\nControlled\nAggregator" as clstETH <> { pair: stETH/ETH } -object "External\nAccess\nControlled\nAggregator" as cleth <> { -pair: ETH/USD +object "OETH/ETH Pool" as coep <> { +assets: OETH, ETH } -object "External\nAccess\nControlled\nAggregator" as clfrax <> { -pair: FRAX/USD +object "frxETH/OETH Pool" as cfop <> { +assets: frxETH, OETH } -object "frxETH/ETH Pool" as cp <> { +object "frxETH/ETH Pool" as cfep <> { assets: frxETH, ETH } -object "StaticOracle" as uso <> { +object "frxETH/WETH Pool" as cfwp <> { +assets: frxETH, WETH } -object "frxETH/FRAX Pool" as up <> { - assets: frxETH, FRAX +object "OETH/ETH Pool" as boep <> { +assets: OETH, ETH } vault ..> router : price(asset) -router ...> clrETH : latestRoundData() -router ...> clstETH : latestRoundData() -router ..> fo : latestRoundData() -fdo .> fo : addRoundData() -fdo ....> cp : price_oracle() -fdo ....> uso : quoteSpecificPoolsWithTimePeriod() -uso .> up : observe() -fdo ..> cleth : latestRoundData() -fdo ..> clfrax : latestRoundData() +router ..> clrETH : latestRoundData() +router ..> clstETH : latestRoundData() + +vault <.. oou : price() +oetho <.. oou : addRoundData() +oou ...> coep : price_oracle() +oou ...> cfop : price_oracle() +oou ...> boep : price_oracle() + +router ..> frxo : latestRoundData() +fou ..> frxo : addRoundData() +fou ...> cfep : price_oracle() +fou ...> cfwp : price_oracle() + + +' object "FrxEthFraxOracle" as fo <> { +' pair: frxETH/ETH +' } + +' object "FrxEthEthDualOracle" as fdo <> { +' pair: frxETH/ETH +' } + + +' object "External\nAccess\nControlled\nAggregator" as cleth <> { +' pair: ETH/USD +' } + +' object "External\nAccess\nControlled\nAggregator" as clfrax <> { +' pair: FRAX/USD +' } + +' object "StaticOracle" as uso <> { +' } + +' object "frxETH/FRAX Pool" as up <> { +' assets: frxETH, FRAX +' } + +' router ..> fo : latestRoundData() +' fdo .> fo : addRoundData() +' fdo ....> cfep : price_oracle() +' fdo ....> uso : quoteSpecificPoolsWithTimePeriod() +' uso .> up : observe() +' fdo ..> cleth : latestRoundData() +' fdo ..> clfrax : latestRoundData() @enduml \ No newline at end of file From c7dc5b482b06b8dc00878f588bdd78ab7cbc430f Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Tue, 12 Sep 2023 20:53:44 +1000 Subject: [PATCH 03/23] Added price Oracle to vault --- contracts/contracts/interfaces/IVault.sol | 2 + contracts/contracts/vault/VaultCore.sol | 31 +++++++++ contracts/deploy/076_oeth_vault_upgrade.js | 32 ++++++++++ contracts/test/vault/oeth-vault.fork-test.js | 67 +++++++++++++++++--- 4 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 contracts/deploy/076_oeth_vault_upgrade.js diff --git a/contracts/contracts/interfaces/IVault.sol b/contracts/contracts/interfaces/IVault.sol index e6b1668ca9..e2f2334173 100644 --- a/contracts/contracts/interfaces/IVault.sol +++ b/contracts/contracts/interfaces/IVault.sol @@ -120,6 +120,8 @@ interface IVault { function priceUnitRedeem(address asset) external view returns (uint256); + function price() external view returns (uint256); + function withdrawAllFromStrategy(address _strategyAddr) external; function withdrawAllFromStrategies() external; diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index efa8f2ca41..f0bac54c40 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -565,6 +565,37 @@ contract VaultCore is VaultInitializer { Pricing ****************************************/ + /** + * @notice Value of 1 OToken if redeemed using the Vault. + * This includes any redeem fee. + * For example, USD value of 1 OUSD or ETH value of 1 OETH. + * @return price_ USD or ETH value of 1 OToken to 18 decimals + */ + function price() external view returns (uint256 price_) { + uint256 totalAssetsValue = 0; + // For each asset + uint256 assetCount = allAssets.length; + for (uint256 i = 0; i < assetCount; ++i) { + // read the asset address into memory + address assetAddr = allAssets[i]; + + // Get the total amount of assets in the vault + uint256 balance = _checkBalance(assetAddr); + + // total asset value = total asset value + (balance * price) + totalAssetsValue += (_toUnits(balance, assetAddr) * + _toUnitPrice(assetAddr, false)); + } + price_ = totalAssetsValue / oUSD.totalSupply(); + + // adjust for redeem fee + uint256 redeemFeeBpsMem = redeemFeeBps; + // Calculate redeem fee + if (redeemFeeBpsMem > 0) { + price_ = price_ - price_.mulTruncateScale(redeemFeeBpsMem, 1e4); + } + } + /** * @notice Returns the total price in 18 digit units for a given asset. * Never goes above 1, since that is how we price mints. diff --git a/contracts/deploy/076_oeth_vault_upgrade.js b/contracts/deploy/076_oeth_vault_upgrade.js new file mode 100644 index 0000000000..d64e8ba47b --- /dev/null +++ b/contracts/deploy/076_oeth_vault_upgrade.js @@ -0,0 +1,32 @@ +const { deploymentWithGovernanceProposal } = require("../utils/deploy"); + +module.exports = deploymentWithGovernanceProposal( + { + deployName: "076_oeth_vault_upgrade", + forceDeploy: false, + // forceSkip: true, + reduceQueueTime: false, + deployerIsProposer: true, + // proposalId: "", + }, + async ({ ethers, deployWithConfirmation }) => { + const dVaultCore = await deployWithConfirmation("OETHVaultCore"); + + // 2. Connect to the OETH Vault as its governor via the proxy + const cVaultProxy = await ethers.getContract("OETHVaultProxy"); + + // Governance Actions + // ---------------- + return { + name: "Upgrade the OETH Vault with price Oracle.", + actions: [ + // 1. Upgrade the OETH Vault proxy to the new core vault implementation + { + contract: cVaultProxy, + signature: "upgradeTo(address)", + args: [dVaultCore.address], + }, + ], + }; + } +); diff --git a/contracts/test/vault/oeth-vault.fork-test.js b/contracts/test/vault/oeth-vault.fork-test.js index 197b707cb6..7bf4bc61c2 100644 --- a/contracts/test/vault/oeth-vault.fork-test.js +++ b/contracts/test/vault/oeth-vault.fork-test.js @@ -2,6 +2,7 @@ const { expect } = require("chai"); const { formatUnits, parseUnits } = require("ethers/lib/utils"); const addresses = require("../../utils/addresses"); +const { resolveAsset } = require("../../utils/assets"); const { createFixtureLoader, oethDefaultFixture, @@ -20,14 +21,13 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { this.retries(isCI ? 3 : 0); let fixture; + const loadFixture = createFixtureLoader(oethDefaultFixture); + beforeEach(async () => { + fixture = await loadFixture(); + }); describe("OETH Vault", () => { describe("post deployment", () => { - const loadFixture = createFixtureLoader(oethDefaultFixture); - beforeEach(async () => { - fixture = await loadFixture(); - }); - it("Should have the correct governor address set", async () => { const { oethVault, @@ -56,12 +56,63 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { } }); }); + describe("Oracle prices", () => { + const assetPriceRanges = { + WETH: { + min: parseUnits("1"), + max: parseUnits("1"), + }, + stETH: { + min: parseUnits("0.99"), + max: parseUnits("1"), + }, + rETH: { + min: parseUnits("1.08"), + max: parseUnits("1.1"), + }, + frxETH: { + min: parseUnits("0.985"), + max: parseUnits("1"), + }, + }; + for (const [symbol, { min, max }] of Object.entries(assetPriceRanges)) { + it(`Should return a price for minting with ${symbol}`, async () => { + const { oethVault } = fixture; + + const asset = await resolveAsset(symbol); + const price = await oethVault.priceUnitMint(asset.address); + + log(`Price for minting with ${symbol}: ${formatUnits(price, 18)}`); + + expect(price).to.be.gte(min); + expect(price).to.be.lte(max); + }); + it(`Should return a price for redeeming with ${symbol}`, async () => { + const { oethVault } = fixture; + + const asset = await resolveAsset(symbol); + const price = await oethVault.priceUnitRedeem(asset.address); + + log(`Price for redeeming with ${symbol}: ${formatUnits(price, 18)}`); + + expect(price).to.be.gte(min); + expect(price).to.be.lte(max); + }); + } + it("Should return OETH Oracle price", async () => { + const { oethVault } = fixture; + + const price = await oethVault.price(); + + log(`OETH price: ${formatUnits(price, 18)}`); + + expect(price).to.be.gte(parseUnits("0.99")); + expect(price).to.be.lte(parseUnits("1")); + }); + }); describe("user operations", () => { let oethWhaleSigner; - const loadFixture = createFixtureLoader(oethDefaultFixture); beforeEach(async () => { - fixture = await loadFixture(); - await impersonateAccount(oethWhaleAddress); oethWhaleSigner = await ethers.provider.getSigner(oethWhaleAddress); }); From 4c6361c5ac3f282e6824f16017c00ec338dd4961 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 13 Sep 2023 17:07:20 +1000 Subject: [PATCH 04/23] Added reference implementation of OETH Oracle --- contracts/contracts/oracle/BaseOracle.sol | 243 ++++++++++++++++++ .../contracts/oracle/IOracleReceiver.sol | 10 + contracts/contracts/oracle/OETHOracle.sol | 21 ++ .../contracts/oracle/OETHOracleUpdater.sol | 85 ++++++ contracts/contracts/oracle/README.md | 22 +- contracts/contracts/strategies/ICurvePool.sol | 2 + contracts/contracts/vault/VaultCore.sol | 9 +- contracts/deploy/076_oeth_vault_upgrade.js | 47 +++- contracts/docs/OETHOracleHierarchy.svg | 75 ++++++ contracts/docs/OETHOracleSquashed.svg | 65 +++++ contracts/docs/OETHOracleStorage.svg | 87 +++++++ contracts/docs/OETHOracleUpdaterHierarchy.svg | 161 ++++++++++++ contracts/docs/OETHOracleUpdaterSquashed.svg | 52 ++++ contracts/docs/OETHOracleUpdaterStorage.svg | 23 ++ contracts/docs/generate.sh | 10 +- contracts/test/_fixture.js | 5 + contracts/test/oracle/oracle.fork-test.js | 39 ++- contracts/test/vault/oeth-vault.fork-test.js | 6 +- 18 files changed, 943 insertions(+), 19 deletions(-) create mode 100644 contracts/contracts/oracle/BaseOracle.sol create mode 100644 contracts/contracts/oracle/IOracleReceiver.sol create mode 100644 contracts/contracts/oracle/OETHOracle.sol create mode 100644 contracts/contracts/oracle/OETHOracleUpdater.sol create mode 100644 contracts/docs/OETHOracleHierarchy.svg create mode 100644 contracts/docs/OETHOracleSquashed.svg create mode 100644 contracts/docs/OETHOracleStorage.svg create mode 100644 contracts/docs/OETHOracleUpdaterHierarchy.svg create mode 100644 contracts/docs/OETHOracleUpdaterSquashed.svg create mode 100644 contracts/docs/OETHOracleUpdaterStorage.svg diff --git a/contracts/contracts/oracle/BaseOracle.sol b/contracts/contracts/oracle/BaseOracle.sol new file mode 100644 index 0000000000..7754d72707 --- /dev/null +++ b/contracts/contracts/oracle/BaseOracle.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IOracleReceiver } from "./IOracleReceiver.sol"; +import { AggregatorV3Interface } from "../interfaces/chainlink/AggregatorV3Interface.sol"; +import { Governable } from "../governance/Governable.sol"; + +/** + * @title BaseOracle + * @notice Generic Chainlink style oracle + * @author Origin Protocol Inc + */ +abstract contract BaseOracle is + AggregatorV3Interface, + IOracleReceiver, + Governable +{ + /// @notice Contract or account that can call addRoundData() to update the Oracle prices + address public oracleUpdater; + + /// @notice Last round ID where isBadData is false and price is within maximum deviation + uint80 public lastCorrectRoundId; + + /// @notice Historical Oracle prices + Round[] public rounds; + + /// @notice Time in seconds between updates before the price is considered stale + uint256 public heartbeatThreshold; + + /// @notice Packed Round data struct + /// @notice answer Oracle price + /// @notice timestamp timestamp in seconds of price + /// @notice isBadData If data is bad / should be used + struct Round { + uint128 answer; + uint40 timestamp; + bool isBadData; + } + + event SetHeartbeatThreshold(uint256 heartbeatThreshold); + event SetOracleUpdater(address oracleUpdater); + + + constructor( + address _oracleUpdater, + uint256 _maximumOracleDelay + ) Governable() { + _setOracleUpdater(_oracleUpdater); + _setHeartbeatThreshold(_maximumOracleDelay); + } + + /*************************************** + Internal Setters + ****************************************/ + + /// @notice Sets the max oracle delay to determine if data is stale + /// @param _heartbeatThreshold The time in seconds before the price is considered stale + function _setHeartbeatThreshold(uint256 _heartbeatThreshold) internal { + emit SetHeartbeatThreshold(_heartbeatThreshold); + heartbeatThreshold = _heartbeatThreshold; + } + + /// @notice Sets the contract or account that can add Oracle prices + /// @param _oracleUpdater Address of the contract or account that can update the Oracle prices + function _setOracleUpdater(address _oracleUpdater) internal { + emit SetOracleUpdater(_oracleUpdater); + oracleUpdater = _oracleUpdater; + } + + /*************************************** + External Setters + ****************************************/ + + /// @notice Sets the max Oracle delay to determine if data is stale + /// @param _heartbeatThreshold The time in seconds before the price is considered stale + function setHeartbeatThreshold( + uint256 _heartbeatThreshold + ) external onlyGovernor { + _setHeartbeatThreshold(_heartbeatThreshold); + } + + /// @notice Sets the contract or account that can update the Oracle prices + /// @param _oracleUpdater Address of the contract or account that can update the Oracle prices + function setOracleUpdater(address _oracleUpdater) external onlyGovernor { + _setOracleUpdater(_oracleUpdater); + } + + /*************************************** + Metadata + ****************************************/ + + /// @notice The number of decimals in the Oracle price. + function decimals() + external + pure + virtual + override + returns (uint8 _decimals) + { + _decimals = 18; + } + + /// @notice The version number for the AggregatorV3Interface. + /// @dev Adheres to AggregatorV3Interface, which is different than typical semver + function version() + external + view + virtual + override + returns (uint256 _version) + { + _version = 1; + } + + /*************************************** + Oracle Receiver + ****************************************/ + + /// @notice Adds a new Oracle price by the Oracle updater. + /// @param _isBadData Boolean representing if the data is bad + /// @param _answer is the Oracle price with 18 decimals + /// @param _timestamp The timestamp of the update + function addRoundData( + bool _isBadData, + uint128 _answer, + uint40 _timestamp + ) external override { + if (msg.sender != oracleUpdater) revert OnlyOracleUpdater(); + if (_timestamp > block.timestamp) revert CalledWithFutureTimestamp(); + + uint256 _roundsLength = rounds.length; + if ( + _roundsLength > 0 && + _timestamp <= rounds[_roundsLength - 1].timestamp + ) { + revert CalledWithTimestampBeforePreviousRound(); + } + + if (!_isBadData) { + lastCorrectRoundId = uint80(_roundsLength); + } + + rounds.push( + Round({ + isBadData: _isBadData, + answer: _answer, + timestamp: _timestamp + }) + ); + } + + /*************************************** + Prices + ****************************************/ + + function _getRoundData( + uint80 _roundId + ) + internal + view + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) + { + if (rounds.length <= _roundId) revert NoPriceData(); + + Round memory _round = rounds[_roundId]; + answer = int256(uint256(_round.answer)); + + roundId = answeredInRound = _roundId; + startedAt = updatedAt = _round.timestamp; + } + + /// @notice Returns the Oracle price data for a specific round. + /// @param _roundId The round ID + /// @return roundId The round ID + /// @return answer The Oracle price + /// @return startedAt Timestamp of when the round started + /// @return updatedAt Timestamp of when the round was updated + /// @return answeredInRound The round ID in which the answer was computed + function getRoundData( + uint80 _roundId + ) + external + view + override + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) + { + ( + roundId, + answer, + startedAt, + updatedAt, + answeredInRound + ) = _getRoundData(_roundId); + } + + /// @notice Returns the latest Oracle price data. + /// @return roundId The round ID + /// @return answer The Oracle price + /// @return startedAt Timestamp of when the round started + /// @return updatedAt Timestamp of when the round was updated + /// @return answeredInRound The round ID in which the answer was computed + function latestRoundData() + external + view + override + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) + { + ( + roundId, + answer, + startedAt, + updatedAt, + answeredInRound + ) = _getRoundData(lastCorrectRoundId); + } + + /*************************************** + Errors + ****************************************/ + + error CalledWithFutureTimestamp(); + error CalledWithTimestampBeforePreviousRound(); + error NoPriceData(); + error OnlyOracleUpdater(); +} diff --git a/contracts/contracts/oracle/IOracleReceiver.sol b/contracts/contracts/oracle/IOracleReceiver.sol new file mode 100644 index 0000000000..e1e8d48e3a --- /dev/null +++ b/contracts/contracts/oracle/IOracleReceiver.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IOracleReceiver { + function addRoundData( + bool isBadData, + uint128 answer, + uint40 timestamp + ) external; +} diff --git a/contracts/contracts/oracle/OETHOracle.sol b/contracts/contracts/oracle/OETHOracle.sol new file mode 100644 index 0000000000..d5cf773d0b --- /dev/null +++ b/contracts/contracts/oracle/OETHOracle.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { BaseOracle } from "./BaseOracle.sol"; +import { IOracleReceiver } from "./IOracleReceiver.sol"; +import { AggregatorV3Interface } from "../interfaces/chainlink/AggregatorV3Interface.sol"; +import { Governable } from "../governance/Governable.sol"; + +/** + * @title OETH Oracle + * @notice Chainlink style oracle for OETH/ETH + * @author Origin Protocol Inc + */ +contract OETHOracle is BaseOracle { + string public constant override description = "OETH / ETH"; + + constructor( + address _oracleUpdater, + uint256 _maximumOracleDelay + ) BaseOracle(_oracleUpdater, _maximumOracleDelay) {} +} diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol new file mode 100644 index 0000000000..7929e3de57 --- /dev/null +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IOracleReceiver } from "./IOracleReceiver.sol"; +import { IVault } from "../interfaces/IVault.sol"; +import { AggregatorV3Interface } from "../interfaces/chainlink/AggregatorV3Interface.sol"; +import { Governable } from "../governance/Governable.sol"; +import { ICurvePool } from "../strategies/ICurvePool.sol"; + +/** + * @title OETH Oracle Updater + * @notice Gathers OETH pricing data and updates the OEHOracle contract. + * @author Origin Protocol Inc + */ +contract OETHOracleUpdater is Governable { + ICurvePool public immutable curvePool; + IVault public immutable vault; + + struct OracleUpdaterConfig { + address vault; + address curvePool; + } + + constructor(address _vault, address _curvePool) Governable() { + curvePool = ICurvePool(_curvePool); + vault = IVault(_vault); + } + + /// @notice Adds new Oracle price to an Oracle + /// @dev Callable by anyone as the prices are sourced and aggregated on-chain. + /// @param oracle Address of the Oracle that has this contract set as its priceSource + function addRoundData(IOracleReceiver oracle) external { + (bool isBadData, uint256 answer, , ) = _getPrices(); + + // Authorization is handled on Oracle side + oracle.addRoundData({ + isBadData: isBadData, + answer: uint128(answer), + timestamp: uint40(block.timestamp) + }); + } + + function _getPrices() + internal + view + returns ( + bool isBadData, + uint256 answer, + uint256 vaultPrice, + uint256 curvePrice + ) + { + // Get price from the Vault + vaultPrice = vault.price(); + + // Get price from the Curve pool + curvePrice = curvePool.price_oracle(); + + // TODO check if the data is bad + isBadData = false; + + // Return the Curve price with the Vault price as the floor price + if (curvePrice > vaultPrice) { + answer = curvePrice; + } else { + answer = vaultPrice; + } + } + + /// @notice Get the latest price from the Vault and Curve pool + /// @return isBadData is true when data is stale or otherwise bad + /// @return answer is the latest Oracle price + function getPrices() + external + view + returns ( + bool isBadData, + uint256 answer, + uint256 vaultPrice, + uint256 curvePrice + ) + { + (isBadData, answer, vaultPrice, curvePrice) = _getPrices(); + } +} diff --git a/contracts/contracts/oracle/README.md b/contracts/contracts/oracle/README.md index b309bbbbf5..d7107be210 100644 --- a/contracts/contracts/oracle/README.md +++ b/contracts/contracts/oracle/README.md @@ -14,16 +14,30 @@ ![OETH Oracle Router Storage](../../docs/OETHOracleRouterStorage.svg) -## Mix Oracle +## OETH Oracle ### Hierarchy -![Mix Oracle Hierarchy](../../docs/MixOracleHierarchy.svg) +![OETH Oracle Hierarchy](../../docs/OETHOracleHierarchy.svg) ### Squashed -![Mix Oracle Squashed](../../docs/MixOracleSquashed.svg) +![OETH Oracle Squashed](../../docs/OETHOracleSquashed.svg) ### Storage -![Mix Oracle Storage](../../docs/MixOracleStorage.svg) +![OETH Oracle Storage](../../docs/OETHOracleStorage.svg) + +## OETH Oracle Updater + +### Hierarchy + +![OETH Oracle Updater Hierarchy](../../docs/OETHOracleUpdaterHierarchy.svg) + +### Squashed + +![OETH Oracle Updater Squashed](../../docs/OETHOracleUpdaterSquashed.svg) + +### Storage + +![OETH Oracle Updater Storage](../../docs/OETHOracleUpdaterStorage.svg) diff --git a/contracts/contracts/strategies/ICurvePool.sol b/contracts/contracts/strategies/ICurvePool.sol index 9f2b5c9a28..ed5ac33f7e 100644 --- a/contracts/contracts/strategies/ICurvePool.sol +++ b/contracts/contracts/strategies/ICurvePool.sol @@ -36,4 +36,6 @@ interface ICurvePool { uint256[3] calldata _amounts, uint256 maxBurnAmount ) external; + + function price_oracle() external view returns (uint256); } diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index f0bac54c40..cc6a7b88fb 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -572,7 +572,8 @@ contract VaultCore is VaultInitializer { * @return price_ USD or ETH value of 1 OToken to 18 decimals */ function price() external view returns (uint256 price_) { - uint256 totalAssetsValue = 0; + // Sum of asset values scaled to 1e36 + uint256 totalAssetsValueScaled = 0; // For each asset uint256 assetCount = allAssets.length; for (uint256 i = 0; i < assetCount; ++i) { @@ -583,10 +584,12 @@ contract VaultCore is VaultInitializer { uint256 balance = _checkBalance(assetAddr); // total asset value = total asset value + (balance * price) - totalAssetsValue += (_toUnits(balance, assetAddr) * + // Both balance and price are scaled to 18 decimals so the result is 36 decmials + totalAssetsValueScaled += (_toUnits(balance, assetAddr) * _toUnitPrice(assetAddr, false)); } - price_ = totalAssetsValue / oUSD.totalSupply(); + // The total supply is 18 decimals so the price is scaled down to 18 decimals + price_ = totalAssetsValueScaled / oUSD.totalSupply(); // adjust for redeem fee uint256 redeemFeeBpsMem = redeemFeeBps; diff --git a/contracts/deploy/076_oeth_vault_upgrade.js b/contracts/deploy/076_oeth_vault_upgrade.js index d64e8ba47b..c1b0941100 100644 --- a/contracts/deploy/076_oeth_vault_upgrade.js +++ b/contracts/deploy/076_oeth_vault_upgrade.js @@ -1,4 +1,8 @@ -const { deploymentWithGovernanceProposal } = require("../utils/deploy"); +const addresses = require("../utils/addresses"); +const { + deploymentWithGovernanceProposal, + withConfirmation, +} = require("../utils/deploy"); module.exports = deploymentWithGovernanceProposal( { @@ -10,13 +14,46 @@ module.exports = deploymentWithGovernanceProposal( // proposalId: "", }, async ({ ethers, deployWithConfirmation }) => { - const dVaultCore = await deployWithConfirmation("OETHVaultCore"); + const { deployerAddr } = await getNamedAccounts(); + const sDeployer = await ethers.provider.getSigner(deployerAddr); - // 2. Connect to the OETH Vault as its governor via the proxy + // 1. Connect to the OETH Vault as its governor via the proxy const cVaultProxy = await ethers.getContract("OETHVaultProxy"); - // Governance Actions - // ---------------- + // 2. Deploy the new Vault implementation + const dVaultCore = await deployWithConfirmation("OETHVaultCore"); + + // 3. Deploy the new Oracle contracts + const dOETHOracleUpdater = await deployWithConfirmation( + "OETHOracleUpdater", + [cVaultProxy.address, addresses.mainnet.CurveOETHMetaPool] + ); + const cOETHOracleUpdater = await ethers.getContractAt( + "OETHOracleUpdater", + dOETHOracleUpdater.address + ); + const dOETHOracle = await deployWithConfirmation("OETHOracle", [ + dOETHOracleUpdater.address, + 86400, + ]); + const cOETHOracle = await ethers.getContractAt( + "OETHOracleUpdater", + dOETHOracle.address + ); + + // 4. Transfer governance + await withConfirmation( + cOETHOracleUpdater + .connect(sDeployer) + .transferGovernance(addresses.mainnet.Timelock) + ); + await withConfirmation( + cOETHOracle + .connect(sDeployer) + .transferGovernance(addresses.mainnet.Timelock) + ); + + // 4. Governance Actions return { name: "Upgrade the OETH Vault with price Oracle.", actions: [ diff --git a/contracts/docs/OETHOracleHierarchy.svg b/contracts/docs/OETHOracleHierarchy.svg new file mode 100644 index 0000000000..382a321912 --- /dev/null +++ b/contracts/docs/OETHOracleHierarchy.svg @@ -0,0 +1,75 @@ + + + + + + +UmlClassDiagram + + + +7 + +Governable +../contracts/governance/Governable.sol + + + +193 + +<<Interface>> +AggregatorV3Interface +../contracts/interfaces/chainlink/AggregatorV3Interface.sol + + + +93 + +<<Abstract>> +BaseOracle +../contracts/oracle/BaseOracle.sol + + + +93->7 + + + + + +93->193 + + + + + +95 + +<<Interface>> +IOracleReceiver +../contracts/oracle/IOracleReceiver.sol + + + +93->95 + + + + + +96 + +OETHOracle +../contracts/oracle/OETHOracle.sol + + + +96->93 + + + + + diff --git a/contracts/docs/OETHOracleSquashed.svg b/contracts/docs/OETHOracleSquashed.svg new file mode 100644 index 0000000000..8f0ab09987 --- /dev/null +++ b/contracts/docs/OETHOracleSquashed.svg @@ -0,0 +1,65 @@ + + + + + + +UmlClassDiagram + + + +96 + +OETHOracle +../contracts/oracle/OETHOracle.sol + +Private: +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   oracleUpdater: address <<BaseOracle>> +   lastCorrectRoundId: uint80 <<BaseOracle>> +   rounds: Round[] <<BaseOracle>> +   heartbeatThreshold: uint256 <<BaseOracle>> +   description: string <<OETHOracle>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _setHeartbeatThreshold(_heartbeatThreshold: uint256) <<BaseOracle>> +    _setOracleUpdater(_oracleUpdater: address) <<BaseOracle>> +    _getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> +External: +     description(): string <<AggregatorV3Interface>> +    decimals(): (_decimals: uint8) <<BaseOracle>> +    version(): (_version: uint256) <<BaseOracle>> +    getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> +    latestRoundData(): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> +    addRoundData(_isBadData: bool, _answer: uint128, _timestamp: uint40) <<BaseOracle>> +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    setHeartbeatThreshold(_heartbeatThreshold: uint256) <<onlyGovernor>> <<BaseOracle>> +    setOracleUpdater(_oracleUpdater: address) <<onlyGovernor>> <<BaseOracle>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> SetHeartbeatThreshold(heartbeatThreshold: uint256) <<BaseOracle>> +    <<event>> SetOracleUpdater(oracleUpdater: address) <<BaseOracle>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_oracleUpdater: address, _maximumOracleDelay: uint256) <<OETHOracle>> + + + diff --git a/contracts/docs/OETHOracleStorage.svg b/contracts/docs/OETHOracleStorage.svg new file mode 100644 index 0000000000..980c7df190 --- /dev/null +++ b/contracts/docs/OETHOracleStorage.svg @@ -0,0 +1,87 @@ + + + + + + +StorageDiagram + + + +3 + +OETHOracle <<Contract>> + +slot + +0 + +1 + +2 + +type: <inherited contract>.variable (bytes) + +unallocated (2) + +uint80: BaseOracle.lastCorrectRoundId (10) + +address: BaseOracle.oracleUpdater (20) + +Round[]: BaseOracle.rounds (32) + +uint256: BaseOracle.heartbeatThreshold (32) + + + +2 + +Round[]: rounds <<Array>> +0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6 + +offset + +0 + +type: variable (bytes) + +Round (32) + + + +3:7->2 + + + + + +1 + +Round <<Struct>> +0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6 + +offset + +0 + +type: variable (bytes) + +unallocated (10) + +bool: isBadData (1) + +uint40: timestamp (5) + +uint128: answer (16) + + + +2:6->1 + + + + + diff --git a/contracts/docs/OETHOracleUpdaterHierarchy.svg b/contracts/docs/OETHOracleUpdaterHierarchy.svg new file mode 100644 index 0000000000..4aebafe97f --- /dev/null +++ b/contracts/docs/OETHOracleUpdaterHierarchy.svg @@ -0,0 +1,161 @@ + + + + + + +UmlClassDiagram + + + +7 + +Governable +../contracts/governance/Governable.sol + + + +40 + +<<Interface>> +IVault +../contracts/interfaces/IVault.sol + + + +186 + +VaultStorage +../contracts/vault/VaultStorage.sol + + + +40->186 + + + + + +95 + +<<Interface>> +IOracleReceiver +../contracts/oracle/IOracleReceiver.sol + + + +97 + +OETHOracleUpdater +../contracts/oracle/OETHOracleUpdater.sol + + + +97->7 + + + + + +97->40 + + + + + +97->95 + + + + + +154 + +<<Interface>> +ICurvePool +../contracts/strategies/ICurvePool.sol + + + +97->154 + + + + + +166 + +OUSD +../contracts/token/OUSD.sol + + + +166->7 + + + + + +173 + +<<Abstract>> +Initializable +../contracts/utils/Initializable.sol + + + +166->173 + + + + + +176 + +<<Abstract>> +InitializableERC20Detailed +../contracts/utils/InitializableERC20Detailed.sol + + + +166->176 + + + + + +348 + +<<Interface>> +IERC20 +../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + + + +176->348 + + + + + +186->7 + + + + + +186->166 + + + + + +186->173 + + + + + diff --git a/contracts/docs/OETHOracleUpdaterSquashed.svg b/contracts/docs/OETHOracleUpdaterSquashed.svg new file mode 100644 index 0000000000..8601015859 --- /dev/null +++ b/contracts/docs/OETHOracleUpdaterSquashed.svg @@ -0,0 +1,52 @@ + + + + + + +UmlClassDiagram + + + +97 + +OETHOracleUpdater +../contracts/oracle/OETHOracleUpdater.sol + +Private: +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   curvePool: ICurvePool <<OETHOracleUpdater>> +   vault: IVault <<OETHOracleUpdater>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _getPrices(): (isBadData: bool, answer: uint256, vaultPrice: uint256, curvePrice: uint256) <<OETHOracleUpdater>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    addRoundData(oracle: IOracleReceiver) <<OETHOracleUpdater>> +    getPrices(): (isBadData: bool, answer: uint256, vaultPrice: uint256, curvePrice: uint256) <<OETHOracleUpdater>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<modifier>> onlyGovernor() <<Governable>> +    <<modifier>> nonReentrant() <<Governable>> +    constructor() <<Governable>> +    governor(): address <<Governable>> +    isGovernor(): bool <<Governable>> +    constructor(_vault: address, _curvePool: address) <<OETHOracleUpdater>> + + + diff --git a/contracts/docs/OETHOracleUpdaterStorage.svg b/contracts/docs/OETHOracleUpdaterStorage.svg new file mode 100644 index 0000000000..54b8454473 --- /dev/null +++ b/contracts/docs/OETHOracleUpdaterStorage.svg @@ -0,0 +1,23 @@ + + + + + + +StorageDiagram + + + +1 + +OETHOracleUpdater <<Contract>> + +slot + +type: <inherited contract>.variable (bytes) + + + diff --git a/contracts/docs/generate.sh b/contracts/docs/generate.sh index 562f050219..a5d06d1531 100644 --- a/contracts/docs/generate.sh +++ b/contracts/docs/generate.sh @@ -37,9 +37,13 @@ sol2uml .. -v -hv -hf -he -hs -hl -b OETHOracleRouter -o OETHOracleRouterHierarc sol2uml .. -s -d 0 -b OETHOracleRouter -o OETHOracleRouterSquashed.svg sol2uml storage .. -c OETHOracleRouter -o OETHOracleRouterStorage.svg -sol2uml .. -v -hv -hf -he -hs -hl -b MixOracle -o MixOracleHierarchy.svg -sol2uml .. -s -d 0 -b MixOracle -o MixOracleSquashed.svg -sol2uml storage .. -c MixOracle -o MixOracleStorage.svg +sol2uml .. -v -hv -hf -he -hs -hl -b OETHOracle -o OETHOracleHierarchy.svg +sol2uml .. -s -d 0 -b OETHOracle -o OETHOracleSquashed.svg +sol2uml storage .. -c OETHOracle -o OETHOracleStorage.svg + +sol2uml .. -v -hv -hf -he -hs -hl -b OETHOracleUpdater -o OETHOracleUpdaterHierarchy.svg +sol2uml .. -s -d 0 -b OETHOracleUpdater -o OETHOracleUpdaterSquashed.svg +sol2uml storage .. -c OETHOracleUpdater -o OETHOracleUpdaterStorage.svg # contracts/proxies sol2uml .. -v -hv -hf -he -hs -hl -b OUSDProxy -o OUSDProxyHierarchy.svg diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index ee67ba1363..12463e4fbc 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -145,6 +145,9 @@ const defaultFixture = deployments.createFixture(async () => { isFork ? "OETHOracleRouter" : "OracleRouter" ); + const oethOracle = await ethers.getContract("OETHOracle"); + const oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); + const buybackProxy = await ethers.getContract("BuybackProxy"); const buyback = await ethers.getContractAt("Buyback", buybackProxy.address); @@ -533,6 +536,8 @@ const defaultFixture = deployments.createFixture(async () => { compoundStrategy, oracleRouter, oethOracleRouter, + oethOracle, + oethOracleUpdater, // Assets usdt, dai, diff --git a/contracts/test/oracle/oracle.fork-test.js b/contracts/test/oracle/oracle.fork-test.js index 7d6791adbd..7727d3e378 100644 --- a/contracts/test/oracle/oracle.fork-test.js +++ b/contracts/test/oracle/oracle.fork-test.js @@ -1,21 +1,25 @@ const { expect } = require("chai"); -const { parseUnits } = require("ethers/lib/utils"); +const { parseUnits, formatUnits } = require("ethers/lib/utils"); const { loadDefaultFixture } = require("../_fixture"); const { forkOnlyDescribe, isCI } = require("../helpers"); -forkOnlyDescribe("ForkTest: Oracle Routers", function () { +const log = require("../../utils/logger")("test:fork:oracles"); + +forkOnlyDescribe("ForkTest: Oracles", function () { this.timeout(0); // Retry up to 3 times on CI this.retries(isCI ? 3 : 0); let fixture; + beforeEach(async () => { + fixture = await loadDefaultFixture(); + }); describe("OETH Oracle Router", () => { let oethOracleRouter; beforeEach(async () => { - fixture = await loadDefaultFixture(); oethOracleRouter = await ethers.getContract("OETHOracleRouter"); }); it("should get rETH price", async () => { @@ -55,4 +59,33 @@ forkOnlyDescribe("ForkTest: Oracle Routers", function () { } }); }); + describe("OETH Oracle", () => { + it("Should add new OETH Oracle price", async () => { + const { josh, oethOracle, oethOracleUpdater } = fixture; + + await oethOracleUpdater.addRoundData(oethOracle.address); + + const data = await oethOracle.latestRoundData(); + log(`OETH price: ${formatUnits(data.answer, 18)}`); + + expect(data.answer).to.be.gte(parseUnits("0.99")); + expect(data.answer).to.be.lte(parseUnits("1.01")); + expect(data.roundId).to.be.eq(0); + + // This uses a transaction to call a view function so the gas usage can be reported. + const tx = await oethOracle + .connect(josh) + .populateTransaction.latestRoundData(); + await josh.sendTransaction(tx); + }); + it("Should add OETH Oracle price twice", async () => { + const { oethOracle, oethOracleUpdater } = fixture; + + await oethOracleUpdater.addRoundData(oethOracle.address); + await oethOracleUpdater.addRoundData(oethOracle.address); + + const data = await oethOracle.latestRoundData(); + expect(data.roundId).to.be.eq(1); + }); + }); }); diff --git a/contracts/test/vault/oeth-vault.fork-test.js b/contracts/test/vault/oeth-vault.fork-test.js index 7bf4bc61c2..aa8b882800 100644 --- a/contracts/test/vault/oeth-vault.fork-test.js +++ b/contracts/test/vault/oeth-vault.fork-test.js @@ -100,7 +100,7 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { }); } it("Should return OETH Oracle price", async () => { - const { oethVault } = fixture; + const { oethVault, josh } = fixture; const price = await oethVault.price(); @@ -108,6 +108,10 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { expect(price).to.be.gte(parseUnits("0.99")); expect(price).to.be.lte(parseUnits("1")); + + // This uses a transaction to call a view function so the gas usage can be reported. + const tx = await oethVault.connect(josh).populateTransaction.price(); + await josh.sendTransaction(tx); }); }); describe("user operations", () => { From 08824ef830e9a90f5e576039f6ad6919fdab3c71 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 13 Sep 2023 21:30:44 +1000 Subject: [PATCH 05/23] Refactor OETH Oracle --- contracts/contracts/oracle/BaseOracle.sol | 68 +++----------- .../contracts/oracle/IOracleReceiver.sol | 6 +- contracts/contracts/oracle/OETHOracle.sol | 5 +- .../contracts/oracle/OETHOracleUpdater.sol | 36 +++---- contracts/deploy/076_oeth_vault_upgrade.js | 1 - contracts/docs/OETHOracleSquashed.svg | 88 +++++++++--------- contracts/docs/OETHOracleStorage.svg | 78 +++++++--------- contracts/docs/OETHOracleUpdaterSquashed.svg | 67 ++++++------- contracts/docs/plantuml/oethOracles.png | Bin 57223 -> 55946 bytes contracts/docs/plantuml/oethOracles.puml | 4 +- contracts/test/oracle/oracle.fork-test.js | 22 +++-- 11 files changed, 163 insertions(+), 212 deletions(-) diff --git a/contracts/contracts/oracle/BaseOracle.sol b/contracts/contracts/oracle/BaseOracle.sol index 7754d72707..3846e72d9a 100644 --- a/contracts/contracts/oracle/BaseOracle.sol +++ b/contracts/contracts/oracle/BaseOracle.sol @@ -24,42 +24,24 @@ abstract contract BaseOracle is /// @notice Historical Oracle prices Round[] public rounds; - /// @notice Time in seconds between updates before the price is considered stale - uint256 public heartbeatThreshold; - /// @notice Packed Round data struct - /// @notice answer Oracle price + /// @notice price Oracle price to 18 decimals /// @notice timestamp timestamp in seconds of price - /// @notice isBadData If data is bad / should be used struct Round { - uint128 answer; + uint128 price; uint40 timestamp; - bool isBadData; } - event SetHeartbeatThreshold(uint256 heartbeatThreshold); event SetOracleUpdater(address oracleUpdater); - - constructor( - address _oracleUpdater, - uint256 _maximumOracleDelay - ) Governable() { + constructor(address _oracleUpdater) Governable() { _setOracleUpdater(_oracleUpdater); - _setHeartbeatThreshold(_maximumOracleDelay); } /*************************************** Internal Setters ****************************************/ - /// @notice Sets the max oracle delay to determine if data is stale - /// @param _heartbeatThreshold The time in seconds before the price is considered stale - function _setHeartbeatThreshold(uint256 _heartbeatThreshold) internal { - emit SetHeartbeatThreshold(_heartbeatThreshold); - heartbeatThreshold = _heartbeatThreshold; - } - /// @notice Sets the contract or account that can add Oracle prices /// @param _oracleUpdater Address of the contract or account that can update the Oracle prices function _setOracleUpdater(address _oracleUpdater) internal { @@ -71,14 +53,6 @@ abstract contract BaseOracle is External Setters ****************************************/ - /// @notice Sets the max Oracle delay to determine if data is stale - /// @param _heartbeatThreshold The time in seconds before the price is considered stale - function setHeartbeatThreshold( - uint256 _heartbeatThreshold - ) external onlyGovernor { - _setHeartbeatThreshold(_heartbeatThreshold); - } - /// @notice Sets the contract or account that can update the Oracle prices /// @param _oracleUpdater Address of the contract or account that can update the Oracle prices function setOracleUpdater(address _oracleUpdater) external onlyGovernor { @@ -117,35 +91,24 @@ abstract contract BaseOracle is ****************************************/ /// @notice Adds a new Oracle price by the Oracle updater. - /// @param _isBadData Boolean representing if the data is bad - /// @param _answer is the Oracle price with 18 decimals - /// @param _timestamp The timestamp of the update - function addRoundData( - bool _isBadData, - uint128 _answer, - uint40 _timestamp - ) external override { + /// @param _price is the Oracle price with 18 decimals + function addPrice(uint128 _price) external override { if (msg.sender != oracleUpdater) revert OnlyOracleUpdater(); - if (_timestamp > block.timestamp) revert CalledWithFutureTimestamp(); + // TODO what is a sensible min? + if (_price == 0) revert NoPriceData(); uint256 _roundsLength = rounds.length; if ( _roundsLength > 0 && - _timestamp <= rounds[_roundsLength - 1].timestamp + block.timestamp <= rounds[_roundsLength - 1].timestamp ) { revert CalledWithTimestampBeforePreviousRound(); } - if (!_isBadData) { - lastCorrectRoundId = uint80(_roundsLength); - } + lastCorrectRoundId = uint80(_roundsLength); rounds.push( - Round({ - isBadData: _isBadData, - answer: _answer, - timestamp: _timestamp - }) + Round({ price: _price, timestamp: uint40(block.timestamp) }) ); } @@ -153,9 +116,7 @@ abstract contract BaseOracle is Prices ****************************************/ - function _getRoundData( - uint80 _roundId - ) + function _getRoundData(uint80 _roundId) internal view returns ( @@ -169,7 +130,7 @@ abstract contract BaseOracle is if (rounds.length <= _roundId) revert NoPriceData(); Round memory _round = rounds[_roundId]; - answer = int256(uint256(_round.answer)); + answer = int256(uint256(_round.price)); roundId = answeredInRound = _roundId; startedAt = updatedAt = _round.timestamp; @@ -182,9 +143,7 @@ abstract contract BaseOracle is /// @return startedAt Timestamp of when the round started /// @return updatedAt Timestamp of when the round was updated /// @return answeredInRound The round ID in which the answer was computed - function getRoundData( - uint80 _roundId - ) + function getRoundData(uint80 _roundId) external view override @@ -236,7 +195,6 @@ abstract contract BaseOracle is Errors ****************************************/ - error CalledWithFutureTimestamp(); error CalledWithTimestampBeforePreviousRound(); error NoPriceData(); error OnlyOracleUpdater(); diff --git a/contracts/contracts/oracle/IOracleReceiver.sol b/contracts/contracts/oracle/IOracleReceiver.sol index e1e8d48e3a..b943e9b987 100644 --- a/contracts/contracts/oracle/IOracleReceiver.sol +++ b/contracts/contracts/oracle/IOracleReceiver.sol @@ -2,9 +2,5 @@ pragma solidity ^0.8.0; interface IOracleReceiver { - function addRoundData( - bool isBadData, - uint128 answer, - uint40 timestamp - ) external; + function addPrice(uint128 price) external; } diff --git a/contracts/contracts/oracle/OETHOracle.sol b/contracts/contracts/oracle/OETHOracle.sol index d5cf773d0b..84cb3bb91a 100644 --- a/contracts/contracts/oracle/OETHOracle.sol +++ b/contracts/contracts/oracle/OETHOracle.sol @@ -14,8 +14,5 @@ import { Governable } from "../governance/Governable.sol"; contract OETHOracle is BaseOracle { string public constant override description = "OETH / ETH"; - constructor( - address _oracleUpdater, - uint256 _maximumOracleDelay - ) BaseOracle(_oracleUpdater, _maximumOracleDelay) {} + constructor(address _oracleUpdater) BaseOracle(_oracleUpdater) {} } diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol index 7929e3de57..c38d0d5311 100644 --- a/contracts/contracts/oracle/OETHOracleUpdater.sol +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -21,6 +21,8 @@ contract OETHOracleUpdater is Governable { address curvePool; } + event AddPrice(uint256 answer, uint256 vaultPrice, uint256 marketPrice); + constructor(address _vault, address _curvePool) Governable() { curvePool = ICurvePool(_curvePool); vault = IVault(_vault); @@ -29,57 +31,55 @@ contract OETHOracleUpdater is Governable { /// @notice Adds new Oracle price to an Oracle /// @dev Callable by anyone as the prices are sourced and aggregated on-chain. /// @param oracle Address of the Oracle that has this contract set as its priceSource - function addRoundData(IOracleReceiver oracle) external { - (bool isBadData, uint256 answer, , ) = _getPrices(); + function addPrice(IOracleReceiver oracle) external { + ( + uint256 answer, + uint256 vaultPrice, + uint256 marketPrice + ) = _getPrices(); + + emit AddPrice(answer, vaultPrice, marketPrice); // Authorization is handled on Oracle side - oracle.addRoundData({ - isBadData: isBadData, - answer: uint128(answer), - timestamp: uint40(block.timestamp) - }); + oracle.addPrice(uint128(answer)); } function _getPrices() internal view returns ( - bool isBadData, uint256 answer, uint256 vaultPrice, - uint256 curvePrice + uint256 marketPrice ) { // Get price from the Vault vaultPrice = vault.price(); // Get price from the Curve pool - curvePrice = curvePool.price_oracle(); + marketPrice = curvePool.price_oracle(); // TODO check if the data is bad - isBadData = false; - // Return the Curve price with the Vault price as the floor price - if (curvePrice > vaultPrice) { - answer = curvePrice; + // Return the market price with the Vault price as the floor price + if (marketPrice > vaultPrice) { + answer = marketPrice; } else { answer = vaultPrice; } } /// @notice Get the latest price from the Vault and Curve pool - /// @return isBadData is true when data is stale or otherwise bad /// @return answer is the latest Oracle price function getPrices() external view returns ( - bool isBadData, uint256 answer, uint256 vaultPrice, - uint256 curvePrice + uint256 marketPrice ) { - (isBadData, answer, vaultPrice, curvePrice) = _getPrices(); + (answer, vaultPrice, marketPrice) = _getPrices(); } } diff --git a/contracts/deploy/076_oeth_vault_upgrade.js b/contracts/deploy/076_oeth_vault_upgrade.js index c1b0941100..908e8ffc30 100644 --- a/contracts/deploy/076_oeth_vault_upgrade.js +++ b/contracts/deploy/076_oeth_vault_upgrade.js @@ -34,7 +34,6 @@ module.exports = deploymentWithGovernanceProposal( ); const dOETHOracle = await deployWithConfirmation("OETHOracle", [ dOETHOracleUpdater.address, - 86400, ]); const cOETHOracle = await ethers.getContractAt( "OETHOracleUpdater", diff --git a/contracts/docs/OETHOracleSquashed.svg b/contracts/docs/OETHOracleSquashed.svg index 8f0ab09987..cd4334e008 100644 --- a/contracts/docs/OETHOracleSquashed.svg +++ b/contracts/docs/OETHOracleSquashed.svg @@ -4,62 +4,58 @@ - - + + UmlClassDiagram - + 96 - -OETHOracle -../contracts/oracle/OETHOracle.sol - -Private: -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   oracleUpdater: address <<BaseOracle>> -   lastCorrectRoundId: uint80 <<BaseOracle>> -   rounds: Round[] <<BaseOracle>> -   heartbeatThreshold: uint256 <<BaseOracle>> -   description: string <<OETHOracle>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _setHeartbeatThreshold(_heartbeatThreshold: uint256) <<BaseOracle>> -    _setOracleUpdater(_oracleUpdater: address) <<BaseOracle>> -    _getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> -External: -     description(): string <<AggregatorV3Interface>> -    decimals(): (_decimals: uint8) <<BaseOracle>> -    version(): (_version: uint256) <<BaseOracle>> -    getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> -    latestRoundData(): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> -    addRoundData(_isBadData: bool, _answer: uint128, _timestamp: uint40) <<BaseOracle>> -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    setHeartbeatThreshold(_heartbeatThreshold: uint256) <<onlyGovernor>> <<BaseOracle>> -    setOracleUpdater(_oracleUpdater: address) <<onlyGovernor>> <<BaseOracle>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> SetHeartbeatThreshold(heartbeatThreshold: uint256) <<BaseOracle>> + +OETHOracle +../contracts/oracle/OETHOracle.sol + +Private: +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   oracleUpdater: address <<BaseOracle>> +   lastCorrectRoundId: uint80 <<BaseOracle>> +   rounds: Round[] <<BaseOracle>> +   description: string <<OETHOracle>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _setOracleUpdater(_oracleUpdater: address) <<BaseOracle>> +    _getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> +External: +     description(): string <<AggregatorV3Interface>> +    decimals(): (_decimals: uint8) <<BaseOracle>> +    version(): (_version: uint256) <<BaseOracle>> +    getRoundData(_roundId: uint80): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> +    latestRoundData(): (roundId: uint80, answer: int256, startedAt: uint256, updatedAt: uint256, answeredInRound: uint80) <<BaseOracle>> +    addPrice(_price: uint128) <<BaseOracle>> +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    setOracleUpdater(_oracleUpdater: address) <<onlyGovernor>> <<BaseOracle>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>>    <<event>> SetOracleUpdater(oracleUpdater: address) <<BaseOracle>>    <<modifier>> onlyGovernor() <<Governable>>    <<modifier>> nonReentrant() <<Governable>>    constructor() <<Governable>>    governor(): address <<Governable>>    isGovernor(): bool <<Governable>> -    constructor(_oracleUpdater: address, _maximumOracleDelay: uint256) <<OETHOracle>> +    constructor(_oracleUpdater: address) <<OETHOracle>> diff --git a/contracts/docs/OETHOracleStorage.svg b/contracts/docs/OETHOracleStorage.svg index 980c7df190..8ff620e07d 100644 --- a/contracts/docs/OETHOracleStorage.svg +++ b/contracts/docs/OETHOracleStorage.svg @@ -4,36 +4,32 @@ - - + + StorageDiagram - + 3 - -OETHOracle <<Contract>> - -slot - -0 - -1 - -2 - -type: <inherited contract>.variable (bytes) - -unallocated (2) - -uint80: BaseOracle.lastCorrectRoundId (10) - -address: BaseOracle.oracleUpdater (20) - -Round[]: BaseOracle.rounds (32) - -uint256: BaseOracle.heartbeatThreshold (32) + +OETHOracle <<Contract>> + +slot + +0 + +1 + +type: <inherited contract>.variable (bytes) + +unallocated (2) + +uint80: BaseOracle.lastCorrectRoundId (10) + +address: BaseOracle.oracleUpdater (20) + +Round[]: BaseOracle.rounds (32) @@ -52,36 +48,34 @@ -3:7->2 +3:6->2 1 - -Round <<Struct>> -0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6 - + +Round <<Struct>> +0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6 + offset 0 -type: variable (bytes) - -unallocated (10) +type: variable (bytes) + +unallocated (11) -bool: isBadData (1) - -uint40: timestamp (5) - -uint128: answer (16) +uint40: timestamp (5) + +uint128: price (16) -2:6->1 - - +2:5->1 + + diff --git a/contracts/docs/OETHOracleUpdaterSquashed.svg b/contracts/docs/OETHOracleUpdaterSquashed.svg index 8601015859..9c6377af72 100644 --- a/contracts/docs/OETHOracleUpdaterSquashed.svg +++ b/contracts/docs/OETHOracleUpdaterSquashed.svg @@ -4,43 +4,44 @@ - - + + UmlClassDiagram - + 97 - -OETHOracleUpdater -../contracts/oracle/OETHOracleUpdater.sol - -Private: -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   curvePool: ICurvePool <<OETHOracleUpdater>> -   vault: IVault <<OETHOracleUpdater>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _getPrices(): (isBadData: bool, answer: uint256, vaultPrice: uint256, curvePrice: uint256) <<OETHOracleUpdater>> -External: -    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> -    claimGovernance() <<Governable>> -    addRoundData(oracle: IOracleReceiver) <<OETHOracleUpdater>> -    getPrices(): (isBadData: bool, answer: uint256, vaultPrice: uint256, curvePrice: uint256) <<OETHOracleUpdater>> -Public: -    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> -    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> + +OETHOracleUpdater +../contracts/oracle/OETHOracleUpdater.sol + +Private: +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   curvePool: ICurvePool <<OETHOracleUpdater>> +   vault: IVault <<OETHOracleUpdater>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _getPrices(): (answer: uint256, vaultPrice: uint256, marketPrice: uint256) <<OETHOracleUpdater>> +External: +    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>> +    claimGovernance() <<Governable>> +    addPrice(oracle: IOracleReceiver) <<OETHOracleUpdater>> +    getPrices(): (answer: uint256, vaultPrice: uint256, marketPrice: uint256) <<OETHOracleUpdater>> +Public: +    <<event>> PendingGovernorshipTransfer(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> GovernorshipTransferred(previousGovernor: address, newGovernor: address) <<Governable>> +    <<event>> AddPrice(answer: uint256, vaultPrice: uint256, marketPrice: uint256) <<OETHOracleUpdater>>    <<modifier>> onlyGovernor() <<Governable>>    <<modifier>> nonReentrant() <<Governable>>    constructor() <<Governable>> diff --git a/contracts/docs/plantuml/oethOracles.png b/contracts/docs/plantuml/oethOracles.png index 2c173ccd1c3ed74dbeb7a4b7e189271a9b9987af..49cee19ecc5e1b880f63c825495f546f2dda7952 100644 GIT binary patch literal 55946 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 bCNHi#pjoKtYZP~x_+D8-_2^?clPmuRK7)D4 literal 57223 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 diff --git a/contracts/docs/plantuml/oethOracles.puml b/contracts/docs/plantuml/oethOracles.puml index 7ea90362d2..53f0dd3ebf 100644 --- a/contracts/docs/plantuml/oethOracles.puml +++ b/contracts/docs/plantuml/oethOracles.puml @@ -70,13 +70,13 @@ router ..> clrETH : latestRoundData() router ..> clstETH : latestRoundData() vault <.. oou : price() -oetho <.. oou : addRoundData() +oetho <.. oou : addPrice() oou ...> coep : price_oracle() oou ...> cfop : price_oracle() oou ...> boep : price_oracle() router ..> frxo : latestRoundData() -fou ..> frxo : addRoundData() +fou ..> frxo : addPrice() fou ...> cfep : price_oracle() fou ...> cfwp : price_oracle() diff --git a/contracts/test/oracle/oracle.fork-test.js b/contracts/test/oracle/oracle.fork-test.js index 7727d3e378..f9adecc923 100644 --- a/contracts/test/oracle/oracle.fork-test.js +++ b/contracts/test/oracle/oracle.fork-test.js @@ -61,9 +61,11 @@ forkOnlyDescribe("ForkTest: Oracles", function () { }); describe("OETH Oracle", () => { it("Should add new OETH Oracle price", async () => { - const { josh, oethOracle, oethOracleUpdater } = fixture; + const { oethOracle, oethOracleUpdater } = fixture; + + const tx = await oethOracleUpdater.addPrice(oethOracle.address); - await oethOracleUpdater.addRoundData(oethOracle.address); + await expect(tx).to.emit(oethOracleUpdater, "AddPrice"); const data = await oethOracle.latestRoundData(); log(`OETH price: ${formatUnits(data.answer, 18)}`); @@ -71,20 +73,28 @@ forkOnlyDescribe("ForkTest: Oracles", function () { expect(data.answer).to.be.gte(parseUnits("0.99")); expect(data.answer).to.be.lte(parseUnits("1.01")); expect(data.roundId).to.be.eq(0); + }); + it("Should get gas usage of latestRoundData", async () => { + const { josh, oethOracle, oethOracleUpdater } = fixture; + + await oethOracleUpdater.addPrice(oethOracle.address); // This uses a transaction to call a view function so the gas usage can be reported. - const tx = await oethOracle + const tx2 = await oethOracle .connect(josh) .populateTransaction.latestRoundData(); - await josh.sendTransaction(tx); + await josh.sendTransaction(tx2); }); it("Should add OETH Oracle price twice", async () => { const { oethOracle, oethOracleUpdater } = fixture; - await oethOracleUpdater.addRoundData(oethOracle.address); - await oethOracleUpdater.addRoundData(oethOracle.address); + await oethOracleUpdater.addPrice(oethOracle.address); + await oethOracleUpdater.addPrice(oethOracle.address); const data = await oethOracle.latestRoundData(); + log(`Oracle price: ${formatUnits(data.answer, 18)}`); + log(`Oracle round: ${data.roundId}`); + log(`Oracle answeredInRound: ${data.answeredInRound}`); expect(data.roundId).to.be.eq(1); }); }); From 3be9b7a006be41d6f89219295b230e8945a0e4f9 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 13 Sep 2023 22:10:33 +1000 Subject: [PATCH 06/23] Fixed warnings of price override --- contracts/contracts/vault/VaultCore.sol | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index cc6a7b88fb..0e7b69dff8 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -603,12 +603,12 @@ contract VaultCore is VaultInitializer { * @notice Returns the total price in 18 digit units for a given asset. * Never goes above 1, since that is how we price mints. * @param asset address of the asset - * @return price uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed + * @return price_ uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed */ function priceUnitMint(address asset) external view - returns (uint256 price) + returns (uint256 price_) { /* need to supply 1 asset unit in asset's decimals and can not just hard-code * to 1e18 and ignore calling `_toUnits` since we need to consider assets @@ -618,19 +618,19 @@ contract VaultCore is VaultInitializer { uint256(1e18).scaleBy(_getDecimals(asset), 18), asset ); - price = (_toUnitPrice(asset, true) * units) / 1e18; + price_ = (_toUnitPrice(asset, true) * units) / 1e18; } /** * @notice Returns the total price in 18 digit unit for a given asset. * Never goes below 1, since that is how we price redeems * @param asset Address of the asset - * @return price uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed + * @return price_ uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed */ function priceUnitRedeem(address asset) external view - returns (uint256 price) + returns (uint256 price_) { /* need to supply 1 asset unit in asset's decimals and can not just hard-code * to 1e18 and ignore calling `_toUnits` since we need to consider assets @@ -640,7 +640,7 @@ contract VaultCore is VaultInitializer { uint256(1e18).scaleBy(_getDecimals(asset), 18), asset ); - price = (_toUnitPrice(asset, false) * units) / 1e18; + price_ = (_toUnitPrice(asset, false) * units) / 1e18; } /*************************************** @@ -696,15 +696,15 @@ contract VaultCore is VaultInitializer { function _toUnitPrice(address _asset, bool isMint) internal view - returns (uint256 price) + returns (uint256 price_) { UnitConversion conversion = assets[_asset].unitConversion; - price = IOracle(priceProvider).price(_asset); + price_ = IOracle(priceProvider).price(_asset); if (conversion == UnitConversion.GETEXCHANGERATE) { uint256 exchangeRate = IGetExchangeRateToken(_asset) .getExchangeRate(); - price = (price * 1e18) / exchangeRate; + price_ = (price_ * 1e18) / exchangeRate; } else if (conversion != UnitConversion.DECIMALS) { revert("Unsupported conversion type"); } @@ -713,23 +713,23 @@ contract VaultCore is VaultInitializer { * so the price checks are agnostic to underlying asset being * pegged to a USD or to an ETH or having a custom exchange rate. */ - require(price <= MAX_UNIT_PRICE_DRIFT, "Vault: Price exceeds max"); - require(price >= MIN_UNIT_PRICE_DRIFT, "Vault: Price under min"); + require(price_ <= MAX_UNIT_PRICE_DRIFT, "Vault: Price exceeds max"); + require(price_ >= MIN_UNIT_PRICE_DRIFT, "Vault: Price under min"); if (isMint) { /* Never price a normalized unit price for more than one * unit of OETH/OUSD when minting. */ - if (price > 1e18) { - price = 1e18; + if (price_ > 1e18) { + price_ = 1e18; } - require(price >= MINT_MINIMUM_UNIT_PRICE, "Asset price below peg"); + require(price_ >= MINT_MINIMUM_UNIT_PRICE, "Asset price below peg"); } else { /* Never give out more than 1 normalized unit amount of assets * for one unit of OETH/OUSD when redeeming. */ - if (price < 1e18) { - price = 1e18; + if (price_ < 1e18) { + price_ = 1e18; } } } From 0d55c81a8a7cce645f79631460242b02d78606d3 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 13 Sep 2023 22:28:43 +1000 Subject: [PATCH 07/23] Fix unit tests --- contracts/test/_fixture.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 12463e4fbc..5bb8fa62d4 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -145,9 +145,6 @@ const defaultFixture = deployments.createFixture(async () => { isFork ? "OETHOracleRouter" : "OracleRouter" ); - const oethOracle = await ethers.getContract("OETHOracle"); - const oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); - const buybackProxy = await ethers.getContract("BuybackProxy"); const buyback = await ethers.getContractAt("Buyback", buybackProxy.address); @@ -218,7 +215,9 @@ const defaultFixture = deployments.createFixture(async () => { swapper1Inch, mock1InchSwapRouter, convexEthMetaStrategy, - fluxStrategy; + fluxStrategy, + oethOracleUpdater, + oethOracle; if (isFork) { usdt = await ethers.getContractAt(usdtAbi, addresses.mainnet.USDT); @@ -351,6 +350,9 @@ const defaultFixture = deployments.createFixture(async () => { "CompoundStrategy", fluxStrategyProxy.address ); + + oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); + oethOracle = await ethers.getContract("OETHOracle"); } else { usdt = await ethers.getContract("MockUSDT"); dai = await ethers.getContract("MockDAI"); From 90e8e8ca6e0ad858659aa6a6525ca9f75dbdb235 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 13 Sep 2023 22:51:45 +1000 Subject: [PATCH 08/23] Fix fork tests --- contracts/test/vault/oeth-vault.fork-test.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/contracts/test/vault/oeth-vault.fork-test.js b/contracts/test/vault/oeth-vault.fork-test.js index aa8b882800..d23ea69060 100644 --- a/contracts/test/vault/oeth-vault.fork-test.js +++ b/contracts/test/vault/oeth-vault.fork-test.js @@ -77,15 +77,22 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { }; for (const [symbol, { min, max }] of Object.entries(assetPriceRanges)) { it(`Should return a price for minting with ${symbol}`, async () => { - const { oethVault } = fixture; + const { oethVault, oethOracleRouter } = fixture; const asset = await resolveAsset(symbol); - const price = await oethVault.priceUnitMint(asset.address); - log(`Price for minting with ${symbol}: ${formatUnits(price, 18)}`); + const oraclePrice = await oethOracleRouter.price(asset.address); + if (oraclePrice.gt(parseUnits("0.998"))) { + const price = await oethVault.priceUnitMint(asset.address); - expect(price).to.be.gte(min); - expect(price).to.be.lte(max); + log(`Price for minting with ${symbol}: ${formatUnits(price, 18)}`); + + expect(price).to.be.gte(min); + expect(price).to.be.lte(max); + } else { + const tx = oethVault.priceUnitMint(asset.address); + await expect(tx).to.revertedWith("Asset price below peg"); + } }); it(`Should return a price for redeeming with ${symbol}`, async () => { const { oethVault } = fixture; From db6fa51267da6eaa854122f8567dd3710ff39a93 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Thu, 14 Sep 2023 16:37:55 +1000 Subject: [PATCH 09/23] Implements two floorPrice functions to compare --- contracts/contracts/interfaces/IVault.sol | 4 +- .../contracts/oracle/OETHOracleUpdater.sol | 2 +- contracts/contracts/vault/VaultCore.sol | 40 ++++++++++++++----- contracts/test/vault/oeth-vault.fork-test.js | 12 ++++-- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/contracts/contracts/interfaces/IVault.sol b/contracts/contracts/interfaces/IVault.sol index e2f2334173..4a8166e40c 100644 --- a/contracts/contracts/interfaces/IVault.sol +++ b/contracts/contracts/interfaces/IVault.sol @@ -120,7 +120,9 @@ interface IVault { function priceUnitRedeem(address asset) external view returns (uint256); - function price() external view returns (uint256); + function floorPrice() external view returns (uint256); + + function floorPrice2() external view returns (uint256); function withdrawAllFromStrategy(address _strategyAddr) external; diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol index c38d0d5311..a4b85b7ba4 100644 --- a/contracts/contracts/oracle/OETHOracleUpdater.sol +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -54,7 +54,7 @@ contract OETHOracleUpdater is Governable { ) { // Get price from the Vault - vaultPrice = vault.price(); + vaultPrice = vault.floorPrice(); // Get price from the Curve pool marketPrice = curvePool.price_oracle(); diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index 0e7b69dff8..926be92d8e 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -11,13 +11,12 @@ pragma solidity ^0.8.0; * @author Origin Protocol Inc */ -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC20, SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { StableMath } from "../utils/StableMath.sol"; import { IOracle } from "../interfaces/IOracle.sol"; import { IGetExchangeRateToken } from "../interfaces/IGetExchangeRateToken.sol"; - -import "./VaultInitializer.sol"; +import { IStrategy, VaultInitializer } from "./VaultInitializer.sol"; contract VaultCore is VaultInitializer { using SafeERC20 for IERC20; @@ -565,13 +564,34 @@ contract VaultCore is VaultInitializer { Pricing ****************************************/ + /** + * @notice The amount of ETH value for redeeming 1 OETH. + * This is the minimum price for OETH. The better price is + * is usually achieved by swapping OETH for ETH + * with the Curve OETH/ETH pool. + */ + function floorPrice() external view returns (uint256 price) { + // Get the assets for redeeming 1 OETH + // This has already had the redeem fee applied + uint256[] memory redeemAssets = _calculateRedeemOutputs(1e18); + + // For each of the redeemed assets + for (uint256 i = 0; i < redeemAssets.length; ++i) { + // Sum the value of the asset in ETH = asset amount * oracle price + price += + redeemAssets[i] * + IOracle(priceProvider).price(allAssets[i]); + } + price = price / 1e18; + } + /** * @notice Value of 1 OToken if redeemed using the Vault. * This includes any redeem fee. * For example, USD value of 1 OUSD or ETH value of 1 OETH. * @return price_ USD or ETH value of 1 OToken to 18 decimals */ - function price() external view returns (uint256 price_) { + function floorPrice2() external view returns (uint256 price_) { // Sum of asset values scaled to 1e36 uint256 totalAssetsValueScaled = 0; // For each asset @@ -603,12 +623,12 @@ contract VaultCore is VaultInitializer { * @notice Returns the total price in 18 digit units for a given asset. * Never goes above 1, since that is how we price mints. * @param asset address of the asset - * @return price_ uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed + * @return price uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed */ function priceUnitMint(address asset) external view - returns (uint256 price_) + returns (uint256 price) { /* need to supply 1 asset unit in asset's decimals and can not just hard-code * to 1e18 and ignore calling `_toUnits` since we need to consider assets @@ -618,19 +638,19 @@ contract VaultCore is VaultInitializer { uint256(1e18).scaleBy(_getDecimals(asset), 18), asset ); - price_ = (_toUnitPrice(asset, true) * units) / 1e18; + price = (_toUnitPrice(asset, true) * units) / 1e18; } /** * @notice Returns the total price in 18 digit unit for a given asset. * Never goes below 1, since that is how we price redeems * @param asset Address of the asset - * @return price_ uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed + * @return price uint256: unit (USD / ETH) price for 1 unit of the asset, in 18 decimal fixed */ function priceUnitRedeem(address asset) external view - returns (uint256 price_) + returns (uint256 price) { /* need to supply 1 asset unit in asset's decimals and can not just hard-code * to 1e18 and ignore calling `_toUnits` since we need to consider assets @@ -640,7 +660,7 @@ contract VaultCore is VaultInitializer { uint256(1e18).scaleBy(_getDecimals(asset), 18), asset ); - price_ = (_toUnitPrice(asset, false) * units) / 1e18; + price = (_toUnitPrice(asset, false) * units) / 1e18; } /*************************************** diff --git a/contracts/test/vault/oeth-vault.fork-test.js b/contracts/test/vault/oeth-vault.fork-test.js index d23ea69060..6cc2b2c507 100644 --- a/contracts/test/vault/oeth-vault.fork-test.js +++ b/contracts/test/vault/oeth-vault.fork-test.js @@ -106,18 +106,22 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { expect(price).to.be.lte(max); }); } - it("Should return OETH Oracle price", async () => { + it("Should return OETH floor price", async () => { const { oethVault, josh } = fixture; - const price = await oethVault.price(); - + const price = await oethVault.floorPrice(); log(`OETH price: ${formatUnits(price, 18)}`); + const price2 = await oethVault.floorPrice2(); + log(`OETH price2: ${formatUnits(price2, 18)}`); + expect(price).to.be.gte(parseUnits("0.99")); expect(price).to.be.lte(parseUnits("1")); // This uses a transaction to call a view function so the gas usage can be reported. - const tx = await oethVault.connect(josh).populateTransaction.price(); + const tx = await oethVault + .connect(josh) + .populateTransaction.floorPrice(); await josh.sendTransaction(tx); }); }); From dbd952574ed13b5cd8c8350ec3449f799020f0a8 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Thu, 14 Sep 2023 16:58:53 +1000 Subject: [PATCH 10/23] Remove test floorPrice2 --- contracts/contracts/vault/VaultCore.sol | 34 -------------------- contracts/test/vault/oeth-vault.fork-test.js | 3 -- 2 files changed, 37 deletions(-) diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index 926be92d8e..db3fd1527d 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -585,40 +585,6 @@ contract VaultCore is VaultInitializer { price = price / 1e18; } - /** - * @notice Value of 1 OToken if redeemed using the Vault. - * This includes any redeem fee. - * For example, USD value of 1 OUSD or ETH value of 1 OETH. - * @return price_ USD or ETH value of 1 OToken to 18 decimals - */ - function floorPrice2() external view returns (uint256 price_) { - // Sum of asset values scaled to 1e36 - uint256 totalAssetsValueScaled = 0; - // For each asset - uint256 assetCount = allAssets.length; - for (uint256 i = 0; i < assetCount; ++i) { - // read the asset address into memory - address assetAddr = allAssets[i]; - - // Get the total amount of assets in the vault - uint256 balance = _checkBalance(assetAddr); - - // total asset value = total asset value + (balance * price) - // Both balance and price are scaled to 18 decimals so the result is 36 decmials - totalAssetsValueScaled += (_toUnits(balance, assetAddr) * - _toUnitPrice(assetAddr, false)); - } - // The total supply is 18 decimals so the price is scaled down to 18 decimals - price_ = totalAssetsValueScaled / oUSD.totalSupply(); - - // adjust for redeem fee - uint256 redeemFeeBpsMem = redeemFeeBps; - // Calculate redeem fee - if (redeemFeeBpsMem > 0) { - price_ = price_ - price_.mulTruncateScale(redeemFeeBpsMem, 1e4); - } - } - /** * @notice Returns the total price in 18 digit units for a given asset. * Never goes above 1, since that is how we price mints. diff --git a/contracts/test/vault/oeth-vault.fork-test.js b/contracts/test/vault/oeth-vault.fork-test.js index 6cc2b2c507..0354b49bb2 100644 --- a/contracts/test/vault/oeth-vault.fork-test.js +++ b/contracts/test/vault/oeth-vault.fork-test.js @@ -112,9 +112,6 @@ forkOnlyDescribe("ForkTest: OETH Vault", function () { const price = await oethVault.floorPrice(); log(`OETH price: ${formatUnits(price, 18)}`); - const price2 = await oethVault.floorPrice2(); - log(`OETH price2: ${formatUnits(price2, 18)}`); - expect(price).to.be.gte(parseUnits("0.99")); expect(price).to.be.lte(parseUnits("1")); From 714e3934a8d20a0f6b68d6eaa76d732f6924acfc Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Thu, 14 Sep 2023 23:22:54 +1000 Subject: [PATCH 11/23] Added price cap on OETH Oracle --- contracts/contracts/oracle/BaseOracle.sol | 7 ++- .../contracts/oracle/OETHOracleUpdater.sol | 5 ++ contracts/docs/plantuml/oethOracles.png | Bin 55946 -> 34665 bytes contracts/docs/plantuml/oethOracles.puml | 59 ++++++++++-------- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/contracts/contracts/oracle/BaseOracle.sol b/contracts/contracts/oracle/BaseOracle.sol index 3846e72d9a..849535c73b 100644 --- a/contracts/contracts/oracle/BaseOracle.sol +++ b/contracts/contracts/oracle/BaseOracle.sol @@ -91,18 +91,19 @@ abstract contract BaseOracle is ****************************************/ /// @notice Adds a new Oracle price by the Oracle updater. + /// Can not be run twice in the same block. /// @param _price is the Oracle price with 18 decimals function addPrice(uint128 _price) external override { if (msg.sender != oracleUpdater) revert OnlyOracleUpdater(); - // TODO what is a sensible min? if (_price == 0) revert NoPriceData(); + // Can not add price in the same or previous blocks uint256 _roundsLength = rounds.length; if ( _roundsLength > 0 && block.timestamp <= rounds[_roundsLength - 1].timestamp ) { - revert CalledWithTimestampBeforePreviousRound(); + revert AddPriceSameBlock(); } lastCorrectRoundId = uint80(_roundsLength); @@ -195,7 +196,7 @@ abstract contract BaseOracle is Errors ****************************************/ - error CalledWithTimestampBeforePreviousRound(); + error AddPriceSameBlock(); error NoPriceData(); error OnlyOracleUpdater(); } diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol index a4b85b7ba4..e4069e422c 100644 --- a/contracts/contracts/oracle/OETHOracleUpdater.sol +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -67,6 +67,11 @@ contract OETHOracleUpdater is Governable { } else { answer = vaultPrice; } + + // Cap the OETH/ETH price at 1 + if (answer > 1e18) { + answer = 1e18; + } } /// @notice Get the latest price from the Vault and Curve pool diff --git a/contracts/docs/plantuml/oethOracles.png b/contracts/docs/plantuml/oethOracles.png index 49cee19ecc5e1b880f63c825495f546f2dda7952..da78b2fc88fdb74e28d1032f2f05ed011950863c 100644 GIT binary patch literal 34665 zcmbrlWmuG9*EWg;3JB67-3=n$NOy;{ASECD39gkq%=@a?)rd#To3PpD+KQ~ z8^M1}5b0NtHx7=Tb{3Wp6j=*<3ujY^g*l~}C#5w6;wZ?$;b>=S4{?2G$Nt9Q9nNzB zQWTVX9&fc?LH^HmlsjMJBr{pZG<0`SZJC2aMm%9pjZIU}l48Yu~rY+RBET zUhByA-gNHEzQ1Y+S zdYN&=*=2-28?Qn8+YN118uYKcyFi%R~%*>Xb+-- za9x%&(oAD-P;lC|+uCTdGu(_+5yeEk#1F{Bj-M0m;JuObr+6b3wEBfiNhdg&9sQl| zQtc}6$u-Ry=u8I`*0ZivPq4?wsSka(m}c$1?_`4!srA6Q4PnW=`QbCl|R42w`!FT--RUkG^=*W{MTN14BHV}6-t z+L26AWXeCHA<@=_)BV>t-18t}Q$`fOX znba!+X^Znr)ycLyQ=awS@2(!Q;TbbAQ?_|KPcw;O^T2cAbxom?%=@8EuQ6=PVhxTY zs=L-7*~28dXwxL$eCFI>k0FzqK1zRVZSc0mI&bBZGG#_Jl(vNG;+eh4H(giQC%G#j zs)IPgg_7RS5VU$q*OunTjBe1Yh%YL^8~0k3wDHgF%XelLT`u`?<(KHIanaKgaOjpE zJ>XP6>7J_PaOc5vJ4KlMJ=ipQG-STLI+sx`Q2aEjnBCS@74eQzP?W?kNXd+$gFOXT zH-z%L)KG}|d$eS{HR)z<9f#2`cGQ(NZ{=Z=e?7vbNMZ!izkGKr&#+z#wMuUnJ6%|E z*}b}Ryhx$Ov1s7+*xaAv$|8$g-Fdt@h;Hq}b94&ZL75u83k~Ap1G^9|>kNtIaeJRy zRg#e%LCKL#?UI9cju;<;=DL63Pzj`b)WFdyBdL{gB+@8)R`A$MhxnxU7vv2M1o7EX zhA3HKbFGc&{jXGchS%@_F@M1(N?g);BZ0ZoQml;BBS=xdu!I$FM6fP{NtuC^6;&#e zY_fh5bM|Mk*%5NR8-JT4Cpxhr{7MwB32OQ{~#lTGKUFsyLHZh=NQk zQvN68(t4!L_oAZhuY%F{u`$gRtFBKtbv6^YsL6t^ z#jwd#9^3J4)>oAQX5_v{qtq1goUtKNeXQg9?mKgOFv#2PFoL@4!ND{>B8KS-Ue0cpy9Af_0m+jYoOY(+9oXdniM?_$9+1Fb)VFIy~epTdXm7>#H?MrB| zpZ7Xk8w@An5Iy<%2454bv*>rBT!Wt`;(cOuv)_p=7K5=0k&?PU==*a{2?wpHc$@=)0qK4*Kp?`B%APG(hw_oX7A@f3PI#=zJdD^Q(>xt8dZ zJ$v$G@9K21pYG=RVi(9>_;Rl^fmz#TrWWz>5gr7pn9zb4D`;+P)T%I^pPD-T7KGu| zEq;nuOQ`L3e0|a2u;_PvzE0t_K{XQ_5`spo?`y{r%}Y-oTzvib8TZC?&3XuhAEN_D zu~w19Y^h1RD4RGT$69;7d*B1ho?`8iyhD|AK?_=*mG|4gYQ_uI>ujgoTwG@BY?Joy zb005>c>j;xQeZ86&fBIjHUHEpG$^d5sUo*Y8y`F39pXWIb^)Z$<0-#1a|%^ z5nJ?3Jkbjci*zJn7Y@accKb6fU(=Eg8`W)61G)ZXUGrKfgH7p*3&tc(mq19U-EipNn zu_5=|Sszc2jA32md?oH+`b<+*1nOB!`xIUupVQF5*Bz%v!eb*PhDh#-Byr!IEHk^d z_2PS#1sP5kVrZywT9%K*l&h~9G zEUv%R`!qjuzS+INn_mC4tYJaoJ#gOFdWE$K7Ku7(lzMc~)c2O2WfBuiW6+XtV+7$J zIsIDe{dxDr-W*MW0ieUTgcCS#1qB53?3K&n-j=h6FUK*c!XeYu7OORz^vbCts$t`T zm5)hy)r7ShcNbbqynp_Q61_fq^H;u(<^1sS{P53Cp~C5Mv>5!ZGokjeHDSVmzG`6j zc?H70QXH|+?w_e76C3|SMnkgvXPH5R*v;i(Ujoa4(e+Te5QZT*mYDZR=@(I-v*&Cw zMR`bFvRJZD6=}+fc4R@s)sg3U476xbC7nP%c&45!(`%+ugP)r^S8ix#W~P+1Go~u$ zdnOh!4#9AxHE6KcCX!QDP8ad6uc+Xdz?kUt*shyesntnWt>I7Xk7v;>cW2j%8@qs= zrn@i1qPboDb)D~w3Jd$Zo4q^NBq_$l#kG3qI4!QfW8a_1#(i}-EY`pMLokO5L3nP$ z@&WQl&nY4zg8TC`eS#jptG}beoNvD4H-_zqsqi=#b(EHt`X9EBA(fNT&t)|fpXTi9 z3N>Jv4&POsUm%<{pfKh^m1tBtV-Gg64uGZkQTIp_glug^by9^f|p zcK`VKWSId2#e|J7L2lFEl8QFw%y^XvN+u@x&5pLq14Yl*PEJm+5H@$M8cSt8gPi#U z4wDSCdWXgGIw9@n-=PL8{$&s0+MDUJ(d0Z}yJ++j1!$mY&hnj|-UQ zsqM;=o0NLQi_|NOMVh`cY365%gN#tg>b|@1ZnnP6$D_~>M^XASYjFL$SxX+I1!>(W zHEz`}mlz}BFwR4u6EKf(>q(WLfk;8Z92HF=#-5~Zu(}acT!}4m^n`5^=DKO(f2AE+ zKz%VRcBAD^o5|pRGHrFRUXbZ$V+gyxzUCJ3zxI)Yvu(BKH@{q--Ul)GbZa`!Y;JxY z;SWTeN}zlk3bD4feqXY2y}amu)A~i!WesyM$EKAT9AJ>O=}UUL^0UN-yK7gBq#)OA z{LYOQW!5bxB@k@&I-aRC?Zn_{p`1MsKKMcNrq~?6EdgQsC(6xTBZT*L!tuwUNw>uH!rm3fI0di;B>Bc zB#WrXCY#+I{#ICcmxDm|%%uB=n2MF+@t+CkgViz15A~Y0Wds6A^55f=4~$T*On{~6 zM?M13<-J9d=VAWVaZZ;(JpPGXxluDc$=VZh9M`{#bG!VSnwrOc61nFn=fI9`fd695 zjRFHa20)^?ES#sw_kx$q(NsvM#p}3upZp2NMFm0Q*Sn+2kL#A?ZqgT&I7RNzY4s~9 zDsqimHdY$2sId3bWKTGq-vemrHC~pkG!h>LBqW2}p7k;iGV6NpzX8)f?DYQ|Zy^EL ze_=G_*OTs2Z5&CHSDJmDrP{WR^hosf+6lF_QpV@ZfeAbQAwM1xtvNnK(9Z`#?jUbT zjNkdX*!_zsN8Lre{)^*VHi`NT6T9WNqt&haUL}k!R7ObHM`?uPt2b^#3B$y9$iVR) z>u&7+@K7kvs+Y|q9AW#|zURzPjtHD60M0(2caf9O;OIs`F*g|QQ<<>A^MS$mCyh>b z=qjh#4=uj~R{y>_33sPekC|sxX6+uow_AcHLXR1`_9!_WYUEn(A?|`*tLa09tOAn{ zs()T4Y=~+}`3)S;{Ng)g8+li`agc1bXj3PhwqtgwvAW*%JmcwEZK1lZF!8tHxX^&< z^EJ3sD}7E-!G=)qdYhjDtDkIy0rkR_yvHd~=ndE;0I=~`2$fg#^K*x{(`OOeCU zub*#nQ3)-+7@Ykin%f;K7Nkkcc_2WiaqV+n=&{MFYA4VWt0l&6qRu)O%crY?nM@hA zzIS1Co|g(SfChVr=y`}RXXpc2AvcenCnTsB?iy zj63fxs1dTp8~|Z^Qkbgfy0jxH-E3^gl~Ip6FMbzkt_Xd4($;R(&~^Kj;g4=t*uEUd z=!b$Zi>JDE#5{~!J)s~ZV92^B;G5iOYnt$ks!wA2G(;ya^j$UZQE-EuILsk^l@pa# z#X@S9T;V4CMJ-||Hud+$JN2eiw>(UH<347#S=&=;c^B;YUpP26lj{o!hmpBY=*SBx zv2N7y5pH{9JCV5X2S7L-GSKGLFNJFIh`Ct9W=FKsp;u*zKW}QPQJBh%@pe9`KbAl3 zg8TLz{bDNp7R)+>*&Q3%#{+UoB3C5*5k*5ZoE^Tcdh@rjkmySO&lI`eyTXxVMTTg#6vuZb_l4yOWVK`^4gJ2Zylj5b8SwoU_q0RB*`fEtc5bTU~ML9l%sDH2&fi(le{x@&{YSPpU%Y2ys%xiBIWWx=L43mj`*xTot_u zYs_rIho^FN&vjwX-po5(hrJ;u&Tyz|dvk^r@NEQfDXf>UnPw%0=YB2Eci%L`c{w*; zTkz!fe35GZe2WKr%F};OA%vE=X;ke)a4yWa-+a1IE-Ij(w+gj6`CPRt8&@wLPS*P1 z-)TGH-HejAeG56F+gnlKL6EYphy)zSn>T}yZFcjWjPV}G zaG(W(Tui5HfhpN@7L#Q5|Z-8z1)D;6ybK&j^%1m1c3+ zkzEaJ_Kd}@$8D9_>%#EvD(0^emcdNvQ_WaaZPM9bFDF$s=nUj-+jCp^_NVJFo-pnA zmO%ygMP%CroJsKw*3dL%e#^joh$}^(NHFeKhc$z&+1KQ_3NsDBvh$mtwriaWa7Hko ziVg<8`rnCg&R=hlQ(?+7d=Y0kaW6S~;mQ+V4jd(bngq^9Ai!@*d}`bJ_xWkt`S*3| z=gG$@G3gE|Ywx5oN0)wNek;Pn#-^iL9Zrf4YZyA{N^~KWKVCi{XsWSyE&uZLIq1X* zdMSEpD8tG$0-NcNz2cjrz8k8b?a7KBhT!9MuzN&oEN`Y6 zyn|bju@c(281Hdhuq(GiY9O=I*bzIcaj<4nUWZW3@LR`Kjn?a;QHx#EHkAaeDg5b} za+>vDeXrD8qkdkO73!Ik@@HYnjy77fSqL64!#K2G6|{e=GvzV9LU73)krYS`h2ayF z>}?vmg0y{r|EY*`&HFb1QQsBnmN%ELc8^1T+n@LQ2yV!(6wW^%fE|@ z#dB_zC-kyrc%$V`GLJu2Dyad`;Fb!at}}( zyQqZ_er;cUxR;fq$HR67l(@Zr=DAWCr6ugdDpescGG3i#fA$4Yeb}XB0(Z5~rIXQ> z)FNq8p_8#JQ>cCUM2+02JCEqx^th(vU~s~)MB9q|X8+gjrErQ{?e%?qkj+TTfB5;O zZ3qXasHQb z-xPgJIhp*_k@$pRF`hdG^UU#*P~}_Oy-5n-Y|%+KEEJDkmiNo>1(Z)Zzs#aSx0sf1^mWJqr>X<$Q~ya0p92 z&mU*)gkqXhIJ6Ry2@i@{WDJb8jb<79nigMa-S9P7%Zu+JaCBtA(30cZdc8nI$*Jq9 z-xfPT+FUklZGYpu0lWT@jQM+o7WQ{@+G9ANMZaSIG4c*1y7ocXUq(m^d7wAA{)?;3 zY$_ot>q9pummT{&o8f1ySFyE@H~Xxk1%!^7s1=z@4erj%c)EwEor^@fHx`aYGZh5w zt3i-%Z@wntCMBQE`xx6!I(c-d7B7J(U=U6F_Uu_D;md{12UpUs+r5?r35rld3S+pX z$_zro6r+hI+G#-9C(?06QuwB$$Dic)yayS7&0x&Wd$4lMLJ8YDndQ-Fr^xnX4n zw$YqVG;bLoaSiK_|G_mcJV#mqt^r+)U*wOEH7yHWxXZdBP+N29|HNsXzL(Wmn#3aM zG5>)w%G0?wQuZ2r7d+&%;!%rMg)X&S{vIRQGHi_q@%is_62^)!uL~(q7=i9ap21y# zr^igqj(v(V`_aR{&XO^^vy|t$%EJ|6DoD`d%WGJo+X{lOmkAK5)w0!=K?-vg=)}5i zHFjVlaIR4YR(Erm&r$sOY(}lVIY_;MG{g3u)DX7})APSTN{*l1J42Wk6>^nCdyA^` zlDmSkaYh+DPJCx7Q*xQsNaTnWwuQap+@m2`u-aW~H_Y?sI7n|~v#+rr(fR-#k!l3c z%d}~{t^U4hFhE$g0AY#Jp5(KKk0C{wIDCEnXU+4n*ilySPgJQ^y5k^>R&PSA3+V4{GQgJgGz89Br#>0f8@z znMK{@#Az)Ou*A4>(%;D%#;e&XW*453K8XBza+~SqXL?Os6?fuq;ZA#oNpe~OpVG{m z9?_PdyF#+LXEZ6__|yu9k7j04=SmElFwQxr7?qEoLB`9$pDP6Lx(^T>qzKsvrvb$BrhVFDf~Fo6*rIs!EOyrR zB@C*+DE==_F-F2yGcLcp3YkY`iM}YFT**|Piy+1ac!SCaScO_Vb=sDk5|*xCA1_og ze~qiq6DgD15XT6GlL;DmMzi=wnH0|#PT(pVQyFy%yn3q#nMkpH!ivw#wg@~JMNRbs zBsQ?{Hr3|JNnF^0=h&FAy&ak95?dBoKRY65t| z@76T4{;4^R+pvH#plPmI^k=2(Udw==GV%EE(d&}HSxK0}#<*(jwt76lqF}#?k36Hh zHO;PJwM<+4=PpSyT62THTOYu)>9ov;r#l{OW>AD_aL@kvbrQ4Vzf8wLs2Ys#RmQg7 zxW1iw+#PmrYbHoYs+&1SpRMY~Dt!GS?(kgZ>wy&!vL?-@zL?fFWPTfIN*TEJlOs6K zHf~;0unlr-`B<7T*&=_XbXU&rtO^m{lC16YMfUwy!r{}kcU=*#I{eK*Gve}c?tfW? zb13#-vyiiWF}q}7j!xa=TfJ+0;mM9BJEWb+z}K)z_nq|vM3EBBVsc=1VBSn~;&7A! zbR`n>h8^(I(LOQrGULM?cm*_&+9>@QOCJ zzEMc3$*(S)O%@tI@`}e(KHkjgHT$Uq+BF+jQagKUx(7Ph_lFHc{D)8-;51W(s-75{ z#_%YAAJm>6^H$QH9jS;w*JZdugCe%#dC#|L6f%;#C{=Yumb&|oOweu^l2N% zJg+q3xdl_GL4o>$N4S>!@kVj$z|bx~=Y%jk(f<0&1j)uu*vLB#K2Fw(karlX7c`x9 zA=8yVr$G^bVkZN$;VcVwXRm^U4&AHm=T9R=u2qu4vr_QF;=F`BHGhjn87qB=NB4YA zq5|UTqQeLJ8f^Dl%gHz>Jk%n`B+mVWLnxv{$ZCiFt@sMoeBHx=6Kcve8q=qfCj@y` zF#B8VmF~7z=rh;z-#2rS-3j(b77KUZ8M3sMhzW`AM?nv+CgO4o&wYkt_Emu6JcBB( z+OatNUQowO?NSUT`v7?-0gI=h)lbcup`sGv4Q=Wh%UhsUOuE~yT$soq>sCeYD5 z6%w)K`=r9sA1QDat`0?Fp0gY2`#}mb$fW%SNZjA`7$uOwsHktlfzR zo;N{wx)BoLe9U7Z`B4bp{u$Dfsk`2G;y>qMv#@rP!DWJ-<9fJCL*{T&=-S}v zmDr(w?J>!=HmjQ(I9dSiXLeXkLvv3*r*6WDW-8SV-)fLG+}Dr8){KMryQEU^Pmfd+ z5(B~hjK%Nis@c01$e}c1<_m<3<1BKiO$fNq?F9uaXW70(GOqrpb;tI;|5Qq`f&7xl zAB5S-5#0em^QU+0yOP`$3D`qq8vPw+XFx{R5HIHr595hut*jYw+QPgLe63)PjCXK& z!eYu#8!=6&6wFOlMnf_;L+}1G-4elx`Sn&Jc6mYgY2(YZ=jtmiR zxdw0}v^|o9@8sYhEHYBM8pKRwM1L*@2IUYpH~Z0?pwcb3jSJad`2i=h^@aEO3P~QT3A!WdsK`4(pm(XZpNE~Dfm)8)XlbQ4E;cq+jvD!7 zP+71229w`ZF&=1%5VAvjyH%3j-d;Im3b-x3!3mL9k$ujX@_U%J*#F9VF}P7>I@#NX z&KXeuA$3^^S=~Ff*|;sI{Dgu(LXa)ON_m9+xxVlVL#l= zm9zWw_8};*=@AEoKIGKM`i1!$mJ=poY*2CBX)Sq==7hggB+u63!-o$sNF#|Uf0XSe z`TP76=za(E^t3hTF|*thH(U| z5P@E_h}gs3>l{m8oXqZhJlz_~&PClBrRj;v6P10vl>jhevb3^V_6YzP8f19+DJYLS zzI5##e#uh&*+&0dK+481tLV;|W=~H(`?*G=X1A)UD!{?uXZiP_dmxo=u;I99t6sKI z)EV&1%5S_dGXxW?-uw3U_M)Pq1uE&^LQU1dEH(C47WPb!uh!XZ7g{_!Z>&dix;x(A z8-v3gy^wPS6hvzK@c|g36)Q|lPwT0umGRNg++%q3PmKal5*(c0zkiQ5IxXvz>5od8 zo3GRii?U28){J~d2X=rWH)RKJb^QGyEsccOed}kHsi`S)V4eeQFHp^l3JvWY80eb5 zi%giK@~W!4!dpyox^7XU`N|{*I|r-%H-p=x9^WH~t$Q)SZvs3ib1{iunE%qmBR6Wy zj}KvDc?J9W^(z=k=P8sakph1!EM)w`fV89J_m!2;iwCI4v~Y28<-im#L!08>(Z=X9 zAd|=u*958ug9R0cv@#D54q$#)f}bVmgoM)a(h?G&=g(1k%^r;i0J|4wqUPb5n3y;| zLX63wvwa8*M2ZZk{5gYUFs5FEJsJEZ5#-YyP)DMm9F{!5Rsq%uQdYqB2O)x6vqxdU zdHOUtKK>)*R-Y)9{7g(t85tQKy9Peg)YP}uh=Sj-GvDm%>pMzEixe!XKpF=8D=VvU z3;*-yPj=mr9xx)QqoWf|F5qwiTdc# zBWo5cq$J|0%T3y&q!?d|rBin*XWA zL->P^wrmYQ5X&}RPZPfQ5b>c887UmizkT~gukz&+pc1)rWVk|8-s^n=WQIaWB_c9E zHpT^hFQ5Hkh!aQ*r4pY(HA8B6;8wvXI@I*^-)Cn@GF@LHPwOV5p#cY!m(u#?*#-xp z0b_+kU||0K{stRV2X5^39P@x`lb4s5Ouqa2EkG@52ZqgVgPol;qM~hTwq-`myzK1d z51WMmk0{{Iz0y7Z!3+^0Uf#*7!zhUD_nWF@PyOmg_BoJ6pF?G;F5n}PT_GVM!~GWL z2diLG+UmZW(V0g8EV38x=~KBNMboK2fM+5nCucgmmz5t|D#b^ zK+jTAR+c6-U{F=${W{2Kq^mnc$fl1;%3oUWoyx%@6Yjv20O0pmrQ-GEJ1@%dNfOY>nK|DJjLr z?zWy94`+w~de0(=JAiEUEOdPS8W2$4+D;T}=eBOm)PMapqBag`pUb4`EgQ&yR-8%K6_H8y_4cx)4Wj%1|?5^OI{cawy?_PdGRn3)Y_iY?~KMgwJP zVwTC#O#!+VJD8?lp6#dcIXnyFuDt?$3nZN^)AwW=u%8%%6}V@X!P1JJGDwvOe|1%5 zK46^JgSRKf#O!@Vqlk%s8b0nWfkP3R1uC&lfco|O`K?KQ-ta9}g7*Hbdb0{qP(V+> z03@iG{nW=<;}YutGGtq<4W<<|;SkHyy>@nfL2$&aTxSETD+sMmCVZaQH=fD`>ka9a=>^y-%8t-;U-;>+h$E<>uxVF=o&D4@Um@ z0Ss37l7cocTJ-NH>UO|&X;RYC(gM7UB1mqx`8lH^i@UqKzTHUHOC&chTds9>3P9>? zKu|-+#^#{&1d&IXM|i#=O{aehSJiPoPC-yrL_)hfcnJ#eKK>)E4M)-i9iGiN=mXID zvldCblI`vS=q?gp5TwZ*3v;S+*MfGyk{SE~0%us>x1Gf~B7GZ?K-z2tT|${!Ozpdb ztgl`(YV4jsArs8=?M)oB)>RrjW*Raw!36~clW4Cedy&s>Wk|U6p9p~gS;FE=vd?bW zL29s*1RW4u>KW%js2saGb7;TfwV&gM5ht;gVG;;xx#VcHnRW&Pe#RwWEntxeLN+Ja z&U3NW1(Z2XEUPOLWYKhfHNjLLB=fZeX=D0sGAzep&;?3 zib(0-2D&1flGD5#J@Ciu3(PQvG~it(2_@Mct#H?fTF@G(Wai}Le1O%>?C^VczF9V* zzuA2^wauwm8gX*(OG--7u{<0ORh(Erz2%a)s7HQGjE~h))h^IJlKC?)N?>*Hqv-Do z$6p;1R~S(M?wE^<2k;!$n&TO6lS=N&9|K~OVXK$6JDcRbbO$>e9V9j{!$!xi{r%zB zsnkY_x(cOxHvqM%iyE=kI*0|kg2}p-fhiL84S_X(1^jxssut)P8Xb5posa0LVltF4pQA|EX8d<3uP;? zw3L;C0?CDxyhSM};h<3Yy}Igpup%!ca-Ee$X-qFR%Rkd}=)u zB%WHc+WYlY1E!~^2f&8bm~`qbf0|VS@H(N8z`#IB2?=v^H#avgb~y@UaSPCF6R*wq zr@Ut1;h?e#3JQuO6RJ052RC$z`*leC>}N3+J_Eh9=L~@1r%?qQF)KVg9N%%a{v9B1 z1$5mZTmob*fE60T4Fn-kcMx}9t5^;skM4=-112)aSU`rf7?s=rB13kj{d{jLnCA?D zuasxjJu#60X@33nu1_{bsU+BzxVX5M7XEEZKFoTu6j0#GP%)o6g0!B8T1ih#ObjXq zP-q~*k@(x9cRx@yHyTmm9~KoAk&~0x`*flK5uI7yi-f{CFgV7_C1ksI{ftosNJz-02vzh4k)d*sc4aGB_K(__#no*W=B=U ziA)8}kB^GBIMvcOW+bZNiQCE6Q;G} z&WD8kh;A|_xwLG10DDYmM6S7IP*!g}W)xvkeEH?+cf5O}nQ!w0ljxPXV6u6yR?WuOsmSFc%JhxPJR+v1Ce7^|#Xc z7xluK;eFH^QM~Fywy~DT4K97sb4~sP9GXl`>i^g5w)-2Ir^{+rz@sG(toFqO)nfSu zZJSS1aY0kLOGSXF;wTJ?83v`~08p3Q$t%H;2?-;7_iu{Z{e74}fAN)D<=Tr1+A1bV z_fTEc1F1O&g_gf#?s*$OWkctj-qSQdSHRHHb}UKwYKSg_yhe`O_Y+SAItkFJl!{7J zdwYB2(UVYQQ6V?Q`|W>CbUQeGdp><<1E(mWnDQ<9CU`|q{*XPvyl zS3xGH#eguB+K}Qdi)YY|bDVZivWVr^w`mGwL<$rE>NW)h1?GL4m&oXmXUk>Uao--L zjyY<=W6QywR+{zaPz~-4&TuKdMPJzMaMya2i_$^*cs)x#$4!#cMZ_V5(0(@!$;YY{ zFKFBHIPmJ?ET@PzhzQo|cn{(mz?-c5RP@NW0^6w;`n@B`$%^doF+?1vA_K(yKNzu`e1unM!KyD(07I2DRJozG&+)3&!%B z@ss8um(gBuae;I+LiYk3Py*IQ6BHK*XN$)yS$Y-o{;Q`S{6(Q9 zrNx1VXYY&x7xg@tB{l3~2$Y?VjhMmU6GpLwYMV={6~9`CXYK6L9t7X=r;hEu{*b{O z0HPs~1DO_>po)r&1|W2Y!RatG=v1S0N{HoB5=soDVEJ34{?w-_!e9=WD2~;7ddche z&=86`6}|cz_Ja1hbNK;}%~xObiFd3Y_}(g>{#+E!ds#P=W24Mzh82BPz%oB#%om$M<80o3QTLUzn`hz{c<*1 z<%F;iG3Ko{p}BeX&vp14Ayc%~0w0X0qWoWcTrM(Zxf(yBs^T+xWD_~k2r<%kq0@NW z8HkUZ*3KtY_gq`5Vy6!cLqpdWevmBstr!Nv6EMc#cFp99PfW`U9!6Dqk@?+KiY;q7 zB)`$vj>~#h4CB!#`s0cR2G#BK+y?-7A`>eba;7lZIr4U9-{|U`?d|^zS}g@LI(fRE zxi;RA#^-I*^`$u8!%%91eVauZX&VXZ~lQMe=&tg>jNx;f*PZ(}O( z(FYPyrf*)E%PH_7+V-}X`b4s7^8p{n!N23aMb#OrU;AuP#X;N&RFsi^el5;k+}L&U zhaZ*E>k`o9_#)tf3R3p_ASlT>r*{yf`ZwNA%ZFmG$A*nn(Sp|4^5A=gPYjWnKU*T? zb`O9ZyNQ+Y?OlA!#oJf8V2@=LtFS++g~fytTHp z2I8pHHhc3%L_~ybRFd{Kf}Y=F8k^>+Xd07D?>aerhPn;ry9!sZU?`xo{b#=WkIwd= z`R;?kiHj&xRn4b@=@fg#^+KPSeC{<(;Hqa=d$=W>{K@NhKfD)qU)yRzkcEv>X!x^f zpJGc#++o7{_jEKz?Sw)tZ6$v?2Tr&no_kb5^T$fbrVyNj)2s|$xfq?uE!|U-K=9fc zc zU#KL5OAQ*Z#@^|-I3D_7Oto*N^RV$JKk$H;MQPJVbmDnKiPPq40s zOosVvhBCi5)vk>e9kbW(bNk~}OcyU6H6cwEIkiR{pt;sP`^0|leEGN)A)HEx<0d!! z*`SSZZ0gxu)c*hZo!SgE4U!r1$jNPxgz4kA|3Pg#B=(+|*o>bcs^?5o==0qP%WrKx zl81;Eh74Y%zw-ZpCY#cr2Y9APvfy11`g0-cNUXM|&eV*(nqe6Fk6`}XJ)3#^zkyn! z(2t`rVY}WqDnP(`n4Ipwt~?HSEYrtixe(`uGcr#5P>)lFoy)oykpUzGlm@RK%qzHm zd$Ggib8NbUa{RyO<&GvBveyHA$+ef~2kQHidKo{RqiBl!4BM#P<;sT=@b1y?#hA%D zF#W@2j!9L<(awBp|B=wIGdLMp-*QsR8M(W3+dfwmf=|bL4oe^yvcXR7^%1ZoLv{WC zMy*8kSp0vI%7v5p-Wn6|g0rVXgpTpvd5cGaWXlFOB4#O`!kKL+0Q4jRwD>!6&l<+r z2@7`=2__L0j_+PYf>kkbuf8+I)=*1#Ghf1V(@UBrTLxQ%Qh)x9EL@B?xpLdnG{%;M zWpOLG&zbqL+!F$pcO+~~{`@_Ocv;vR9`cJc68R!YLxyXb487iadgbz3GP7D}-zP5x ztUnjds|^?q&t?bBUaX~+G!e3m6mbY;w2(VRZ1!laWl<40iX&{IW^;*)_!iFo(3gKe zmbq?J^E4@DV?@GLJCdt+{r?+z717u<*Xlfzd3!Z?PSy}|u)$2<`UAUUmGR3T!@)Xz z*R@!2?CYW7xVN&Ks#(V`94QfhRad+R0HVj^^ZRwU5qB9NH{|6Kp8w5J6oHkj+LojLJCBfTA!oCp;%hHc)S!22~h|BRc{4BQnAB z4EtKD)rjL7_4SI2kG~BJ!o)gXaKyjNhpzh{APQp0W4WnTn(#z=kZF8zpMXpw-%78b zi*-C<#jTr)ZPfDs5X(Tk0GyNgn^L`g7ACD&XTEAmo#EJT zsA8t+RYKx+4wpA3Lb@|3Jjzm!rF{r{#$;qdmij(IUgAJ67L>2q#f_CG9}&(hm&$F{ z<)9~*K~_P4oBeFxX}OfGQmW0saBaS^@y@XeN?lT`*cJ(3n3lti6PF=umL<7;4X`z71|%?7Hx0 z;*D&xvq>V7b=aTGQUxPsO_;&Z{(SM4PwYU0qwEgRUR~F9X2OGwrLw7yLJC@dv23qJ zRe+{y>J(*=a|!aB9#neP$J^894hQ|>eS$`SeH)wydwZ3Ck+n zMF!c|Lhxg<-r-DhU9}gbVQ*fdqOQy9_GhKOkMDi6Lbo2y%?<#sbsnCeB;RW4KI}o% zPFTL;lp2Fqa9&As#Vyvwn0lPqrUypOda$|J10N48_yb-Bqg%3FYv2DR+u1Wff??%~ zmmwsdxNW{ZX5QpoBX_RN^WJi}mZ{Qzr(T!;lryB~f=e1EBRHz~W35SxqhcZ;I&bct zCw#&?2C$VI3C$|w$p^EXI5hrwB(W9oMA>q_o`tk>`c3= zKRU2bdk=SYTm5=4KH}d(4ZvaH?4$JT@=ZA{08;0;$Pmo`0jXX9q&i&5pZqz+`3|)$ z#cP#koyi{Sg164~VuSwe?n{ln+ZPPx4pq-^-h|{`m>`GHASX)7y8|dH@jp-$v-rQD zDDr6w<(nrr18|!q`#s-8Lvgarwjc&~%-1=PW49dlJ$K&n8NQBv((-SA+QugSn5Z7^ zSI0`eH~`CMHNvlcv5PrpH%s&6TX?r!XfB!qqDq9@+t9?gKLI}>VGQO5ZX6)cSRl&f z%|%95^9gRuANFXr>O8AONZL^nkE>!wD1xCdi^Ag-E+*vZFEn%kXEllMJ$17GLr+ktn)v8ga6cjJ``=W&(;OO`@< zO;uEUFb3THDHv5VS0ov5jVDqsgTLdlF-(lKC@+weteyZ)g+U^F(4^5>cGQ|@vrxiS zLDZ@JNl9*phz+7gZOWBf+2SE$>=$1caSIB<@U*h|@o$OXKlwI%WETCQ0_qPSIkFRh z&a2WLtaR7&nI3FRMl@HOqc>0;t4LDZJPcMABhQ`&Kt4>@1mwfC1gk@m%)`>{MSZo9 z3%`|QG9pk(%^=}zTHtuyZ#+K%Tqh-N$KQnDJqr;?F`wOc_wP2JuIgUt%D(p=heyYj zZ~l!~%WTbjQjvilzNilC8#Qdb@t73Y_TA*W{PwCW4}K*AUQQ8xDu|hyB{_2_c_)3N zR~BNv$;1&J!}f*MMv|EZO@5Z@8{h(D5ew3SH`R4u`+7di{iqK_13@3h@Yrr5#a{($ z-JSf;gza}=EH41x{XuS17#&hrvq|N4riu(Teg9ByffwKQiCX`{M5CbF8czV+5E^84 zO^A)*QV~T$zpY+^CrD#7Mb?Yo_FmxzLcknurTex*W$K{A%0v2t@Jx||@$hzMU_8Mp z%%*$XgTbrfiel=?r@o2q%Lb|QFwb4cV>0t23;Tx>BbJe*pLhHp19pgluBe60>L4D^ zX4L~Ux<%g0b$+k$-#y}LSit=Tw@g?a9VPn+Eg1wBA z2?PG)YMeqsL;HHW{=V$>il|`ymoa-X%N9J5nNgvnGdlZhEa%1O^I#M{2-1$SAPB5j z`%_RA3M*kvf5VHVI1J2RZ&+;_i~xq@MyzeKC-ihsd!UU7bRCl*ICjl=A|UV@zyM`Z z%#H$3CP&$*Jd-wfs85>@AQ)}$e2-}xf=7IUBixbru5w%D2pEAK!a2lIg|*l|Fahm_ zw(Y?%y?x?D_Ljx>Gv@yT*VNz%WaYSVoe7!M6Pc5nzpko2pX-3R}{p>~Qe z$pV&Lr`6$o#kyIU)Yes6_s+Gh$m2R4PVWmPu*J_17Pj#Ge!QhR zBZV?07W-q^ZD0=p$5L);>8k^Nw9;Jwjc)NRrBQguvcUJYbVd_)BzE4U72-pfLz}wf_LGNbW0~1c1d7s1~ACBfWSUKRgH-z>M@tdYeztM ziU0HuKH^(+gV#cI-Ed*lNV?@W0-$ad1@|G;w#)I~wde%T8$|%tl!DDko5^KQ%{WJ0 zXjLHJ+~_DbYLvWX?EF84eRn+7|NA!~ic0p($lip6WY5UTJ~l~+9I_&0?-fy22t_h; z%!usF$R5c#GK=io*U{(u`Tl4f<`Es$xDL-_Q|EwQL(JV^)#Bb_K#G4+LUNod~16Xx$uKkh{jM9BsN&5 zFmE@){XYhmBwKMD{lldk@;UHsG*SMCOPO*tS@d*G7*cLCpH~p&ol)EB4vpCRY;m5i zJTDJ<wZE{%HUzdCMOEot-u za}_c}Go%OIVoaV|ihf+_c=yU->@CafAg>=b9?=e?G4 z-I7W*LMblcjvJo(XHH&w4RoMC!?hRoKyTn87OL-25}ejAZ5A z>1nT}HJACzk=z@;xsH3KLC_O7nTh*87hZT}F#ld?ac!Nz&#+bgi73aaU*d~#_yc|s$ZJU}F`@%xHY zsF<1+8ad!hBq($z__s%~M{idqmukMxj*^JGXK!7y!>ftUrW+>i@3E8E_EZ2nZ-Ft= z=CQTKm05!%ZcW^RiV)oT8k75W3SF`m`Pe>mIDWFn)vJ&iUr*NC^nGeMb`qeI75l^# z8Yl7BC+SYcHSExB)Tk8>0(H3%kS)k!DUT;vwKf^_$z}ZWA4_hGz*y$G)Q#x!GngRj zUt2%LUMMi!kRHC#9C$3%r3llgfHIk3*<#>GzaH&|ZT~(SRafV0Z_fen0mSo9_$_|X zFjKyEHPriD+U2ZK`^2}I%g`L~n3_ErJ92;#Z0j2uu)Iltae-C1vB7w0vin|#LB53@ zSw==`;X;q_oQhBv2b8%myZiefPQ%QItpvzI4(KJr8avH1yD6gl6-sYHfsY?Q{`So_ z4-YIB9nt4Ewi?%;LrpKO1J7M6do+e+VZKY5!@H>ChOc5R|1+oZJm3NaERcn%CGX7Ss!dO9EL_$J> znVA{LbP5MpE-={O$huxMAe@OEb|wIhcwgJgymDroA zs?D?~rH3(AC$0-nvMnk00cPC~4HdcQA5+I2I6VrZ$fOOEKK2%>n(%Z|cxvp6NC}K2X zjuhB$yEZs91jr~>&}F*U)7Sr85aNk^l{v?{JPKY1JY*>K!05$IhLl)oa4&D*SUv>q zLJoW~wirG}3#IMS(o$d_tgLli2b~`HOaf13A0HHG84ZGr7|aRgsSr&Nmhnr&1|@zD zj?)-RN#H(h?(C>Y(y$5%2}w%QVX)QjEgCEx^rdo4%j2SgVDb2NY{6|~1Gq_qiKpQG z-x89N6j1p-XQEBH0MO;ck^s5->+Fx0N#Kjd-54M03kbPbscC3PJ=zx?{6Mij-;1R+ zYG?8g5)kC{5|h^nXUwGM*kdVE-Jv)1QR_-2oD6#{yYB0wEpOEm@bBT*J zkFynoyY-}8TYoVf>MvMynP`0WRij?wPG13*R2ln+3hv(AXgWcW4pXGa_ zV73!0)26p~b}WE^ik+=dH;_8o-rAA|F`UGf`uBBp3&xLxv8OyP?m}Z4KF**A1F+X@ zY-|$F+rP~hyE}-F(e{JgprD|Ta2|Ns=TAA>JOyLa3SR-s10~@y30Q6P!0D4!#lazX zypF9c;@}vxOieLnX=5#5r993ToUB7R)b~KGmmmy-l)za@hGTT;x(|>vShyc6ZEkP3 zN&Jp?abp?X-`jKkT27#byOIiIihzLQl@%v8f-(klJLRAl9*|ndIkgleaeO)1*zlRw zv1n1%UF?xvU5zQg{lX$HF3!$QfU#tG@ZiDz&N>qlQ(PVnmG$y)5n7CBkY5sL2)1VX zQF&$Off<`!$B-Ai*wN9Etw(o%>T!q!?2vR|wJ31{!{m{e5xI0m`6=K5y|2Ip+oaTQ z2KXA5syv=oPyp6bV(f;;Li@QN^|B2wqPR7FqX!gZdQ^f;IX}3yOxW+^9q{aFcDkw7 zxPro(J&^wl#&o>AcI(Z|eK7gImOh&zE$%n&6_Cz@L|gj7xie>SFu-5yF!Rkhwgw@$ ziaVdh^Swj%?XHteN}h=&pB5i#(tqc0;R8}YBdrE&S1B?Q05BxvDDP4AZAZRGm&3ztVLmEW#j|HOj0!r2fP_jz}7p^9~J(V3xyvWPE! z24Bxy*Le2Fk9$=jXkc(Y-2{?VPQX+9hTZw7kfYS9Z1;pnapR{1`1mA@lEb?{v9wy( zdmIv4UK2M1vZJ`~q*AK;m$V9Dzu-t)j8|IPtmY`$eh_$Sy++|xmKW*@htdmp*P3xz3s$o{}|m_9?{Uc0Q5^>z+t)JbfUn(oZ4LYWOoS6 zdNBWbMY{RGwu_??mcLJ{I9d1bEy!Ex6Q%zV{2}n`zRUU&Fwve4fx+Q2tzNR!&bhq=> zQ-GhmuNLu_=NcFo2!cj0pX7f`78&yO#I*I_eOaZ_;Qi|1XgYP!^gk1(sHliuwK2Ye z!FWn=aC`?+EAj{w4l}H|s4k~ncP2=k|;HttD z>qNNz`mQ-eIU<4v;UkMWPku^LdU2=tA3omRIz<<$sa2k7k^_G;uc7}943r;%(!VqY zx>&Mzs(qS)Ap2vc=@|BI5i<~xGU`=cuJ*rq^5hAyj~;7DDAN73__^$$P@bQsgEXq0STjNjSlUMfY&qVAvZe`ZrpOFDt z7wTyL$J-{``lO^GpzxxrSAa;n+^I}(AKDb)=`=Z8Yi9g?H)iD|$+t2QKEe;i9aeR& zu5YcG{F3kYr3vYBQ#HJh9E3DpJ}NieVZj@TpcXJweb|VK%aqysM!r|bbM4x*KJj!J z-`{+QWuU7f$@-P<9p25@jRUdB&QtTC6_=ldJ*H;%3+*vmzd#-8s`+Uh_5~256V<$G zjeK>B9Es|W#Ijd6UpbQ%Zw{Gl8w~6=y?IEBT7Sv!ceFjaY=-I`=AY5@D-Oo5(GE(I zM^}zIeu>(u`FUnt^(5>P(`%1qeBG5swgf#DBK~mtQJfjl2`4mLxrRHb(+K)&&XvCl zGamXpEb(;dByrgq@DyO5PgDkr0(4VaoMdc&d0hY7tO!~n_KtCd- zM;y4X>07Enrfqy7N@)i2K(Io|ozLqDW7S^|#7_@s}>sn5n9@cXt_;a~?1ZjwD%` zEXGdfrPhf5oW91&D*r1;e;xDf`T#urb~QnE(BrjGpw4F3<$mWah1Jdwmv0O65eDr& zJ%I|39|rs0%fsBpr;89{(Dg9xMT=aUyw)4Wg5}TVh@f|70^sCJri60*>Gny@@imXk zJ2re|Cx3(c1u;89r%qGuvm%>Tv&Uau#OP8DiRkv2h#_DB zsFbznd#^9|N;TAdDZx1Y9eJ+`kO6_Yny`*LoEH}plW!Xn74?#2ZQ!NKUsmm{$p5lu za~dyY`yK)Xao{O%(tY9hU@5nuIvgOWc^~?>GC_QFviy7G@%Q_N@=CH0JYd>m#N{6v zRn~#882SRblH=ue8he??2`ZN`UrOkeu;Ot@%l2;OdEj#At+H`)g39EJNcmn7huw|2 zyLaza76F5=pJn8=VO$>z`LUfsx3(moMWfl8=S#<8sNR_U(9p2oP6(=%w7KSjKW|(c_;8QpKH$l4~{X+O^)>>n5f#nCd%Yf!H&?) z&v5Jxu78|wi;Cgv2d1xah5gaN%or;94$^|*U-E7zJv%jZDrmZP(ieg`0;?BA<^JFS zsCj;Y&Vc*V^1zH0vhdU*{*8kUs?^1R7LF= zW)V~F3euZ|uHhE(y$pErdk|c1t@{$4;LeClV8X0{s_RtPb;m1U$G3-OteBHJtL<&y z0JmB@NZWs;P)Fg>x9n%eCN~you87=w{^CVvfX`R?)4CcMCut?GHMBByt^_$ownB zydN_V+D3iPuMIT?1VEUcp`xhxWL!xMrp}_f<*YW@)c?P{HUzx5#42$JK z$j+FKOM zaBUD)Zok&L?d-RPRaXemLTld`S18k^A~kM6juiM2x7lCL;%dGQ3bMuA`H9b;1=-j> zPE6E+PlVM|!jnNVKb$)WU4P&@6-pdb;|eSDoi7IKQyNYCAYUrqxcEm6gNU;0uGIWcb*e)=o!jkWt9;@i^z{ zGGi)1^PA7a?({LRg&^XSlCC%o7Xpd@GPcj{SF>U5Z+XZ$?F>vz=n`AZLB5pL=NulC z79VxKOA~ia=Vu5#BpQ)qu3!+n<(vfD>Bfy4$$2<{Bm%MhS@Wb(#bf33lIEG?96)Lo z5D-9@kmL9!u0bYtGi{Rv5fj3rYs^!+DJk)#9CC7UfH0^MW~ag`Rz_7) zV$4A|8v+Rc1%NbP0_`PBeJ>Uku)?g5Se|ez-O<(6g^0MQa74;*DmEfY4%MNqT62=h ze)>d+!P%OJ?2eE{oMp;=sc!@{fgyy%_PTj(&cnne)4{?3*WRI(WDEAtF_?K)Ms*_;XfOkk15MI@pbx9kp5XN9^OvM| zI}$E~b&QIRJ_J2$?w{Cxr$J}vvH}lvn^zK61G1?&$(*Xl$yiJjqQS>wbH43U98(xF zAq7kBX9chh`Ux@Grv||>twvJv{#if%^Lb__t5{J!JUpCestp?0itqz==fbkQ=FgaL z2n#2$5}u>mTB-OP8X5}9%8U}OvWN$riR_^U1J6xoty2XM%l$d6;TJEXT^@n4f?VSe zI;_y&5r%9h4@l6AM7tQB|9Sci&lLQ@b8XTaOa%0#U3Z)R2xr7`v=lnd#7f!~Qq+S=29VWLJOkVb+2rJmIZa5Ymv0MAZJ^k`2O_kKNwUSUH1~;rZGK`J z+PXU9r$BJeYxlTjCtvQi8Rnooyj)dLagj_%@k#bK3K^Qi6t!r{g=(WdWiVuG@P;xA%SqMEyah%NXvcNJ!`3cYU%mTy8!*!QZ&l@1qUj}K;!yLv*d zxz6IO`9RtO4HeLctD&wAKEY>uxlLx)?b^uwiw!(U&d}UPMMVYZnVli@4lRBAhJ=1% zP|gku3E3QNjz=eQt0B)k@tkwvEo4L<`FKOD2euyesAW5B0N9bc>~Ms`egqG}PUT=@ z+gNJB>9`OJr$@OD(2r)`bYYuNfMo*`W6}J%hIZv*;^MJ%VqIY3FW_CH6?Za{lfzw( zjEj2}p>L~BhBy_N9guqfy(kcIF3dtuwmUI7Sr4k=?(Xhau2eweP*+>4q@r?}5!q?q zg|qM}4uaXX4|!@yvR~lPLobm8U?j6k6b(v8#eU+XmHGL0(9z`V>}+Ml;wSR^IU5T5 zHN84|dhXD6=13@?u?r_k73rb))vx~1L3Lpv(YG=CKIr5w$Me$29-umUf_p#K%Bg^D zfRcb>bad1(eyqP=mS16Z0TNkADy1S^9_m&nJpOIYkwGWkoCj9*kXfg;ww7YHn~22* z8QlYUpvv3Sh;o=oHWZ^@J|Ei4EU)SN_wRDSr*#5-T!z4RWQa+|FI-@AfBPO8 zBG(D#BEm&Q+t9G)(She0;{#}y0go+Z{?3|!<|#!75w39vhJZK3|6uhh8w!P@^Im|} zLX)W?r9#TfMdGB|4HOq{-TDk8m6DWG=NthsRrVrCz+Z*F00_@@x@q`@Hsn)x0q5AH zjsz5N3@%Y{q(Vfkf$D0l_z8+zKXYlyL)40WhH=3WQhETQsIn5MZ>dT)&WqlVf*pp zM|ZC+2Mvq=@zFz)dZRlu!qy*QzKb+bDoB-BhOecj;J|h|IkSk!W@_Y@skSw8pN$Z+ zoIH=`Y3y10bGUTl0<8$XG%kqrMhPd2p0&R3Whu5&n z=@T)4QoY`pLDE7~4q(8|8M`Iw!rPGe#IpzqZ8Q_Qo`3rNW{fcPa~@w`-}lCV^IV2q z!!uJ*xnXj*KL!I0y!RX(^Kq4h@dun89ihE?5~_Mec_WjPW-@y2GTOIqr+{1pV4h;e ztgLOrSP=_12!D1;6OYCIo&pW#fmNJwGf~ytiR-yPR#yBn!$9_d<+`{yRpS6OoYK+L zeC)~z~|4O z6jl@jmCKtd z3^)7_pD1vjl;+1c5F>FYQ{*T%i;15hn2rYZ*R!T{%ETn!b8 zY*&B8Aw~OeL`1}jsD#8=J>|uV7opGmLp~%<1M+{j(P|5|g&*$shFx4V9vkX39|{!r z*8sYM{u)6*18(0AnG+11VrOS(L#bb!I{z{^H|WOgC5VhKFv)zJIZth*r`LK|va>#; zKw|s*4)e(wc8rCtTPRm->NOs$)j=5&{1Ox}ta<=AzFuhxM-XQ2#~F}|f%$0!*^KT0 zfMsl%2W~f_=W9Z(D%JCKkBlYVk2*@fZ>977k9%S>a;DFAd( z01rUG2eAH$9R_1B4}Aq-#jpSzbh^`O5ni~|Q>`#3Wc`syN~#Xpr7EU0zW2SLzjP@x zEzQB&`e$6gVeld})l-#=UA+n@X9>V0penEj*AI}BkqIdVKY3_>Q#tqbb@$e~Rfvti za`=c75)!%uwZWNg+F$0CyA>WA`&|Zy@rJ)2U~`~Z(5&qQcZ|G`)cf7UTSgy`CX-7d zP(#+8gA;-4(GnN<2;#v^v{}UWhNYy8Ksr4pJZbR_M&b-{#4|kn z%&Mv?xOHF|?9W)cEv&+o9jLHE-Ey?QpSi=p+&oqW3)C{e-7*ZH0KX*NdeRzpVPb5o zx$4oc?=eY9dL||&;EGZBE3qFTDicTQSzd*83gRG6M0;MCpPyHbW!T$kI-VLIPZ#Es zHWXTE`m_BOWzg*2fW(mLGPkc#3Gqqrf`-Ud))!3#U2u33%E3bl5LALeIQ@XoI5a-QIog183sMWSZD)O2V8ghX7#N)9Rp?-;1gVX0pDzOJ6C+ZG z8zFE})Hq(T#uvvW&bi-in(gE-G61IXCFa6Gcxm z1mfI2`-i1_T;czzj~X$Q@>m80FK z+@XWNHJgT0PR`Be_sUnelgJhlh$lf$Q&SZlC0Id*0OM*lpbZHNs~7?=E+Hk=n%Xw| z=KXu9!x%rCY9>{rZW0!4fQsG4%0~CfgtSD()K(ZHY}FV%s`OKN+-XXSYioToTp1;z z?rv^YzONtxgX(ZCykf~>PyNW{m>pA%zxl(3J$KZ-rD)aL27lgLX($mvB@Siobzbb@3&^8<1 z@X>Jm4m}w{ggwF~bpc|D=L@g9w-Ib8lNN|3!9_F2AAST~j-p#-gZOC5?d@&#KLOk3 z$j#UEBDO>m#i>l3x8qfk6pLKZ>70pwLthBE6{x1b*9E<7+WSrq^+b zWgH%gMC8u(2SQ6aY~`nNGJn5`HyCcYSevY^pl6x|LI*T{BV?+oY>rb~lngbT?Yz*B zx3`UuygWRh-~tLEnSRYLq#pM4^caQLKx{%zo&*TT=KYJB$!Eg)aF{^-hlt&sxFwGa z>!J7AQ4nZ|A6=H*C`Yu)+sacs?6m2a1-%fb300hsThB!DA^dxNcHIbV*A`joXBuJB z1u2w1iPMMcE_2nX*5Of6ts_gHvxv?0j7?0+OPHz*iJM%jMbh|BeaXj;3#-E+%0QH! zMbrW`f!cfzLh|a2&U}s3Mz|yD`E!OM#Q|6J`b<+?csLYZw?NwjE*W89U=Ug(*ThD? z%SGrQL4BSPolBA%>4@TZD3Xz8acm8<$FUH2Ia#__Z!>S#XFmk<8oWV| zzRj}id-96pO07A;$x~BP##(7fZYT%r zR@4npGL*f&?BLE=q0a(0dL4XAx}}Iw)3*0zQgCFf=AsfX0~gdHE^qy~#A*v5H{^RN zf0X2^<4>19;r3&mbcLn|lRcoC3TrI~xn#0j3&nsH1aHA|azXRQcET z_Tuk*6#V$H;oxLo1BHdDxVj3d++udq&V2ELG2oc|91|Wlz={BkRaaMUv>SOLWWR4V z*U}h5<(5cY*#nm5t|31^nMUhgC2!SDGeJeer0T&$1_OP4X3!e(A9#l@Z@?Y%A*7*x zMD_^hg(oDtemjQW$s$Twf)!Jpimwb1q!^i)V6SlNY5QFg6A^)X9cT{oG;9PqbEkQ^ zJ_3ODfw12Hh%RDQ5jaRHDxW|{XmN4zortrOldBDAg#{51YmdWvjZJ?ts(oMw+Af}+ zzaf#;IklrEzr3j(!aU7{mx+tHef#!mu@dsGM3!g%(}*7-XvaZ=+-euS^9VCD|9LB@ z%AC6PaRVzf5)dWss6&kyBlZSGg|_H>E-tZkjYq#tZ6ALMfSP{anr^BpG9nvJO2H~Q z;t$eIfJ1tS#lLbK+!BxqyreNJ8O(x@ZcK0OfPeCaEnPHLL?<^rt<8*F%3voLXaobp}9tBkXeNe_?y|Uj4CgZCL z*YC_{GiGR%(_?n`P9Y`gUWAd6k%0lnFAqh+S;6+@=9V|$)GM-k+xcL_9{Du9(SnGR zosU5YKxdASN)4o#H%ZwQKNX0My^$uS%FWrx3}Mj6MKtY++)u@ zyZJ6^gyy(9y@jbD0%dDu^&ueaO~ri_!&z|5&mQI7p^@_B^IhO~@9bBEgrg2_WD30e zd73OOBja_`*Z}P=|3sj{+Q{ostb~sNn8VY|sM$%7zWETlQpXYS+7Z~kbv`es5fTdT zdHMNceC2u{iKciWm7Z@KS@auI8Q;6=Z?(36#(zW=S0yzIB3#UnBQ!`;4Q zZX+?(+}HGA{pdo`L9}x!GF}_m@7^V7-VhKJTxw#F`P>SaP<&=`GJbW}=g)VvZZ0Y9 zKq~v5_rEE~aF_J-Vt49?MAB}6k+4ByY&Y0Bet!Nr+L{`wf&96{38mDC9|`E{uLio+ zYtalX=71e&A1@D7RdqxOkiu1d11e1HoSZW#k0{M-DUblmNF`B0-Z)sfa%khkkwfy0 zy7f%yS#!_MZ^;(X`FrKk0t0DEsW*#k2VRKYO)MPmO%ujTeLnWkvQ)4iscBt3D*ar2031kz)bzyPt8RgOVxZZEYdG_3vyx zQBhJ>)jXw&_`im45B>E^1!kRF!qM^ZF{_lf5eR2%>mcFC*{7u?O7Tg~*6huIfE*ni zeI>rOl?930-3Mw7ztH*UFT=yLGd4H$bvoXpTWhQhkDe-iOQ&z~{MDQ_pXSp=tM@TK zVIN9aHa~{T9v7DGJcpP;|2=vchmw*KQTOVyB&GWcVX~modyN{(w{MR?z_q-*ENL8t z9(0v^Yhb}qDwsPFSiMXFOvc+hx1+2#mPdHG7rM*_eFyBi+ko|#C(`jYoeV+Dg>uv` zlepE|W|Yp?t)OGMw6U=Pg<{P#A>24C?6-n9M88BYlK?ejH-a_=lfs2^s-=k%y1Y*& z>pzk_Y$Cf|n|#>joi5n!=x%K8?9A_w9%V8#IY|=GEdlGImJ2Cw3a-E26xr=0#hnWP zJu@|zf%ehGhT^?q?hm%-o)M6&@>KWQdAqj7_pM$YxBfVD0zu%DA%X^#b|5RVL^T~Q z3g#M$S%{4Y6nv>46Hi?f&Y!zwCTen$5duhdMx7cV^aeuV+S+S1$6`$BZ_{<}I2PRw z{`=8yEt;y!%8aTUDWysZ3uSfMxxo@FhGXxrJieG52v3Z;iR@fcztSL|O7g)N_ss7f zqZhQ=0gi+q;ldK$pR;wvbH&`adfjj6oDAQ=Tpd7?r85jkBjEN#Ox+Hgx(VE!L+tUd zG_+B#x?Sg52n-Dkt5u2LtU@He8eRhL{$L{e3_Bo$Bs*_N0%?UTamWs~Fuwq={Jl0c zk@hf;6(F~N9wu~rd>qvJ3fFlC2M2EJIhWF{$iB<%{;4ewRS$Rfis_4$PbJd-PA|K5 zGRuBSBEh+t0$Xh?&L|KF&QBdyk8^}rd#tn*xmo8ouez;~v)et6|%Nq=L;!%L% zA015s&=9^l+5`y^O4|jtY!=yU4h{~dfE6IsR{ofV)HdVKMezGTsuiZho9MVyL)6mo zv8`>c*mC^Y7(u9 zlp^;e557VY4DlLJc5|vg?yL{A509$Y-n@~>WG)m$(W0Px8`G$WUt++h+7EX%{aBq2XCP=!itxbrPMo%4C8y@N0Xde15&&A2n@#p4dpaN)c;htV9wlVt> zOh^@;tGWM!<+RMvhokvwr6F_vuHypUGC^f|s321M5ozB_J{wXb<3-7@O~FS}xG!BN z*tmNN1DZcW`Ohj%66O`D@woae{-%eSX}3HfF%-LUMIjVhL}@=nxY`L6U3i_}lG07V zDk-GT^riEY7Pa($2HibVLC5+;*>`iEfWG(fA4>@@wjMRG{2!i(6^m3ahq57&{Q;`u#2{}kgct)1Iz%r^|MvxH8flwr&^$y3U^Uc zJ99u5$dXXqR0@KTXAnWhef@=vn65GEj;^j2t|TQ?vO3Hp_x>~GN?DKOloXZ=k~z$e zAn2kY78es6xQZwV7vTHkBkRU1l-RN!&z~R@@JCu;b*e74yGKbpr8e&maq7QA66&>i zMIZckJfEUz@mSk&&14S`oT#I)c)9yq(n>Z|_ArE6bGY*I^6^OryRX>yZDz_ml*`r0 z5wr&)&FtsSo(&q_Jf`-~)#vJ=sw&G6At(mPIl{{x{+U2xqkQPLfFPSHrJj0re>HO>F`~B}eSNV9gVE0&_I^oA z!_~7%TVXsNI z-14aI?D_NJ_X$+pf%MV=^vXe2Mw$c`;MG$UnP1ExZjC6NZHEXgyT(<4LG^7_l~~O> z<%6@KE-*z)Yi&ZY8FsC>HALtOxv@@8_p_n2a99z4_5(k{G^(Wu6FE*zhgn-YZ#qkH zYyuqtde++?sW94Uhh-VMJL=oy;&m+$xK*5zyrZL&@VjU0)s3SwpJx!I zQTGuU!WCb+2;|UdGRGz+z`Im%GJm{I1ZSD62`F#T9QG^^X8{q z4JuK#41Y~+8l=rW08P4jyyt|@dZR=|If&^RHP7G&;XYPORm5U#%%uNGhVf59ScCn| z06QrWHkyD70-?bC_cs}2L=Z5R=>CR;@xA5c7a#tXA*rmV^huzOu|fslmOl#=UElK% z(Yir+rlHZ@-mYBoCATSe;x-i<_WeO$l&(T^4+lrVuSFn){oeseCGb8#$8!aWGEGVg zv*93uH`(`R{IybmQq5~VB4C+q+PEgd;7>)A79{i2ajZPz6`ix_eHs1k`Lc9}${kiR z=!;sLZZKVbT3W0WnEM)!`0US(;GU$D_qfm}GlC8{1qE`p85e>_KuqB>bGZ055}^*A z6FWOKfH%6jj)CmxEY%;ke~OGT*qSb!eT~~6KNqntzk%qs3plpcY`L$m5Cdoo;-XBq z$G(0AX3#nA4Gt(k^7HWlQ5Gmxodwt#tvS~P<^u&T<=-H{A>3vOc<9PXN_KbdR0Q5| zbHu^HyQiior|&Rlw&Ctyf6Ma#ph-C^h#wWtj@^KeqnOoSi{jJ^@cevlOf!Ztz$_xa z03wy-+MJh~|ATqNqL+Ju-V@CGKuZJ`X8Hb|m0gp;Q9iCiYFI~K*eFVC5DazOT-GoBH<=4P(o%{UMNbhCCiyKXFq~z!D3Al{mZeIP>@VjG+40 z!-+*D!+7#nf8D92JNGj3Uw69f)P|Og% zJIMAlETG5P+Vbw*BJ%_vt>U6Gd3CMd}mxPYI9C9+u9tQy=`c?VDTQb z#36dgMlUx9ks^Ra4i_a;1hs>CvcmkWOsamgiT~%U33BrC@_t>R$C~FfLcBhL2FJ!D zr5a{2vD^8&v>P%FQ!a8H*Bo_jy)7&x?XhP)u@zI*O+?FLr||HASQu@9JV$o=K0K49 zSuQ;QEsTuLH271KlRf-)!j}fb*of(Jutv!(LO^at>HlMuusII?sSmP>4+Z6j``P96 z?$Kvr-~1s`0Jb+N)=a_NVK)p|3itsE0Yumzu%-@d(8al9T(hVHGfheI9N>ZCs3~bF JmdaZO{U0eEPy+w} literal 55946 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 bCNHi#pjoKtYZP~x_+D8-_2^?clPmuRK7)D4 diff --git a/contracts/docs/plantuml/oethOracles.puml b/contracts/docs/plantuml/oethOracles.puml index 53f0dd3ebf..c76fa659d5 100644 --- a/contracts/docs/plantuml/oethOracles.puml +++ b/contracts/docs/plantuml/oethOracles.puml @@ -24,17 +24,17 @@ object "OETHOracleUpdater" as oou <> #DeepSkyBlue { pair: OETH/ETH } -object "frxETHOracleUpdater" as fou <> #DeepSkyBlue { -pair: frxETH/ETH -} - object "OETHOracle" as oetho <> #DeepSkyBlue { pair: OETH/ETH } -object "frxETHOracle" as frxo <> #DeepSkyBlue { -pair: frxETH/ETH -} +' object "frxETHOracleUpdater" as fou <> #DeepSkyBlue { +' pair: frxETH/ETH +' } + +' object "frxETHOracle" as frxo <> #DeepSkyBlue { +' pair: frxETH/ETH +' } object "External\nAccess\nControlled\nAggregator" as clrETH <> { pair: rETH/ETH @@ -44,41 +44,46 @@ object "External\nAccess\nControlled\nAggregator" as clstETH <> { pair: stETH/ETH } +object "FrxEthFraxOracle" as fefo <> { +pair: frxETH/ETH +} + object "OETH/ETH Pool" as coep <> { assets: OETH, ETH } -object "frxETH/OETH Pool" as cfop <> { -assets: frxETH, OETH -} +' object "frxETH/OETH Pool" as cfop <> { +' assets: frxETH, OETH +' } -object "frxETH/ETH Pool" as cfep <> { -assets: frxETH, ETH -} +' object "frxETH/ETH Pool" as cfep <> { +' assets: frxETH, ETH +' } -object "frxETH/WETH Pool" as cfwp <> { -assets: frxETH, WETH -} +' object "frxETH/WETH Pool" as cfwp <> { +' assets: frxETH, WETH +' } -object "OETH/ETH Pool" as boep <> { -assets: OETH, ETH -} +' object "OETH/ETH Pool" as boep <> { +' assets: OETH, ETH +' } vault ..> router : price(asset) router ..> clrETH : latestRoundData() router ..> clstETH : latestRoundData() +router ..> fefo : latestRoundData() vault <.. oou : price() oetho <.. oou : addPrice() -oou ...> coep : price_oracle() -oou ...> cfop : price_oracle() -oou ...> boep : price_oracle() - -router ..> frxo : latestRoundData() -fou ..> frxo : addPrice() -fou ...> cfep : price_oracle() -fou ...> cfwp : price_oracle() +oou ..> coep : price_oracle() +' oou ...> cfop : price_oracle() +' oou ...> boep : price_oracle() + +' router ..> frxo : latestRoundData() +' fou ..> frxo : addPrice() +' fou ...> cfep : price_oracle() +' fou ...> cfwp : price_oracle() ' object "FrxEthFraxOracle" as fo <> { From 8e03c2d8753fa151ce6d227541d54ec7aa9ed59e Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Thu, 5 Oct 2023 08:58:18 +1100 Subject: [PATCH 12/23] Only get OETH floor price from the vault if the market price is < 0.995 --- .../contracts/oracle/OETHOracleUpdater.sol | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol index e4069e422c..a206533822 100644 --- a/contracts/contracts/oracle/OETHOracleUpdater.sol +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -13,6 +13,11 @@ import { ICurvePool } from "../strategies/ICurvePool.sol"; * @author Origin Protocol Inc */ contract OETHOracleUpdater is Governable { + /// @notice Max OETH price when redeeming via the vault + /// The vault charges a 0.5% withdraw fee and the oracle prices + /// of the collateral assets are capped at 1 so the max price is 0.995 + uint256 public constant MAX_VAULT_PRICE = 995e15; + ICurvePool public immutable curvePool; IVault public immutable vault; @@ -53,21 +58,29 @@ contract OETHOracleUpdater is Governable { uint256 marketPrice ) { - // Get price from the Vault - vaultPrice = vault.floorPrice(); - // Get price from the Curve pool marketPrice = curvePool.price_oracle(); - // TODO check if the data is bad - - // Return the market price with the Vault price as the floor price - if (marketPrice > vaultPrice) { + // If market price is about the 0.5% redeem fee + if (marketPrice > MAX_VAULT_PRICE) { answer = marketPrice; + // Avoid getting the vault price as this is gas intensive + // its not going to be higher than 0.995 with a 0.5% withdraw fee + vaultPrice = MAX_VAULT_PRICE; } else { - answer = vaultPrice; + // Get price from the Vault + vaultPrice = vault.floorPrice(); + + // Return the market price with the Vault price as the floor price + if (marketPrice > vaultPrice) { + answer = marketPrice; + } else { + answer = vaultPrice; + } } + // TODO check if the data is bad + // Cap the OETH/ETH price at 1 if (answer > 1e18) { answer = 1e18; From d08572ee85890a79478438c5387abfbd53a48ca6 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 10:17:58 +1100 Subject: [PATCH 13/23] Updated OETH Oracle Natspec and code comments --- contracts/contracts/oracle/OETHOracle.sol | 6 +- .../contracts/oracle/OETHOracleUpdater.sol | 56 +++++++++++++------ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/contracts/contracts/oracle/OETHOracle.sol b/contracts/contracts/oracle/OETHOracle.sol index 84cb3bb91a..6092ce5244 100644 --- a/contracts/contracts/oracle/OETHOracle.sol +++ b/contracts/contracts/oracle/OETHOracle.sol @@ -2,9 +2,6 @@ pragma solidity ^0.8.0; import { BaseOracle } from "./BaseOracle.sol"; -import { IOracleReceiver } from "./IOracleReceiver.sol"; -import { AggregatorV3Interface } from "../interfaces/chainlink/AggregatorV3Interface.sol"; -import { Governable } from "../governance/Governable.sol"; /** * @title OETH Oracle @@ -14,5 +11,8 @@ import { Governable } from "../governance/Governable.sol"; contract OETHOracle is BaseOracle { string public constant override description = "OETH / ETH"; + /** + * @param _oracleUpdater Address of the contract that is authorized to add prices + */ constructor(address _oracleUpdater) BaseOracle(_oracleUpdater) {} } diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol index a206533822..58dc9f2431 100644 --- a/contracts/contracts/oracle/OETHOracleUpdater.sol +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -9,16 +9,19 @@ import { ICurvePool } from "../strategies/ICurvePool.sol"; /** * @title OETH Oracle Updater - * @notice Gathers OETH pricing data and updates the OEHOracle contract. + * @notice Gathers on-chain OETH pricing data and updates the OETHOracle contract. * @author Origin Protocol Inc */ contract OETHOracleUpdater is Governable { - /// @notice Max OETH price when redeeming via the vault - /// The vault charges a 0.5% withdraw fee and the oracle prices - /// of the collateral assets are capped at 1 so the max price is 0.995 + /// @notice Max OETH price when redeeming via the vault to 18 decimals. + /// The vault charges a 0.5% withdraw fee and the oracle prices of + /// the vault collateral assets are capped at 1 so the max price is 0.995. + /// @dev A new OETHOracleUpdater needs to be deployed if the vault withdraw fee changes. uint256 public constant MAX_VAULT_PRICE = 995e15; + /// @notice The OETH/ETH Curve pool ICurvePool public immutable curvePool; + /// @notice The OETH Vault IVault public immutable vault; struct OracleUpdaterConfig { @@ -28,14 +31,18 @@ contract OETHOracleUpdater is Governable { event AddPrice(uint256 answer, uint256 vaultPrice, uint256 marketPrice); + /** + * @param _vault Address of the OETH Vault + * @param _curvePool Address of the OETH/ETH Curve pool + */ constructor(address _vault, address _curvePool) Governable() { curvePool = ICurvePool(_curvePool); vault = IVault(_vault); } - /// @notice Adds new Oracle price to an Oracle + /// @notice Adds a new on-chain, aggregated OETH/ETH price to 18 decimals to the specified Oracle. /// @dev Callable by anyone as the prices are sourced and aggregated on-chain. - /// @param oracle Address of the Oracle that has this contract set as its priceSource + /// @param oracle Address of the Oracle that has authorized this contract to add prices. function addPrice(IOracleReceiver oracle) external { ( uint256 answer, @@ -45,10 +52,14 @@ contract OETHOracleUpdater is Governable { emit AddPrice(answer, vaultPrice, marketPrice); + // Add the new aggregated price to the oracle. // Authorization is handled on Oracle side oracle.addPrice(uint128(answer)); } + /** + * @dev Gets the OETH/ETH market price, vault floor price and aggregates to a OETH/ETH price to 18 decimals. + */ function _getPrices() internal view @@ -58,37 +69,50 @@ contract OETHOracleUpdater is Governable { uint256 marketPrice ) { - // Get price from the Curve pool - marketPrice = curvePool.price_oracle(); + // Get the aggregated market price from on-chain DEXs + marketPrice = _getMarketPrice(); - // If market price is about the 0.5% redeem fee + // If market price is above the vault price with the withdraw fee if (marketPrice > MAX_VAULT_PRICE) { answer = marketPrice; - // Avoid getting the vault price as this is gas intensive + // Avoid getting the vault price as this is gas intensive. // its not going to be higher than 0.995 with a 0.5% withdraw fee vaultPrice = MAX_VAULT_PRICE; } else { - // Get price from the Vault + // Get the price from the Vault. This includes the withdraw fee + // and the vault collateral assets priced using oracles vaultPrice = vault.floorPrice(); - // Return the market price with the Vault price as the floor price if (marketPrice > vaultPrice) { + // Return the market price with the Vault price as the floor price answer = marketPrice; } else { + // Return the vault price answer = vaultPrice; } } - // TODO check if the data is bad - // Cap the OETH/ETH price at 1 if (answer > 1e18) { answer = 1e18; } } - /// @notice Get the latest price from the Vault and Curve pool - /// @return answer is the latest Oracle price + /** + * @dev Gets the market prices from on-chain DEXs. + * Currently, this is Curve's OETH/ETH Exponential Moving Average (EMA) oracle. + * This can be expended later to support aggregation across multiple on-chain DEXs. + * For example, other OETH Curve, Balancer or Uniswap pools. + */ + function _getMarketPrice() internal view returns (uint256 marketPrice) { + // Get the EMA oracle price from the Curve pool + marketPrice = curvePool.price_oracle(); + } + + /// @notice Get the latest prices from the OETH Vault and OETH/ETH Curve pool to 18 decimals. + /// @return answer the aggregated OETH/ETH price + /// @return vaultPrice the vault floor price if the market price is below the max vault floor price + /// @return marketPrice the latest market price function getPrices() external view From 0805d43f62c9343d66ff3a9381ae4f716e8b1b5b Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 10:59:18 +1100 Subject: [PATCH 14/23] Update Vault Natspec for floorPrice --- contracts/contracts/interfaces/IVault.sol | 2 -- contracts/contracts/vault/VaultCore.sol | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/contracts/contracts/interfaces/IVault.sol b/contracts/contracts/interfaces/IVault.sol index 4a8166e40c..7e4d1ce83e 100644 --- a/contracts/contracts/interfaces/IVault.sol +++ b/contracts/contracts/interfaces/IVault.sol @@ -122,8 +122,6 @@ interface IVault { function floorPrice() external view returns (uint256); - function floorPrice2() external view returns (uint256); - function withdrawAllFromStrategy(address _strategyAddr) external; function withdrawAllFromStrategies() external; diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index db3fd1527d..665d3bb943 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -565,10 +565,13 @@ contract VaultCore is VaultInitializer { ****************************************/ /** - * @notice The amount of ETH value for redeeming 1 OETH. - * This is the minimum price for OETH. The better price is - * is usually achieved by swapping OETH for ETH - * with the Curve OETH/ETH pool. + * @notice The value (USD or ETH) of the collateral assets received from + * redeeming 1 Origin Token (OUSD or OETH) from the Vault. + * This is the minimum price for the OToken. A better price is usually achieved by + * swapping the OToken on the Curve pool used for Automated Market Operations (AMO). + * For OETH, that's the Curve OETH/ETH pool. + * For OUSD, that's the Curve OUSD/3Crv pool. + * @param price the price to 18 decimals. */ function floorPrice() external view returns (uint256 price) { // Get the assets for redeeming 1 OETH @@ -577,11 +580,15 @@ contract VaultCore is VaultInitializer { // For each of the redeemed assets for (uint256 i = 0; i < redeemAssets.length; ++i) { - // Sum the value of the asset in ETH = asset amount * oracle price + // Sum the value of the vault asset = asset amount * oracle price + // For OUSD's USDC and USDT assets that are to 6 decimals, the oracle + // price is to 18 decimals, so we do not need to scale them up to 18 decimals price += redeemAssets[i] * IOracle(priceProvider).price(allAssets[i]); } + + // scale back down to 18 decimals as we multiplied two 18 decimals numbers to get the value. price = price / 1e18; } From 7e21054a5affa4cafd09d96500e4b321ea01cc0e Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 11:54:04 +1100 Subject: [PATCH 15/23] fixed OETH Oracle fork tests --- ...th_vault_upgrade.js => 081_oeth_oracle.js} | 4 +- contracts/test/_fixture.js | 5 +++ contracts/test/oracle/oracle.fork-test.js | 37 +++++++++++++++++-- 3 files changed, 41 insertions(+), 5 deletions(-) rename contracts/deploy/{076_oeth_vault_upgrade.js => 081_oeth_oracle.js} (94%) diff --git a/contracts/deploy/076_oeth_vault_upgrade.js b/contracts/deploy/081_oeth_oracle.js similarity index 94% rename from contracts/deploy/076_oeth_vault_upgrade.js rename to contracts/deploy/081_oeth_oracle.js index 908e8ffc30..1bca8e3e50 100644 --- a/contracts/deploy/076_oeth_vault_upgrade.js +++ b/contracts/deploy/081_oeth_oracle.js @@ -6,7 +6,7 @@ const { module.exports = deploymentWithGovernanceProposal( { - deployName: "076_oeth_vault_upgrade", + deployName: "081_oeth_oracle", forceDeploy: false, // forceSkip: true, reduceQueueTime: false, @@ -54,7 +54,7 @@ module.exports = deploymentWithGovernanceProposal( // 4. Governance Actions return { - name: "Upgrade the OETH Vault with price Oracle.", + name: "Upgrade the OETH Vault and deploy the OETH Oracle and Oracle Updater.", actions: [ // 1. Upgrade the OETH Vault proxy to the new core vault implementation { diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 160fcec526..75d6733504 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -147,6 +147,9 @@ const defaultFixture = deployments.createFixture(async () => { isFork ? "OETHOracleRouter" : "OracleRouter" ); + const oethOracle = await ethers.getContract("OETHOracle"); + const oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); + let usdt, dai, tusd, @@ -524,6 +527,8 @@ const defaultFixture = deployments.createFixture(async () => { compoundStrategy, oracleRouter, oethOracleRouter, + oethOracle, + oethOracleUpdater, // Assets usdt, dai, diff --git a/contracts/test/oracle/oracle.fork-test.js b/contracts/test/oracle/oracle.fork-test.js index cc71ba5a48..a18a80e9d5 100644 --- a/contracts/test/oracle/oracle.fork-test.js +++ b/contracts/test/oracle/oracle.fork-test.js @@ -3,10 +3,11 @@ const { parseUnits, formatUnits } = require("ethers/lib/utils"); const { loadDefaultFixture } = require("../_fixture"); const { isCI } = require("../helpers"); +const { impersonateAndFund } = require("../../utils/signers.js"); const log = require("../../utils/logger")("test:fork:oracles"); -describe("ForkTest: Oracles Routers", function () { +describe("ForkTest: Oracles", function () { this.timeout(0); // Retry up to 3 times on CI @@ -27,7 +28,7 @@ describe("ForkTest: Oracles Routers", function () { const price = await oethOracleRouter.price(reth.address); expect(price).to.gte(parseUnits("1083", 15)); - expect(price).to.lt(parseUnits("109", 16)); + expect(price).to.lt(parseUnits("110", 16)); }); it("should get frxETH price", async () => { const { frxETH } = fixture; @@ -59,6 +60,17 @@ describe("ForkTest: Oracles Routers", function () { }); }); describe("OETH Oracle", () => { + it("Should get price from OETH Oracle Updater", async () => { + const { oethOracleUpdater } = fixture; + + const prices = await oethOracleUpdater.getPrices(); + + expect(prices.answer).to.be.gte(parseUnits("0.99")); + expect(prices.answer).to.be.lt(parseUnits("1")); + expect(prices.vaultPrice).to.be.lte(parseUnits("0.995")); + expect(prices.marketPrice).to.be.gte(parseUnits("0.99")); + expect(prices.marketPrice).to.be.lt(parseUnits("1.01")); + }); it("Should add new OETH Oracle price", async () => { const { oethOracle, oethOracleUpdater } = fixture; @@ -70,7 +82,7 @@ describe("ForkTest: Oracles Routers", function () { log(`OETH price: ${formatUnits(data.answer, 18)}`); expect(data.answer).to.be.gte(parseUnits("0.99")); - expect(data.answer).to.be.lte(parseUnits("1.01")); + expect(data.answer).to.be.lte(parseUnits("1.0001")); expect(data.roundId).to.be.eq(0); }); it("Should get gas usage of latestRoundData", async () => { @@ -96,5 +108,24 @@ describe("ForkTest: Oracles Routers", function () { log(`Oracle answeredInRound: ${data.answeredInRound}`); expect(data.roundId).to.be.eq(1); }); + it("Should not add OETH Oracle price by anyone", async () => { + const { oethOracle, anna, strategist, governor, harvester, oethVault } = + fixture; + + const harvesterSigner = await impersonateAndFund(harvester.address); + const oethVaultSigner = await impersonateAndFund(oethVault.address); + + for (const signer of [ + anna, + strategist, + governor, + harvesterSigner, + oethVaultSigner, + ]) { + await expect( + oethOracle.connect(signer).addPrice(parseUnits("999", 15)) + ).to.revertedWith("OnlyOracleUpdater"); + } + }); }); }); From f52cd401eb1ac52b66084d176092d238f12be89e Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 12:56:10 +1100 Subject: [PATCH 16/23] fix unit tests after merge --- contracts/test/_fixture.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index 09e5482dc8..a65caaa82f 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -148,9 +148,6 @@ const defaultFixture = deployments.createFixture(async () => { isFork ? "OETHOracleRouter" : "OracleRouter" ); - const oethOracle = await ethers.getContract("OETHOracle"); - const oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); - let usdt, dai, tusd, @@ -221,7 +218,9 @@ const defaultFixture = deployments.createFixture(async () => { convexEthMetaStrategy, fluxStrategy, vaultValueChecker, - oethVaultValueChecker; + oethVaultValueChecker, + oethOracleUpdater, + oethOracle; if (isFork) { usdt = await ethers.getContractAt(usdtAbi, addresses.mainnet.USDT); @@ -349,6 +348,9 @@ const defaultFixture = deployments.createFixture(async () => { vaultValueChecker = await ethers.getContract("VaultValueChecker"); oethVaultValueChecker = await ethers.getContract("OETHVaultValueChecker"); + + oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); + oethOracle = await ethers.getContract("OETHOracle"); } else { usdt = await ethers.getContract("MockUSDT"); dai = await ethers.getContract("MockDAI"); From d8e34a1bd59405b41a9d2d84c0e0373940fb2216 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 12:58:14 +1100 Subject: [PATCH 17/23] regenerated OETH Oracle contract diagrams --- contracts/docs/OETHOracleHierarchy.svg | 36 ++++---- contracts/docs/OETHOracleSquashed.svg | 4 +- contracts/docs/OETHOracleUpdaterHierarchy.svg | 88 +++++++++---------- contracts/docs/OETHOracleUpdaterSquashed.svg | 56 ++++++------ 4 files changed, 93 insertions(+), 91 deletions(-) diff --git a/contracts/docs/OETHOracleHierarchy.svg b/contracts/docs/OETHOracleHierarchy.svg index 382a321912..103eb44ed0 100644 --- a/contracts/docs/OETHOracleHierarchy.svg +++ b/contracts/docs/OETHOracleHierarchy.svg @@ -9,65 +9,65 @@ UmlClassDiagram - + -7 +20 Governable ../contracts/governance/Governable.sol - + -193 +228 <<Interface>> AggregatorV3Interface ../contracts/interfaces/chainlink/AggregatorV3Interface.sol - + -93 +115 <<Abstract>> BaseOracle ../contracts/oracle/BaseOracle.sol - + -93->7 +115->20 - + -93->193 +115->228 - + -95 +117 <<Interface>> IOracleReceiver ../contracts/oracle/IOracleReceiver.sol - + -93->95 +115->117 - + -96 +118 OETHOracle ../contracts/oracle/OETHOracle.sol - + -96->93 +118->115 diff --git a/contracts/docs/OETHOracleSquashed.svg b/contracts/docs/OETHOracleSquashed.svg index cd4334e008..bc79f51a56 100644 --- a/contracts/docs/OETHOracleSquashed.svg +++ b/contracts/docs/OETHOracleSquashed.svg @@ -9,9 +9,9 @@ UmlClassDiagram - + -96 +118 OETHOracle ../contracts/oracle/OETHOracle.sol diff --git a/contracts/docs/OETHOracleUpdaterHierarchy.svg b/contracts/docs/OETHOracleUpdaterHierarchy.svg index 4aebafe97f..d3aa84d47f 100644 --- a/contracts/docs/OETHOracleUpdaterHierarchy.svg +++ b/contracts/docs/OETHOracleUpdaterHierarchy.svg @@ -9,151 +9,151 @@ UmlClassDiagram - + -7 +20 Governable ../contracts/governance/Governable.sol - + -40 +58 <<Interface>> IVault ../contracts/interfaces/IVault.sol - + -186 +212 VaultStorage ../contracts/vault/VaultStorage.sol - + -40->186 +58->212 - + -95 +117 <<Interface>> IOracleReceiver ../contracts/oracle/IOracleReceiver.sol - + -97 +119 OETHOracleUpdater ../contracts/oracle/OETHOracleUpdater.sol - + -97->7 +119->20 - + -97->40 +119->58 - + -97->95 +119->117 - + -154 +179 <<Interface>> ICurvePool ../contracts/strategies/ICurvePool.sol - + -97->154 +119->179 - + -166 +191 OUSD ../contracts/token/OUSD.sol - + -166->7 +191->20 - + -173 +199 <<Abstract>> Initializable ../contracts/utils/Initializable.sol - + -166->173 +191->199 - + -176 +202 <<Abstract>> InitializableERC20Detailed ../contracts/utils/InitializableERC20Detailed.sol - + -166->176 +191->202 - + -348 +391 <<Interface>> IERC20 ../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - + -176->348 +202->391 - + -186->7 +212->20 - + -186->166 +212->191 - + -186->173 +212->199 diff --git a/contracts/docs/OETHOracleUpdaterSquashed.svg b/contracts/docs/OETHOracleUpdaterSquashed.svg index 9c6377af72..ad2f350a3f 100644 --- a/contracts/docs/OETHOracleUpdaterSquashed.svg +++ b/contracts/docs/OETHOracleUpdaterSquashed.svg @@ -4,35 +4,37 @@ - - + + UmlClassDiagram - - + + -97 - -OETHOracleUpdater -../contracts/oracle/OETHOracleUpdater.sol - -Private: -   governorPosition: bytes32 <<Governable>> -   pendingGovernorPosition: bytes32 <<Governable>> -   reentryStatusPosition: bytes32 <<Governable>> -Public: -   _NOT_ENTERED: uint256 <<Governable>> -   _ENTERED: uint256 <<Governable>> -   curvePool: ICurvePool <<OETHOracleUpdater>> -   vault: IVault <<OETHOracleUpdater>> - -Internal: -    _governor(): (governorOut: address) <<Governable>> -    _pendingGovernor(): (pendingGovernor: address) <<Governable>> -    _setGovernor(newGovernor: address) <<Governable>> -    _setPendingGovernor(newGovernor: address) <<Governable>> -    _changeGovernor(_newGovernor: address) <<Governable>> -    _getPrices(): (answer: uint256, vaultPrice: uint256, marketPrice: uint256) <<OETHOracleUpdater>> +119 + +OETHOracleUpdater +../contracts/oracle/OETHOracleUpdater.sol + +Private: +   governorPosition: bytes32 <<Governable>> +   pendingGovernorPosition: bytes32 <<Governable>> +   reentryStatusPosition: bytes32 <<Governable>> +Public: +   _NOT_ENTERED: uint256 <<Governable>> +   _ENTERED: uint256 <<Governable>> +   MAX_VAULT_PRICE: uint256 <<OETHOracleUpdater>> +   curvePool: ICurvePool <<OETHOracleUpdater>> +   vault: IVault <<OETHOracleUpdater>> + +Internal: +    _governor(): (governorOut: address) <<Governable>> +    _pendingGovernor(): (pendingGovernor: address) <<Governable>> +    _setGovernor(newGovernor: address) <<Governable>> +    _setPendingGovernor(newGovernor: address) <<Governable>> +    _changeGovernor(_newGovernor: address) <<Governable>> +    _getPrices(): (answer: uint256, vaultPrice: uint256, marketPrice: uint256) <<OETHOracleUpdater>> +    _getMarketPrice(): (marketPrice: uint256) <<OETHOracleUpdater>> External:    transferGovernance(_newGovernor: address) <<onlyGovernor>> <<Governable>>    claimGovernance() <<Governable>> From a393ffd4e63c8355196f4bfcecbd8f38e892cabf Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 13:29:57 +1100 Subject: [PATCH 18/23] Updated Oracle docs --- contracts/contracts/oracle/README.md | 14 +- contracts/docs/OETHOracleHierarchy.svg | 85 ++++----- contracts/docs/OETHOracleRouterHierarchy.svg | 94 ++++------ contracts/docs/OETHOracleUpdaterHierarchy.svg | 161 ------------------ contracts/docs/generate.sh | 6 +- 5 files changed, 71 insertions(+), 289 deletions(-) delete mode 100644 contracts/docs/OETHOracleUpdaterHierarchy.svg diff --git a/contracts/contracts/oracle/README.md b/contracts/contracts/oracle/README.md index d7107be210..5c4feffdf3 100644 --- a/contracts/contracts/oracle/README.md +++ b/contracts/contracts/oracle/README.md @@ -20,24 +20,18 @@ ![OETH Oracle Hierarchy](../../docs/OETHOracleHierarchy.svg) -### Squashed +### OETHOracle Squashed ![OETH Oracle Squashed](../../docs/OETHOracleSquashed.svg) -### Storage +### OETHOracle Storage ![OETH Oracle Storage](../../docs/OETHOracleStorage.svg) -## OETH Oracle Updater - -### Hierarchy - -![OETH Oracle Updater Hierarchy](../../docs/OETHOracleUpdaterHierarchy.svg) - -### Squashed +### OETHOracleUpdater Squashed ![OETH Oracle Updater Squashed](../../docs/OETHOracleUpdaterSquashed.svg) -### Storage +### OETHOracleUpdater Storage ![OETH Oracle Updater Storage](../../docs/OETHOracleUpdaterStorage.svg) diff --git a/contracts/docs/OETHOracleHierarchy.svg b/contracts/docs/OETHOracleHierarchy.svg index 103eb44ed0..bb1363581e 100644 --- a/contracts/docs/OETHOracleHierarchy.svg +++ b/contracts/docs/OETHOracleHierarchy.svg @@ -4,72 +4,57 @@ - - + + UmlClassDiagram - + 20 - -Governable -../contracts/governance/Governable.sol - - - -228 - -<<Interface>> -AggregatorV3Interface -../contracts/interfaces/chainlink/AggregatorV3Interface.sol + +Governable +../contracts/governance/Governable.sol - + 115 - -<<Abstract>> -BaseOracle -../contracts/oracle/BaseOracle.sol + +<<Abstract>> +BaseOracle +../contracts/oracle/BaseOracle.sol - -115->20 - - - - -115->228 - - - - - -117 - -<<Interface>> -IOracleReceiver -../contracts/oracle/IOracleReceiver.sol - - - -115->117 - - +115->20 + + - + 118 - -OETHOracle -../contracts/oracle/OETHOracle.sol + +OETHOracle +../contracts/oracle/OETHOracle.sol - + 118->115 - - + + + + + +119 + +OETHOracleUpdater +../contracts/oracle/OETHOracleUpdater.sol + + + +119->20 + + diff --git a/contracts/docs/OETHOracleRouterHierarchy.svg b/contracts/docs/OETHOracleRouterHierarchy.svg index 1eefc3d304..d0122deb8e 100644 --- a/contracts/docs/OETHOracleRouterHierarchy.svg +++ b/contracts/docs/OETHOracleRouterHierarchy.svg @@ -4,78 +4,44 @@ - - + + UmlClassDiagram - - + + -30 - -<<Interface>> -IOracle -../contracts/interfaces/IOracle.sol +121 + +<<Abstract>> +OracleRouterBase +../contracts/oracle/OracleRouter.sol - + -167 - -<<Interface>> -AggregatorV3Interface -../contracts/interfaces/chainlink/AggregatorV3Interface.sol +122 + +OracleRouter +../contracts/oracle/OracleRouter.sol - - -80 - -<<Abstract>> -OracleRouterBase -../contracts/oracle/OracleRouter.sol - - + -80->30 - - - - - -80->167 - - - - - -81 - -OracleRouter -../contracts/oracle/OracleRouter.sol +122->121 + + - - -81->80 - - - - - -82 - -OETHOracleRouter -../contracts/oracle/OracleRouter.sol - - - -82->167 - - + + +123 + +OETHOracleRouter +../contracts/oracle/OracleRouter.sol - - -82->81 - - + + +123->122 + + diff --git a/contracts/docs/OETHOracleUpdaterHierarchy.svg b/contracts/docs/OETHOracleUpdaterHierarchy.svg deleted file mode 100644 index d3aa84d47f..0000000000 --- a/contracts/docs/OETHOracleUpdaterHierarchy.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - -UmlClassDiagram - - - -20 - -Governable -../contracts/governance/Governable.sol - - - -58 - -<<Interface>> -IVault -../contracts/interfaces/IVault.sol - - - -212 - -VaultStorage -../contracts/vault/VaultStorage.sol - - - -58->212 - - - - - -117 - -<<Interface>> -IOracleReceiver -../contracts/oracle/IOracleReceiver.sol - - - -119 - -OETHOracleUpdater -../contracts/oracle/OETHOracleUpdater.sol - - - -119->20 - - - - - -119->58 - - - - - -119->117 - - - - - -179 - -<<Interface>> -ICurvePool -../contracts/strategies/ICurvePool.sol - - - -119->179 - - - - - -191 - -OUSD -../contracts/token/OUSD.sol - - - -191->20 - - - - - -199 - -<<Abstract>> -Initializable -../contracts/utils/Initializable.sol - - - -191->199 - - - - - -202 - -<<Abstract>> -InitializableERC20Detailed -../contracts/utils/InitializableERC20Detailed.sol - - - -191->202 - - - - - -391 - -<<Interface>> -IERC20 -../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - - - -202->391 - - - - - -212->20 - - - - - -212->191 - - - - - -212->199 - - - - - diff --git a/contracts/docs/generate.sh b/contracts/docs/generate.sh index 1894a6dfb9..321bc38c67 100644 --- a/contracts/docs/generate.sh +++ b/contracts/docs/generate.sh @@ -33,15 +33,13 @@ sol2uml .. -s -d 0 -b Governor -o GovernorSquashed.svg sol2uml storage .. -c Governor -o GovernorStorage.svg # contracts/oracles -sol2uml .. -v -hv -hf -he -hs -hl -b OETHOracleRouter -o OETHOracleRouterHierarchy.svg +sol2uml .. -v -hv -hf -he -hs -hl -hi -b OETHOracleRouter -o OETHOracleRouterHierarchy.svg sol2uml .. -s -d 0 -b OETHOracleRouter -o OETHOracleRouterSquashed.svg sol2uml storage .. -c OETHOracleRouter -o OETHOracleRouterStorage.svg -sol2uml .. -v -hv -hf -he -hs -hl -b OETHOracle -o OETHOracleHierarchy.svg +sol2uml .. -v -hv -hf -he -hs -hl -hi -b OETHOracle,OETHOracleUpdater -o OETHOracleHierarchy.svg sol2uml .. -s -d 0 -b OETHOracle -o OETHOracleSquashed.svg sol2uml storage .. -c OETHOracle -o OETHOracleStorage.svg - -sol2uml .. -v -hv -hf -he -hs -hl -b OETHOracleUpdater -o OETHOracleUpdaterHierarchy.svg sol2uml .. -s -d 0 -b OETHOracleUpdater -o OETHOracleUpdaterSquashed.svg sol2uml storage .. -c OETHOracleUpdater -o OETHOracleUpdaterStorage.svg From 2bd9e0a956583dc2525e7bd3d5d62f08164d42d5 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 13:30:56 +1100 Subject: [PATCH 19/23] Fix Slither error --- contracts/contracts/vault/VaultStorage.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/contracts/vault/VaultStorage.sol b/contracts/contracts/vault/VaultStorage.sol index 066754e38f..b71179b69c 100644 --- a/contracts/contracts/vault/VaultStorage.sol +++ b/contracts/contracts/vault/VaultStorage.sol @@ -72,6 +72,7 @@ contract VaultStorage is Initializable, Governable { // slither-disable-next-line uninitialized-state mapping(address => Asset) internal assets; /// @dev list of all assets supported by the vault. + // slither-disable-next-line uninitialized-state address[] internal allAssets; // Strategies approved for use by the Vault From 2789e13470ea4a745a60c4d4001c5163d68a68b9 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 17:31:22 +1100 Subject: [PATCH 20/23] Fixed OETHOracle deploy script Added more OETH Oracle fork tests --- contracts/deploy/081_oeth_oracle.js | 14 +++++- contracts/test/oracle/oracle.fork-test.js | 52 +++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/contracts/deploy/081_oeth_oracle.js b/contracts/deploy/081_oeth_oracle.js index 1bca8e3e50..e2eedf3d4a 100644 --- a/contracts/deploy/081_oeth_oracle.js +++ b/contracts/deploy/081_oeth_oracle.js @@ -36,7 +36,7 @@ module.exports = deploymentWithGovernanceProposal( dOETHOracleUpdater.address, ]); const cOETHOracle = await ethers.getContractAt( - "OETHOracleUpdater", + "OETHOracle", dOETHOracle.address ); @@ -62,6 +62,18 @@ module.exports = deploymentWithGovernanceProposal( signature: "upgradeTo(address)", args: [dVaultCore.address], }, + // 2. Accept governance for OETHOracleUpdater + { + contract: cOETHOracleUpdater, + signature: "claimGovernance()", + args: [], + }, + // 3. Accept governance for OETHOracle + { + contract: cOETHOracle, + signature: "claimGovernance()", + args: [], + }, ], }; } diff --git a/contracts/test/oracle/oracle.fork-test.js b/contracts/test/oracle/oracle.fork-test.js index a18a80e9d5..de29d79f0f 100644 --- a/contracts/test/oracle/oracle.fork-test.js +++ b/contracts/test/oracle/oracle.fork-test.js @@ -4,6 +4,7 @@ const { parseUnits, formatUnits } = require("ethers/lib/utils"); const { loadDefaultFixture } = require("../_fixture"); const { isCI } = require("../helpers"); const { impersonateAndFund } = require("../../utils/signers.js"); +const addresses = require("../../utils/addresses"); const log = require("../../utils/logger")("test:fork:oracles"); @@ -60,6 +61,25 @@ describe("ForkTest: Oracles", function () { }); }); describe("OETH Oracle", () => { + it("Should be initialized", async () => { + const { oethOracle, oethOracleUpdater, oethVault } = fixture; + + expect(await oethOracleUpdater.governor()).to.eq( + addresses.mainnet.Timelock + ); + expect(await oethOracleUpdater.MAX_VAULT_PRICE()).to.eq( + parseUnits("0.995") + ); + expect(await oethOracleUpdater.curvePool()).to.eq( + addresses.mainnet.CurveOETHMetaPool + ); + expect(await oethOracleUpdater.vault()).to.eq(oethVault.address); + + expect(await oethOracle.decimals()).to.eq(18); + expect(await oethOracle.version()).to.eq(1); + expect(await oethOracle.oracleUpdater()).to.eq(oethOracleUpdater.address); + expect(await oethOracle.governor()).to.eq(addresses.mainnet.Timelock); + }); it("Should get price from OETH Oracle Updater", async () => { const { oethOracleUpdater } = fixture; @@ -127,5 +147,37 @@ describe("ForkTest: Oracles", function () { ).to.revertedWith("OnlyOracleUpdater"); } }); + it("Should update the oracle updater by the governance timelock", async () => { + const { oethOracle, anna, timelock } = fixture; + + const tx = await oethOracle + .connect(timelock) + .setOracleUpdater(anna.address); + + await expect(tx) + .to.emit(oethOracle, "SetOracleUpdater") + .withArgs(anna.address); + + expect(await oethOracle.oracleUpdater()).to.eq(anna.address); + }); + it("Should not update the oracle updater by the governance timelock", async () => { + const { oethOracle, anna, strategist, governor, harvester, oethVault } = + fixture; + + const harvesterSigner = await impersonateAndFund(harvester.address); + const oethVaultSigner = await impersonateAndFund(oethVault.address); + + for (const signer of [ + anna, + strategist, + governor, + harvesterSigner, + oethVaultSigner, + ]) { + await expect( + oethOracle.connect(signer).setOracleUpdater(anna.address) + ).to.revertedWith("Caller is not the Governor"); + } + }); }); }); From f31dcca402423b03b2e007cf36f689e83ce7d968 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 23:05:50 +1100 Subject: [PATCH 21/23] Added OETH Oracle unit tests --- contracts/contracts/mocks/MockVault.sol | 5 + .../mocks/curve/MockCurveOethEthPool.sol | 20 +++ contracts/contracts/vault/VaultCore.sol | 2 +- contracts/deploy/001_core.js | 45 +++++ contracts/test/_fixture.js | 10 +- contracts/test/oracle/oracle-oeth.js | 165 ++++++++++++++++++ contracts/test/oracle/oracle.js | 4 +- 7 files changed, 242 insertions(+), 9 deletions(-) create mode 100644 contracts/contracts/mocks/curve/MockCurveOethEthPool.sol create mode 100644 contracts/test/oracle/oracle-oeth.js diff --git a/contracts/contracts/mocks/MockVault.sol b/contracts/contracts/mocks/MockVault.sol index b563f9a725..9e45945331 100644 --- a/contracts/contracts/mocks/MockVault.sol +++ b/contracts/contracts/mocks/MockVault.sol @@ -10,6 +10,7 @@ contract MockVault is VaultCore { using StableMath for uint256; uint256 storedTotalValue; + uint256 public override floorPrice; function setTotalValue(uint256 _value) public { storedTotalValue = _value; @@ -42,4 +43,8 @@ contract MockVault is VaultCore { function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor { maxSupplyDiff = _maxSupplyDiff; } + + function setFloorPrice(uint256 _floorPrice) external { + floorPrice = _floorPrice; + } } diff --git a/contracts/contracts/mocks/curve/MockCurveOethEthPool.sol b/contracts/contracts/mocks/curve/MockCurveOethEthPool.sol new file mode 100644 index 0000000000..40ae612150 --- /dev/null +++ b/contracts/contracts/mocks/curve/MockCurveOethEthPool.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { MockCurveAbstractMetapool } from "./MockCurveAbstractMetapool.sol"; +import "../MintableERC20.sol"; + +contract MockCurveOethEthPool is MockCurveAbstractMetapool { + constructor(address[2] memory _coins) + ERC20("Curve.fi Factory Pool: OETH", "OETHCRV-f") + { + coins = _coins; + } + + // Simulate pool's EMA Oracle price + uint256 public price_oracle = 9995e14; // 0.9995 + + function setOraclePrice(uint256 _price) public { + price_oracle = _price; + } +} diff --git a/contracts/contracts/vault/VaultCore.sol b/contracts/contracts/vault/VaultCore.sol index 665d3bb943..cfa4afc241 100644 --- a/contracts/contracts/vault/VaultCore.sol +++ b/contracts/contracts/vault/VaultCore.sol @@ -573,7 +573,7 @@ contract VaultCore is VaultInitializer { * For OUSD, that's the Curve OUSD/3Crv pool. * @param price the price to 18 decimals. */ - function floorPrice() external view returns (uint256 price) { + function floorPrice() external view virtual returns (uint256 price) { // Get the assets for redeeming 1 OETH // This has already had the redeem fee applied uint256[] memory redeemAssets = _calculateRedeemOutputs(1e18); diff --git a/contracts/deploy/001_core.js b/contracts/deploy/001_core.js index 49a38b9a5a..4082032235 100644 --- a/contracts/deploy/001_core.js +++ b/contracts/deploy/001_core.js @@ -1191,6 +1191,50 @@ const deployOUSDSwapper = async () => { await vault.connect(sGovernor).setOracleSlippage(assetAddresses.USDT, 50); }; +/** + * Deploy the OETHOracle contracts. + */ +const deployOETHOracle = async () => { + const { deployerAddr, governorAddr } = await getNamedAccounts(); + const sDeployer = await ethers.provider.getSigner(deployerAddr); + const sGovernor = await ethers.provider.getSigner(governorAddr); + + const oeth = await ethers.getContract("OETHProxy"); + await deployWithConfirmation("MockCurveOethEthPool", [ + [oeth.address, addresses.ETH], + ]); + const curveOethEthPool = await ethers.getContract("MockCurveOethEthPool"); + + const vault = await ethers.getContract("MockVault"); + + await deployWithConfirmation("OETHOracleUpdater", [ + vault.address, + curveOethEthPool.address, + ]); + const cOETHOracleUpdater = await ethers.getContract("OETHOracleUpdater"); + + await withConfirmation( + cOETHOracleUpdater.connect(sDeployer).transferGovernance(governorAddr) + ); + await withConfirmation( + cOETHOracleUpdater + .connect(sGovernor) // Claim governance with governor + .claimGovernance() + ); + + await deployWithConfirmation("OETHOracle", [cOETHOracleUpdater.address]); + const cOETHOracle = await ethers.getContract("OETHOracle"); + + await withConfirmation( + cOETHOracle.connect(sDeployer).transferGovernance(governorAddr) + ); + await withConfirmation( + cOETHOracle + .connect(sGovernor) // Claim governance with governor + .claimGovernance() + ); +}; + const main = async () => { console.log("Running 001_core deployment..."); await deployOracles(); @@ -1216,6 +1260,7 @@ const main = async () => { await deployWOusd(); await deployOETHSwapper(); await deployOUSDSwapper(); + await deployOETHOracle(); console.log("001_core deploy done."); return true; }; diff --git a/contracts/test/_fixture.js b/contracts/test/_fixture.js index a65caaa82f..28329bc87e 100644 --- a/contracts/test/_fixture.js +++ b/contracts/test/_fixture.js @@ -148,6 +148,9 @@ const defaultFixture = deployments.createFixture(async () => { isFork ? "OETHOracleRouter" : "OracleRouter" ); + const oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); + const oethOracle = await ethers.getContract("OETHOracle"); + let usdt, dai, tusd, @@ -218,9 +221,7 @@ const defaultFixture = deployments.createFixture(async () => { convexEthMetaStrategy, fluxStrategy, vaultValueChecker, - oethVaultValueChecker, - oethOracleUpdater, - oethOracle; + oethVaultValueChecker; if (isFork) { usdt = await ethers.getContractAt(usdtAbi, addresses.mainnet.USDT); @@ -348,9 +349,6 @@ const defaultFixture = deployments.createFixture(async () => { vaultValueChecker = await ethers.getContract("VaultValueChecker"); oethVaultValueChecker = await ethers.getContract("OETHVaultValueChecker"); - - oethOracleUpdater = await ethers.getContract("OETHOracleUpdater"); - oethOracle = await ethers.getContract("OETHOracle"); } else { usdt = await ethers.getContract("MockUSDT"); dai = await ethers.getContract("MockDAI"); diff --git a/contracts/test/oracle/oracle-oeth.js b/contracts/test/oracle/oracle-oeth.js new file mode 100644 index 0000000000..709aaf2d66 --- /dev/null +++ b/contracts/test/oracle/oracle-oeth.js @@ -0,0 +1,165 @@ +const { expect } = require("chai"); + +const { loadDefaultFixture } = require("../_fixture"); +const { parseUnits } = require("ethers/lib/utils"); +const { impersonateAndFund } = require("../../utils/signers"); + +/* + * Because the oracle code is so tightly integrated into the vault, + * the actual tests for the core oracle features are just a part of the vault tests. + */ + +const maxVaultPrice = parseUnits("0.995"); + +describe.only("OETH Oracle", async () => { + let fixture; + beforeEach(async () => { + fixture = await loadDefaultFixture(); + }); + const assetAddPrice = async (prices) => { + const { anna, oethOracle, oethOracleUpdater } = fixture; + const { vaultPrice, marketPrice, expectPrice, expectedVaultPrice } = prices; + + const vault = await ethers.getContract("MockVault"); + await vault.setFloorPrice(vaultPrice); + + const curvePool = await ethers.getContract("MockCurveOethEthPool"); + await curvePool.setOraclePrice(marketPrice); + + const tx = await oethOracleUpdater + .connect(anna) + .addPrice(oethOracle.address); + + await expect(tx) + .to.emit(oethOracleUpdater, "AddPrice") + .withArgs(expectPrice, expectedVaultPrice, marketPrice); + + const roundData = await oethOracle.latestRoundData(); + expect(roundData.answer).to.eq(expectPrice); + }; + + describe("Should add price when", () => { + describe("vault > 0.995", () => { + const vaultPrice = parseUnits("0.9956"); + it("curve > 1", async () => { + const marketPrice = parseUnits("1.001"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: parseUnits("1"), + expectedVaultPrice: maxVaultPrice, + }); + }); + it("curve < 1", async () => { + const marketPrice = parseUnits("0.998"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: marketPrice, + expectedVaultPrice: maxVaultPrice, + }); + }); + it("curve < 0.995", async () => { + const marketPrice = parseUnits("0.992"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: vaultPrice, + expectedVaultPrice: vaultPrice, + }); + }); + }); + describe("vault < 0.995", () => { + const vaultPrice = parseUnits("0.9937"); + it("curve > 1", async () => { + const marketPrice = parseUnits("1.001"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: parseUnits("1"), + expectedVaultPrice: maxVaultPrice, + }); + }); + it("curve > 0.995", async () => { + const marketPrice = parseUnits("0.9998"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: marketPrice, + expectedVaultPrice: maxVaultPrice, + }); + }); + it("curve < 0.995 and curve > vault", async () => { + const marketPrice = parseUnits("0.9949"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: marketPrice, + expectedVaultPrice: vaultPrice, + }); + }); + it("curve < 0.995 and curve < vault", async () => { + const marketPrice = parseUnits("0.983"); + + await assetAddPrice({ + marketPrice, + vaultPrice, + expectPrice: vaultPrice, + expectedVaultPrice: vaultPrice, + }); + }); + }); + }); + it("Should not add zero price", async () => { + const { oethOracle, oethOracleUpdater } = fixture; + + const updaterSigner = await impersonateAndFund(oethOracleUpdater.address); + await expect(oethOracle.connect(updaterSigner).addPrice(0)).to.revertedWith( + "NoPriceData" + ); + }); + it("Should not add price by non-updater", async () => { + const { anna, oethOracle } = fixture; + + await expect(oethOracle.connect(anna).addPrice(0)).to.revertedWith( + "OnlyOracleUpdater" + ); + }); + describe("when multiple txs in a block", () => { + beforeEach(async () => { + await ethers.provider.send("evm_setAutomine", [false]); + }); + afterEach(async () => { + await ethers.provider.send("evm_setAutomine", [true]); + }); + it("Should not add a second price in the same block", async () => { + const { oethOracle, oethOracleUpdater } = fixture; + + const updaterSigner = await impersonateAndFund(oethOracleUpdater.address); + // Add a price so there is at leave 1 round before two are added + await oethOracle.connect(updaterSigner).addPrice(parseUnits("0.999")); + + // Mine a block + await ethers.provider.send("evm_mine", []); + + // First add price in block + await oethOracle.connect(updaterSigner).addPrice(parseUnits("0.998")); + // Second add price in block + const tx2 = await oethOracle + .connect(updaterSigner) + .addPrice(parseUnits("0.997")); + + // Mine the two transactions in a new block + await ethers.provider.send("evm_mine", []); + + // ideally this would be revertedWith "AddPriceSameBlock" but it's catching it + await expect(tx2).to.reverted; + }); + }); +}); diff --git a/contracts/test/oracle/oracle.js b/contracts/test/oracle/oracle.js index 943f5b3723..cc0969aa4a 100644 --- a/contracts/test/oracle/oracle.js +++ b/contracts/test/oracle/oracle.js @@ -4,11 +4,11 @@ const { loadDefaultFixture } = require("../_fixture"); const { ousdUnits, setOracleTokenPriceUsd } = require("../helpers"); /* - * Because the oracle code is so tightly intergrated into the vault, + * Because the oracle code is so tightly integrated into the vault, * the actual tests for the core oracle features are just a part of the vault tests. */ -describe("Oracle", async () => { +describe("Vault Oracle", async () => { let fixture; beforeEach(async () => { fixture = await loadDefaultFixture(); From 85bf20e0753147accb1652abf6524983c38dae4e Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Wed, 8 Nov 2023 23:19:29 +1100 Subject: [PATCH 22/23] Removed transferToken from governable behaviour as that is strategy related Added governable behaviour tests to OETH Oracle unit tests --- contracts/test/behaviour/governable.js | 14 -------------- contracts/test/oracle/oracle-oeth.js | 14 +++++++++++++- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/contracts/test/behaviour/governable.js b/contracts/test/behaviour/governable.js index d6eef036b9..bb36d5009b 100644 --- a/contracts/test/behaviour/governable.js +++ b/contracts/test/behaviour/governable.js @@ -1,5 +1,4 @@ const { expect } = require("chai"); -const { daiUnits } = require("../helpers"); /** * @@ -25,19 +24,6 @@ const shouldBehaveLikeGovernable = (context) => { expect(await strategy.connect(signer).isGovernor()).to.be.false; } }); - - it("Should not allow transfer of arbitrary token by non-Governor", async () => { - const { strategist, anna, dai, strategy } = context(); - - const recoveryAmount = daiUnits("800"); - for (const signer of [strategist, anna]) { - // Naughty signer - await expect( - strategy.connect(signer).transferToken(dai.address, recoveryAmount) - ).to.be.revertedWith("Caller is not the Governor"); - } - }); - it("Should allow governor to transfer governance", async () => { const { governor, anna, strategy } = context(); diff --git a/contracts/test/oracle/oracle-oeth.js b/contracts/test/oracle/oracle-oeth.js index 709aaf2d66..1e9fd20110 100644 --- a/contracts/test/oracle/oracle-oeth.js +++ b/contracts/test/oracle/oracle-oeth.js @@ -3,6 +3,7 @@ const { expect } = require("chai"); const { loadDefaultFixture } = require("../_fixture"); const { parseUnits } = require("ethers/lib/utils"); const { impersonateAndFund } = require("../../utils/signers"); +const { shouldBehaveLikeGovernable } = require("../behaviour/governable"); /* * Because the oracle code is so tightly integrated into the vault, @@ -11,11 +12,22 @@ const { impersonateAndFund } = require("../../utils/signers"); const maxVaultPrice = parseUnits("0.995"); -describe.only("OETH Oracle", async () => { +describe("OETH Oracle", async () => { let fixture; beforeEach(async () => { fixture = await loadDefaultFixture(); }); + + shouldBehaveLikeGovernable(() => ({ + ...fixture, + strategy: fixture.oethOracle, + })); + + shouldBehaveLikeGovernable(() => ({ + ...fixture, + strategy: fixture.oethOracleUpdater, + })); + const assetAddPrice = async (prices) => { const { anna, oethOracle, oethOracleUpdater } = fixture; const { vaultPrice, marketPrice, expectPrice, expectedVaultPrice } = prices; From b6af1180a06c272c30419b6984cedc3e254effba Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Fri, 10 Nov 2023 08:23:20 +1100 Subject: [PATCH 23/23] Internal review updates to the OETH Oracle --- contracts/contracts/oracle/OETHOracleUpdater.sol | 14 +++++++++----- contracts/test/oracle/oracle-oeth.js | 7 ++++++- contracts/test/oracle/oracle.fork-test.js | 4 +++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/contracts/contracts/oracle/OETHOracleUpdater.sol b/contracts/contracts/oracle/OETHOracleUpdater.sol index 58dc9f2431..ecafe0484c 100644 --- a/contracts/contracts/oracle/OETHOracleUpdater.sol +++ b/contracts/contracts/oracle/OETHOracleUpdater.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import { IOracleReceiver } from "./IOracleReceiver.sol"; import { IVault } from "../interfaces/IVault.sol"; -import { AggregatorV3Interface } from "../interfaces/chainlink/AggregatorV3Interface.sol"; import { Governable } from "../governance/Governable.sol"; import { ICurvePool } from "../strategies/ICurvePool.sol"; @@ -29,7 +28,12 @@ contract OETHOracleUpdater is Governable { address curvePool; } - event AddPrice(uint256 answer, uint256 vaultPrice, uint256 marketPrice); + event AddPrice( + address indexed oracle, + uint256 answer, + uint256 vaultPrice, + uint256 marketPrice + ); /** * @param _vault Address of the OETH Vault @@ -50,7 +54,7 @@ contract OETHOracleUpdater is Governable { uint256 marketPrice ) = _getPrices(); - emit AddPrice(answer, vaultPrice, marketPrice); + emit AddPrice(address(oracle), answer, vaultPrice, marketPrice); // Add the new aggregated price to the oracle. // Authorization is handled on Oracle side @@ -72,8 +76,8 @@ contract OETHOracleUpdater is Governable { // Get the aggregated market price from on-chain DEXs marketPrice = _getMarketPrice(); - // If market price is above the vault price with the withdraw fee - if (marketPrice > MAX_VAULT_PRICE) { + // If market price is equal or above the vault price with the withdraw fee + if (marketPrice >= MAX_VAULT_PRICE) { answer = marketPrice; // Avoid getting the vault price as this is gas intensive. // its not going to be higher than 0.995 with a 0.5% withdraw fee diff --git a/contracts/test/oracle/oracle-oeth.js b/contracts/test/oracle/oracle-oeth.js index 1e9fd20110..5ea9311620 100644 --- a/contracts/test/oracle/oracle-oeth.js +++ b/contracts/test/oracle/oracle-oeth.js @@ -44,7 +44,12 @@ describe("OETH Oracle", async () => { await expect(tx) .to.emit(oethOracleUpdater, "AddPrice") - .withArgs(expectPrice, expectedVaultPrice, marketPrice); + .withArgs( + oethOracle.address, + expectPrice, + expectedVaultPrice, + marketPrice + ); const roundData = await oethOracle.latestRoundData(); expect(roundData.answer).to.eq(expectPrice); diff --git a/contracts/test/oracle/oracle.fork-test.js b/contracts/test/oracle/oracle.fork-test.js index de29d79f0f..29298c55ff 100644 --- a/contracts/test/oracle/oracle.fork-test.js +++ b/contracts/test/oracle/oracle.fork-test.js @@ -96,7 +96,9 @@ describe("ForkTest: Oracles", function () { const tx = await oethOracleUpdater.addPrice(oethOracle.address); - await expect(tx).to.emit(oethOracleUpdater, "AddPrice"); + await expect(tx) + .to.emit(oethOracleUpdater, "AddPrice") + .withNamedArgs({ oracle: oethOracle.address }); const data = await oethOracle.latestRoundData(); log(`OETH price: ${formatUnits(data.answer, 18)}`);