diff --git a/.env.example b/.env.example index eb4d0a1..344f01c 100644 --- a/.env.example +++ b/.env.example @@ -11,3 +11,4 @@ PRICE_FEED_DESCRIPTIONS=["steakLRT", "Re7LRT", "amphrETH", "rstETH"] QUOTED_PRICE_FEEDS=["WETH/ETH", "WETH/USDC"] MELLOW_PRICE_FEEDS=["amphrETH/wstETH"] MELLOW_VAULTS=["0x5fD13359Ba15A84B76f7F87568309040176167cd"] +MELLOW_QUOTE_ASSETS=["0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0"] diff --git a/contracts/mellow-lrt/libraries/external/FullMath.sol b/contracts/mellow-lrt/libraries/external/FullMath.sol new file mode 100644 index 0000000..c561957 --- /dev/null +++ b/contracts/mellow-lrt/libraries/external/FullMath.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/// @title Contains 512-bit math functions +/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision +/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits +library FullMath { + /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 + /// @param a The multiplicand + /// @param b The multiplier + /// @param denominator The divisor + /// @return result The 256-bit result + /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv + function mulDiv( + uint256 a, + uint256 b, + uint256 denominator + ) internal pure returns (uint256 result) { + // diff: original lib works under 0.7.6 with overflows enabled + unchecked { + // 512-bit multiply [prod1 prod0] = a * b + // Compute the product mod 2**256 and mod 2**256 - 1 + // then use the Chinese Remainder Theorem to reconstruct + // the 512 bit result. The result is stored in two 256 + // variables such that product = prod1 * 2**256 + prod0 + uint256 prod0; // Least significant 256 bits of the product + uint256 prod1; // Most significant 256 bits of the product + assembly { + let mm := mulmod(a, b, not(0)) + prod0 := mul(a, b) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } + + // Handle non-overflow cases, 256 by 256 division + if (prod1 == 0) { + require(denominator > 0); + assembly { + result := div(prod0, denominator) + } + return result; + } + + // Make sure the result is less than 2**256. + // Also prevents denominator == 0 + require(denominator > prod1); + + /////////////////////////////////////////////// + // 512 by 256 division. + /////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [prod1 prod0] + // Compute remainder using mulmod + uint256 remainder; + assembly { + remainder := mulmod(a, b, denominator) + } + // Subtract 256 bit number from 512 bit number + assembly { + prod1 := sub(prod1, gt(remainder, prod0)) + prod0 := sub(prod0, remainder) + } + + // Factor powers of two out of denominator + // Compute largest power of two divisor of denominator. + // Always >= 1. + // diff: original uint256 twos = -denominator & denominator; + uint256 twos = uint256(-int256(denominator)) & denominator; + // Divide denominator by power of two + assembly { + denominator := div(denominator, twos) + } + + // Divide [prod1 prod0] by the factors of two + assembly { + prod0 := div(prod0, twos) + } + // Shift in bits from prod1 into prod0. For this we need + // to flip `twos` such that it is 2**256 / twos. + // If twos is zero, then it becomes one + assembly { + twos := add(div(sub(0, twos), twos), 1) + } + prod0 |= prod1 * twos; + + // Invert denominator mod 2**256 + // Now that denominator is an odd number, it has an inverse + // modulo 2**256 such that denominator * inv = 1 mod 2**256. + // Compute the inverse by starting with a seed that is correct + // correct for four bits. That is, denominator * inv = 1 mod 2**4 + uint256 inv = (3 * denominator) ^ 2; + // Now use Newton-Raphson iteration to improve the precision. + // Thanks to Hensel's lifting lemma, this also works in modular + // arithmetic, doubling the correct bits in each step. + inv *= 2 - denominator * inv; // inverse mod 2**8 + inv *= 2 - denominator * inv; // inverse mod 2**16 + inv *= 2 - denominator * inv; // inverse mod 2**32 + inv *= 2 - denominator * inv; // inverse mod 2**64 + inv *= 2 - denominator * inv; // inverse mod 2**128 + inv *= 2 - denominator * inv; // inverse mod 2**256 + + // Because the division is now exact we can divide by multiplying + // with the modular inverse of denominator. This will give us the + // correct result modulo 2**256. Since the precoditions guarantee + // that the outcome is less than 2**256, this is the final result. + // We don't need to compute the high bits of the result and prod1 + // is no longer required. + result = prod0 * inv; + return result; + } + } + + /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 + /// @param a The multiplicand + /// @param b The multiplier + /// @param denominator The divisor + /// @return result The 256-bit result + function mulDivRoundingUp( + uint256 a, + uint256 b, + uint256 denominator + ) internal pure returns (uint256 result) { + // diff: original lib works under 0.7.6 with overflows enabled + unchecked { + result = mulDiv(a, b, denominator); + if (mulmod(a, b, denominator) > 0) { + require(result < type(uint256).max); + result++; + } + } + } +} diff --git a/contracts/mellowpricefeed/CloneFactory.sol b/contracts/mellowpricefeed/CloneFactory.sol index db13554..5dbb18e 100644 --- a/contracts/mellowpricefeed/CloneFactory.sol +++ b/contracts/mellowpricefeed/CloneFactory.sol @@ -23,11 +23,13 @@ contract CloneFactory { /// @notice Create clone of MellowPriceFeed contract and initialize it. /// @dev Clone method returns address of created clone. /// @param _vault Address of Mellow LRT vault. + /// @param _quoteAsset Address of quote asset. /// @param _priceFeedDecimals Amount of decimals a PriceFeed is denominiated in. /// @param _priceFeedBase Base asset of PriceFeed, should be set to asset symbol ticker. /// @param _priceFeedQuote Quote asset of PriceFeed, should be set to asset symbol ticker. function createMellowPriceFeed( address _vault, + address _quoteAsset, uint8 _priceFeedDecimals, string calldata _priceFeedBase, string calldata _priceFeedQuote @@ -35,6 +37,7 @@ contract CloneFactory { address mellowPriceFeedCloneAddress = Clones.clone(implementationAddress); MellowPriceFeed(mellowPriceFeedCloneAddress).initialize( _vault, + _quoteAsset, _priceFeedDecimals, _priceFeedBase, _priceFeedQuote diff --git a/contracts/mellowpricefeed/MellowPriceFeed.sol b/contracts/mellowpricefeed/MellowPriceFeed.sol index f6494a1..ed8d441 100644 --- a/contracts/mellowpricefeed/MellowPriceFeed.sol +++ b/contracts/mellowpricefeed/MellowPriceFeed.sol @@ -3,7 +3,9 @@ pragma solidity ^0.8.20; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; -import "../mellow-lrt/interfaces/oracles/IManagedRatiosOracle.sol"; +import "../mellow-lrt/interfaces/IVault.sol"; +import "../mellow-lrt/libraries/external/FullMath.sol"; +import "../mellow-lrt/interfaces/oracles/IPriceOracle.sol"; /// @title Contract for retreiving a Mellow LRT Vault's exchange rate value with chainlink's AggregatorV3Interface /// implemented. @@ -15,10 +17,10 @@ contract MellowPriceFeed is Initializable, AggregatorV3Interface { string private priceFeedQuote; - IManagedRatiosOracle public immutable managedRatiosOracle; - address public vault; + address public quoteAsset; + uint80 constant DEFAULT_ROUND = 1; uint256 constant DEFAULT_VERSION = 1; @@ -27,23 +29,22 @@ contract MellowPriceFeed is Initializable, AggregatorV3Interface { error GetRoundDataCanBeOnlyCalledWithLatestRound(uint80 requestedRoundId); - constructor(address managedRatiosOracle_) { - managedRatiosOracle = IManagedRatiosOracle(managedRatiosOracle_); - } - /// @notice Initialize clone of this contract. /// @dev This function is used in place of a constructor in proxy contracts. /// @param _vault Address of Mellow LRT vault. + /// @param _quoteAsset Address of quote asset. /// @param _priceFeedDecimals Amount of decimals a PriceFeed is denominiated in. /// @param _priceFeedBase Base asset of PriceFeed. /// @param _priceFeedQuote Quote asset of PriceFeed. function initialize( address _vault, + address _quoteAsset, uint8 _priceFeedDecimals, string calldata _priceFeedBase, string calldata _priceFeedQuote ) external initializer { vault = _vault; + quoteAsset = _quoteAsset; priceFeedDecimals = _priceFeedDecimals; priceFeedBase = _priceFeedBase; priceFeedQuote = _priceFeedQuote; @@ -111,11 +112,27 @@ contract MellowPriceFeed is Initializable, AggregatorV3Interface { ) { roundId = latestRound(); - uint128[] memory ratiosX96 = managedRatiosOracle.getTargetRatiosX96(vault, true); + IVault vault_ = IVault(vault); + ( + address[] memory tokens, + uint256[] memory totalAmounts + ) = vault_.underlyingTvl(); + + IPriceOracle priceOracle = IPriceOracle(vault_.configurator().priceOracle()); + + answer = int256(10**priceFeedDecimals); + uint256 totalTvl = 0; + uint256 quoteValue = 0; + for (uint256 i = 0; i < tokens.length; i++) { + uint256 priceX96 = priceOracle.priceX96(vault, tokens[i]); + if (tokens[i] == quoteAsset) { + quoteValue += FullMath.mulDivRoundingUp(totalAmounts[i], priceX96, vault_.Q96()); + } + totalTvl += FullMath.mulDivRoundingUp(totalAmounts[i], priceX96, vault_.Q96()); + } - answer = 0; - if (ratiosX96.length != 0) { - answer = int256(uint256(ratiosX96[0])) * 1e18 / int256(managedRatiosOracle.Q96()); + if (totalTvl != 0) { + answer = int256(FullMath.mulDiv(quoteValue, uint256(answer), totalTvl)); } // These values are equal after chainlink’s OCR update diff --git a/mainnet_chains.json b/mainnet_chains.json index 61e6607..4dbdc5a 100644 --- a/mainnet_chains.json +++ b/mainnet_chains.json @@ -8,7 +8,6 @@ "gasReceiver": "0x2d5d7d31F671F86C782533cc367F14109a082712", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "0xa1aB70C0F3725AcA1D1e85Bd4402Dd2d5F6AFf19", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -25,7 +24,6 @@ "gasReceiver": "0x2d5d7d31F671F86C782533cc367F14109a082712", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "0xfaC9d315b9b558e10eBdb0462aA42577aADe6601", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -42,7 +40,6 @@ "gasReceiver": "0x2d5d7d31F671F86C782533cc367F14109a082712", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "0x09d43904C8ABd470df1B793df68904A9714558CF", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -59,12 +56,11 @@ "gasReceiver": "0x2d5d7d31F671F86C782533cc367F14109a082712", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "0x955Ff4Cc738cDC009d2903196d1c94C8Cfb4D55d", "priceFeedImplementation": "0xde471274F1B684476d341eB131224F389AD4A270", "priceFeedQuotedImplementation": "", - "mellowPriceFeedImplementation": "0xd93274d286574Dab0BA6D8363F0F31E74df5814c", + "mellowPriceFeedImplementation": "0xc2E105535132E588b5D1764A0b9472e5537FA9cD", "cloneFactory": "0x710C8a3c8CB393cA24748849de3585b5C48D4D0c", "cloneFactoryQuoted": "", - "cloneFactoryMellow": "0x48B10B538B7E5af4CbFd93B1C4d36668e8F6F644" + "cloneFactoryMellow": "0x721c05f08308Bcce5C62e342070564Fd4441ec32" } ] diff --git a/scripts/createMellowPriceFeeds.ts b/scripts/createMellowPriceFeeds.ts index ce77a0a..e101e71 100644 --- a/scripts/createMellowPriceFeeds.ts +++ b/scripts/createMellowPriceFeeds.ts @@ -8,8 +8,9 @@ async function main() { const mellowPriceFeedDecimals = process.env.PRICE_FEED_DECIMALS as any; const mellowPriceFeeds = JSON.parse(process.env.MELLOW_PRICE_FEEDS!); const mellowVaults = JSON.parse(process.env.MELLOW_VAULTS!); + const mellowQuoteAssets = JSON.parse(process.env.MELLOW_QUOTE_ASSETS!); - if (mellowPriceFeeds.length !== mellowVaults.length) { + if (mellowPriceFeeds.length !== mellowVaults.length || mellowPriceFeeds.length !== mellowQuoteAssets.length) { throw new Error('unequal amount of mellowVaults associated with mellowPriceFeeds'); } @@ -41,7 +42,7 @@ async function main() { console.log("baseAsset", baseAsset) console.log("quoteAsset", quoteAsset) - const tx = await cloneFactoryMellowContract.createMellowPriceFeed(mellowVaults[i], mellowPriceFeedDecimals, baseAsset, quoteAsset); + const tx = await cloneFactoryMellowContract.createMellowPriceFeed(mellowVaults[i], mellowQuoteAssets[i], mellowPriceFeedDecimals, baseAsset, quoteAsset); console.log(`Transaction sent: ${tx.hash}`); const receipt = await tx.wait(); diff --git a/scripts/deployMellowPriceFeedImplementation.ts b/scripts/deployMellowPriceFeedImplementation.ts index d0b9e4c..9661333 100644 --- a/scripts/deployMellowPriceFeedImplementation.ts +++ b/scripts/deployMellowPriceFeedImplementation.ts @@ -26,7 +26,7 @@ async function main() { console.log(`${chain.name} wallet balance: ${ethers.formatEther(balance.toString())} ${chain.tokenSymbol}`); const mellowPriceFeedFactory = new ethers.ContractFactory(MellowPriceFeed.abi, MellowPriceFeed.bytecode, wallet) - const mellowPriceFeed = await mellowPriceFeedFactory.deploy(chain.managedRatiosOracle) + const mellowPriceFeed = await mellowPriceFeedFactory.deploy() console.log(`${chain.name}, address: ${await mellowPriceFeed.getAddress()}`); } } diff --git a/testnet_chains.json b/testnet_chains.json index 67e9824..94ea302 100644 --- a/testnet_chains.json +++ b/testnet_chains.json @@ -8,7 +8,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -25,7 +24,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "0x1A069010D7F572c97925E83a1298Df8f96893c60", "mellowPriceFeedImplementation": "", @@ -42,7 +40,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -59,7 +56,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -76,7 +72,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -93,7 +88,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -110,7 +104,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -127,7 +120,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -144,7 +136,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -160,7 +151,7 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", + "priceFeedImplementation": "0x3DB6DF9EDfDcfE97D574Aa6f106C767051561Be2", "priceFeedQuotedImplementation": "0x2Babd8D4BCE072e78aA288c639Ef4516fCe26d89", "mellowPriceFeedImplementation": "", @@ -177,7 +168,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -194,7 +184,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "0x48B10B538B7E5af4CbFd93B1C4d36668e8F6F644", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -211,7 +200,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -228,7 +216,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "0x09d43904C8ABd470df1B793df68904A9714558CF", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -245,7 +232,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -262,7 +248,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -279,7 +264,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -296,7 +280,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "", @@ -313,7 +296,6 @@ "gasReceiver": "0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6", "ojoContract": "0x5BB3E85f91D08fe92a3D123EE35050b763D6E6A7", "create2Deployer": "0x98b2920d53612483f91f12ed7754e51b4a77919e", - "managedRatiosOracle": "", "priceFeedImplementation": "", "priceFeedQuotedImplementation": "", "mellowPriceFeedImplementation": "",