LCOV - code coverage report
Current view: top level - proposals - CRVUSDInstancesProposal.sol (source / functions) Hit Total Coverage
Test: lcov.info Lines: 51 51 100.0 %
Date: 2023-06-19 00:07:36 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : 
       3             : pragma solidity ^0.6.12;
       4             : pragma experimental ABIEncoderV2;
       5             : 
       6             : // OZ Imports
       7             : 
       8             : import { AdminUpgradeableProxy } from "../common/AdminUpgradeableProxy.sol";
       9             : 
      10             : // Tornado imports
      11             : 
      12             : import { ITornadoInstance } from "tornado-anonymity-mining/contracts/interfaces/ITornadoInstance.sol";
      13             : 
      14             : // Local V2 imports
      15             : 
      16             : import { FeeOracleManager } from "../v2/FeeOracleManager.sol";
      17             : 
      18             : import { InstanceRegistry } from "../v2/InstanceRegistry.sol";
      19             : 
      20             : import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "../v2/CurveFeeOracle.sol";
      21             : 
      22             : import { UniswapFeeOracle } from "../v2/UniswapFeeOracle.sol";
      23             : 
      24             : import { TornadoRouter } from "../v2/TornadoRouter.sol";
      25             : 
      26             : /**
      27             :  * @title CRVUSDInstancesProposal
      28             :  * @author AlienTornadosaurusHex
      29             :  * @notice Proposal to add crvUSD instances in 100, 1000, 10000, 100000, 1000000 denominations.
      30             :  */
      31             : contract CRVUSDInstancesProposal {
      32             :     /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      33             : 
      34             :     /* @dev The first Curve pool which is capable of being used as a safe oracle due to analytical EMA price */
      35             :     address public constant crvUSDUSDCStableswap2Pool = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
      36             : 
      37             :     /* @dev The second Curve pool which is capable of being used as a safe oracle due to analytical EMA price */
      38             :     address public constant tricryptoUSDCPool = 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B;
      39             : 
      40             :     /* @dev The InstanceRegistry contract, for registering instances, proxy must be upgraded */
      41             :     InstanceRegistry public constant instanceRegistry =
      42             :         InstanceRegistry(0xB20c66C4DE72433F3cE747b58B86830c459CA911);
      43             : 
      44             :     /* @dev The FeeOracleManager contract, proxy must be upgraded */
      45             :     FeeOracleManager public constant feeOracleManager =
      46             :         FeeOracleManager(0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7);
      47             : 
      48             :     /* @dev This is the Uniswap V3 Oracle which we will use for all of our traditional instances, but it will
      49             :     also help the Curve instances, the former must have been deployed with the address of this */
      50             :     UniswapFeeOracle public immutable uniswapFeeOracle;
      51             : 
      52             :     /* @dev This is the CurveFeeOracle contract which will be deployed beforehand and which will be able to
      53             :     use multiple Curve pools as oracles, at once. */
      54             :     CurveFeeOracle public immutable curveFeeOracle;
      55             : 
      56             :     /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOGIC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      57             : 
      58             :     constructor(address _deployedCurveFeeOracleAddress, address _deployedUniswapFeeOracleAddress) public {
      59             :         curveFeeOracle = CurveFeeOracle(_deployedCurveFeeOracleAddress);
      60             :         uniswapFeeOracle = UniswapFeeOracle(_deployedUniswapFeeOracleAddress);
      61             :     }
      62             : 
      63             :     /**
      64             :      * @dev This function also executes further internal functions inlined below.
      65             :      */
      66             :     function executeProposal() external {
      67             :         // Load the deployed crvUSD instances
      68             : 
      69           2 :         ITornadoInstance cu100 = ITornadoInstance(0x913a73486Dc4AA3832A56d461542836C1eeB93be);
      70           2 :         ITornadoInstance cu1_000 = ITornadoInstance(0x5A6b3C829dB3e938C885000c6E93CF35E74876a4);
      71           2 :         ITornadoInstance cu10_000 = ITornadoInstance(0x49f173CDAB99a2C3800F1255393DF9B7a17B82Bb);
      72           2 :         ITornadoInstance cu100_000 = ITornadoInstance(0x4640Dffc9fD0B113B983e3A350b070a119CA143C);
      73           2 :         ITornadoInstance cu1_000_000 = ITornadoInstance(0xc4eA8Bd3Fd76f3c255395793B47F7c55aD59d991);
      74             : 
      75             :         // Ok, first add the Uniswap V3 Oracle to the contract
      76             : 
      77           2 :         curveFeeOracle.setUniswapFeeOracle(uniswapFeeOracle);
      78             : 
      79             :         // Then, add necessary oracles for the CRVUSD price, to the CurveFeeOracle
      80             : 
      81           2 :         _setCurveFeeChainedOracleForInstance(curveFeeOracle, cu100);
      82           2 :         _setCurveFeeChainedOracleForInstance(curveFeeOracle, cu1_000);
      83           2 :         _setCurveFeeChainedOracleForInstance(curveFeeOracle, cu10_000);
      84           2 :         _setCurveFeeChainedOracleForInstance(curveFeeOracle, cu100_000);
      85           2 :         _setCurveFeeChainedOracleForInstance(curveFeeOracle, cu1_000_000);
      86             : 
      87             :         // Then, add the instances to the InstanceRegistry
      88             : 
      89           2 :         instanceRegistry.addInstance(cu100);
      90           2 :         instanceRegistry.addInstance(cu1_000);
      91           2 :         instanceRegistry.addInstance(cu10_000);
      92           2 :         instanceRegistry.addInstance(cu100_000);
      93           2 :         instanceRegistry.addInstance(cu1_000_000);
      94             : 
      95             :         // Finally, set all necessary data in the FeeOracleManager
      96             : 
      97           2 :         feeOracleManager.setFeeOracle(address(cu100), address(curveFeeOracle));
      98           2 :         feeOracleManager.setFeeOracle(address(cu1_000), address(curveFeeOracle));
      99           2 :         feeOracleManager.setFeeOracle(address(cu10_000), address(curveFeeOracle));
     100           2 :         feeOracleManager.setFeeOracle(address(cu100_000), address(curveFeeOracle));
     101           2 :         feeOracleManager.setFeeOracle(address(cu1_000_000), address(curveFeeOracle));
     102             : 
     103             :         // The fee will be 0.3 % for those pools for which it makes sense
     104             : 
     105           2 :         feeOracleManager.setFeePercentForInstance(cu100, 0);
     106           2 :         feeOracleManager.setFeePercentForInstance(cu1_000, 0);
     107           2 :         feeOracleManager.setFeePercentForInstance(cu10_000, 30);
     108           2 :         feeOracleManager.setFeePercentForInstance(cu100_000, 30);
     109           2 :         feeOracleManager.setFeePercentForInstance(cu1_000_000, 30);
     110             : 
     111             :         // Make the update interval 6 hours
     112             : 
     113           2 :         feeOracleManager.setFeeUpdateIntervalForInstance(cu100, 6 hours);
     114           2 :         feeOracleManager.setFeeUpdateIntervalForInstance(cu1_000, 6 hours);
     115           2 :         feeOracleManager.setFeeUpdateIntervalForInstance(cu10_000, 6 hours);
     116           2 :         feeOracleManager.setFeeUpdateIntervalForInstance(cu100_000, 6 hours);
     117           2 :         feeOracleManager.setFeeUpdateIntervalForInstance(cu1_000_000, 6 hours);
     118             : 
     119             :         // Update them all at the start
     120             : 
     121           2 :         address router = feeOracleManager.feeUpdaterAddress();
     122             : 
     123           2 :         feeOracleManager.setFeeUpdater(address(this));
     124             : 
     125           2 :         feeOracleManager.updateFee(cu100, false);
     126           2 :         feeOracleManager.updateFee(cu1_000, false);
     127           2 :         feeOracleManager.updateFee(cu10_000, false);
     128           2 :         feeOracleManager.updateFee(cu100_000, false);
     129           2 :         feeOracleManager.updateFee(cu1_000_000, false);
     130             : 
     131           2 :         feeOracleManager.setFeeUpdater(router);
     132             :     }
     133             : 
     134             :     /**
     135             :      * @dev This function adds pools as fee oracles to the main curve fee oracle contract. The oracles are
     136             :      * chained, this means that multiple pools can be used as one oracle using the library which can be found
     137             :      * in the contract file. This means:
     138             :      *
     139             :      * (...pool contracts as oracles) ===(`price_oracle`)===> CurveFeeOracle ===(`getFee()`)===>
     140             :      * FeeOracleManager ===(`instanceFeeWithUpdate`)===> RelayerRegistry
     141             :      */
     142             :     function _setCurveFeeChainedOracleForInstance(CurveFeeOracle _feeOracle, ITornadoInstance _instance)
     143             :         internal
     144             :     {
     145             :         // Add the oracles which are the USDC/CRVUSD stableswap and tricryptoUSDC pools
     146             : 
     147          10 :         ICurvePriceOracle[] memory _oracles = new ICurvePriceOracle[](2);
     148             : 
     149          10 :         _oracles[0] = ICurvePriceOracle(crvUSDUSDCStableswap2Pool);
     150          10 :         _oracles[1] = ICurvePriceOracle(tricryptoUSDCPool);
     151             : 
     152             :         // Add the selectors, so which functions to call because tricrypto pools supports getting prices for
     153             :         // multiple tokens, denominated in the first token, which is usually a stable
     154             : 
     155          10 :         bytes4[] memory _selectors = new bytes4[](2);
     156             : 
     157          10 :         _selectors[0] = CurveChainedOracles.PRICE_ORACLE_SELECTOR;
     158          10 :         _selectors[1] = CurveChainedOracles.PRICE_ORACLE_UINT256_SELECTOR;
     159             : 
     160             :         // Specify for the second that the ether price must be retrieved
     161             : 
     162          10 :         uint8[] memory _coins = new uint8[](2);
     163             : 
     164          10 :         _coins[1] = 1; // ETHER
     165             : 
     166             :         // In order to receive the CRVUSD price, its price in USDC must be read out (the USDC price in crvUSD
     167             :         // is worthless because we do not have a common denominator in the oracle then) and then the second
     168             :         // price must be inverted to receive the accurate ETH/CRVUSD price, meaning ETH per CRVUSD, which will
     169             :         // then be divided by ETH per TORN, and then (ETH/CRVUSD)/(ETH/TORN) = (ETH/CRVUSD)*(TORN/ETH) =
     170             :         // (TORN/CRVUSD) which is the price that the oracle should be supplying
     171             : 
     172          10 :         bool[] memory _invert = new bool[](2);
     173             : 
     174          10 :         _invert[0] = false; // DO NOT INVERT, PRICE IS CRVUSD IN USDC
     175          10 :         _invert[1] = true; // INVERT, PRICE IS ETH IN USDC, BUT WE NEED USDC IN ETH
     176             : 
     177             :         // (USDC/CRVUSD)*(ETH/USDC) = (ETH/CRVUSD)
     178             : 
     179          10 :         _feeOracle.modifyChainedOracleForInstance(
     180             :             _instance, _oracles, _selectors, _coins, _invert, "ETH/CRVUSD"
     181             :         );
     182             :     }
     183             : }

Generated by: LCOV version 1.16