From 0b6c7085bac515e14885ead3e66ae3f14e5b41d1 Mon Sep 17 00:00:00 2001 From: Schlag <89420541+Schlagonia@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:14:56 -0600 Subject: [PATCH] build: oracle updates (#51) * build: apr changes * fix: dont revert * chore: check for v3 vault --- src/AprOracle/AprOracle.sol | 74 +++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/src/AprOracle/AprOracle.sol b/src/AprOracle/AprOracle.sol index 9e389dd..6e3ded9 100644 --- a/src/AprOracle/AprOracle.sol +++ b/src/AprOracle/AprOracle.sol @@ -34,9 +34,13 @@ contract AprOracle is Governance { mapping(address => address) public oracles; // Used to get the Current and Expected APR'S. + uint256 internal constant MAX_BPS = 10_000; uint256 internal constant MAX_BPS_EXTENDED = 1_000_000_000_000; uint256 internal constant SECONDS_PER_YEAR = 31_556_952; + address internal constant LEGACY_ORACLE = + 0x27aD2fFc74F74Ed27e1C0A19F1858dD0963277aE; + constructor(address _governance) Governance(_governance) {} /** @@ -61,30 +65,37 @@ contract AprOracle is Governance { // Get the oracle set for this specific strategy. address oracle = oracles[_strategy]; + // If non set check the legacy oracle. + if (oracle == address(0)) { + // Do a low level call in case the legacy oracle is not deployed. + (bool success, bytes memory data) = LEGACY_ORACLE.staticcall( + abi.encodeWithSelector( + AprOracle(LEGACY_ORACLE).oracles.selector, + _strategy + ) + ); + if (success && data.length > 0) { + oracle = abi.decode(data, (address)); + } + } + // Don't revert if a oracle is not set. if (oracle != address(0)) { return IOracle(oracle).aprAfterDebtChange(_strategy, _debtChange); + } else { + // If the vault is a v3 vault, we can get default to the expected apr. + try IVault(_strategy).fullProfitUnlockDate() returns (uint256) { + return getExpectedApr(_strategy, _debtChange); + } catch { + // Else just return 0. + return 0; + } } } - /** - * @notice Get the current weighted APR of a strategy. - * @dev Gives the apr weighted by its `totalAssets`. This can be used - * to get the combined expected return of a collection of strategies. - * - * @param _strategy Address of the strategy. - * @return . The current weighted APR of the strategy. - */ - function weightedApr( - address _strategy - ) external view virtual returns (uint256) { - return - IStrategy(_strategy).totalAssets() * getStrategyApr(_strategy, 0); - } - /** * @notice Set a custom APR `_oracle` for a `_strategy`. - * @dev Can only be called by the oracle's `governance` or + * @dev Can only be called by the oracle's `governance` Is tor * management of the `_strategy`. * * The `_oracle` will need to implement the IOracle interface. @@ -161,4 +172,35 @@ contract AprOracle is Governance { MAX_BPS_EXTENDED / assets; } + + function getWeightedAverageApr( + address _vault + ) external view virtual returns (uint256) { + address[] memory strategies = IVault(_vault).get_default_queue(); + + uint256 totalApr = 0; + for (uint256 i = 0; i < strategies.length; i++) { + uint256 debt = IVault(_vault) + .strategies(strategies[i]) + .current_debt; + + if (debt == 0) continue; + + // Get a performance fee if the strategy has one. + (, bytes memory fee) = strategies[i].staticcall( + abi.encodeWithSelector( + IStrategy(strategies[i]).performanceFee.selector + ) + ); + uint256 performanceFee = abi.decode(fee, (uint256)); + + // Add the weighted apr of the strategy to the total apr. + totalApr += + (getStrategyApr(strategies[i], 0) * debt * performanceFee) / + MAX_BPS; + } + + // Divide by the total assets to get apr as 1e18. + return totalApr / IVault(_vault).totalAssets(); + } }