Configure for presentation

Signed-off-by: AlienTornadosaurusHex <>
This commit is contained in:
AlienTornadosaurusHex 2023-06-21 22:05:56 +00:00
parent 6b480c62cf
commit 2f53f4959c
2 changed files with 0 additions and 393 deletions

@ -1,183 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
// OZ Imports
import { AdminUpgradeableProxy } from "../common/AdminUpgradeableProxy.sol";
// Tornado imports
import { ITornadoInstance } from "tornado-anonymity-mining/contracts/interfaces/ITornadoInstance.sol";
// Local V2 imports
import { FeeOracleManager } from "../v2/FeeOracleManager.sol";
import { InstanceRegistry } from "../v2/InstanceRegistry.sol";
import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "../v2/CurveFeeOracle.sol";
import { UniswapFeeOracle } from "../v2/UniswapFeeOracle.sol";
import { TornadoRouter } from "../v2/TornadoRouter.sol";
/**
* @title CRVUSDInstancesProposal
* @author AlienTornadosaurusHex
* @notice Proposal to add crvUSD instances in 100, 1000, 10000, 100000, 1000000 denominations.
*/
contract CRVUSDInstancesProposal {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* @dev The first Curve pool which is capable of being used as a safe oracle due to analytical EMA price */
address public constant crvUSDUSDCStableswap2Pool = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
/* @dev The second Curve pool which is capable of being used as a safe oracle due to analytical EMA price */
address public constant tricryptoUSDCPool = 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B;
/* @dev The InstanceRegistry contract, for registering instances, proxy must be upgraded */
InstanceRegistry public constant instanceRegistry =
InstanceRegistry(0xB20c66C4DE72433F3cE747b58B86830c459CA911);
/* @dev The FeeOracleManager contract, proxy must be upgraded */
FeeOracleManager public constant feeOracleManager =
FeeOracleManager(0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7);
/* @dev This is the Uniswap V3 Oracle which we will use for all of our traditional instances, but it will
also help the Curve instances, the former must have been deployed with the address of this */
UniswapFeeOracle public immutable uniswapFeeOracle;
/* @dev This is the CurveFeeOracle contract which will be deployed beforehand and which will be able to
use multiple Curve pools as oracles, at once. */
CurveFeeOracle public immutable curveFeeOracle;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOGIC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
constructor(address _deployedCurveFeeOracleAddress, address _deployedUniswapFeeOracleAddress) public {
curveFeeOracle = CurveFeeOracle(_deployedCurveFeeOracleAddress);
uniswapFeeOracle = UniswapFeeOracle(_deployedUniswapFeeOracleAddress);
}
/**
* @dev This function also executes further internal functions inlined below.
*/
function executeProposal() external {
// Load the deployed crvUSD instances
ITornadoInstance cu100 = ITornadoInstance(0x913a73486Dc4AA3832A56d461542836C1eeB93be);
ITornadoInstance cu1_000 = ITornadoInstance(0x5A6b3C829dB3e938C885000c6E93CF35E74876a4);
ITornadoInstance cu10_000 = ITornadoInstance(0x49f173CDAB99a2C3800F1255393DF9B7a17B82Bb);
ITornadoInstance cu100_000 = ITornadoInstance(0x4640Dffc9fD0B113B983e3A350b070a119CA143C);
ITornadoInstance cu1_000_000 = ITornadoInstance(0xc4eA8Bd3Fd76f3c255395793B47F7c55aD59d991);
// Ok, first add the Uniswap V3 Oracle to the contract
curveFeeOracle.setUniswapFeeOracle(uniswapFeeOracle);
// Then, add necessary oracles for the CRVUSD price, to the CurveFeeOracle
_setCurveFeeChainedOracleForInstance(curveFeeOracle, cu100);
_setCurveFeeChainedOracleForInstance(curveFeeOracle, cu1_000);
_setCurveFeeChainedOracleForInstance(curveFeeOracle, cu10_000);
_setCurveFeeChainedOracleForInstance(curveFeeOracle, cu100_000);
_setCurveFeeChainedOracleForInstance(curveFeeOracle, cu1_000_000);
// Then, add the instances to the InstanceRegistry
instanceRegistry.addInstance(cu100);
instanceRegistry.addInstance(cu1_000);
instanceRegistry.addInstance(cu10_000);
instanceRegistry.addInstance(cu100_000);
instanceRegistry.addInstance(cu1_000_000);
// The fee will be 0.3 % for those pools for which it makes sense
feeOracleManager.setFeePercentForInstance(cu100, 0);
feeOracleManager.setFeePercentForInstance(cu1_000, 0);
feeOracleManager.setFeePercentForInstance(cu10_000, 30);
feeOracleManager.setFeePercentForInstance(cu100_000, 30);
feeOracleManager.setFeePercentForInstance(cu1_000_000, 30);
// Make the update interval 6 hours
feeOracleManager.setFeeUpdateIntervalForInstance(cu100, 6 hours);
feeOracleManager.setFeeUpdateIntervalForInstance(cu1_000, 6 hours);
feeOracleManager.setFeeUpdateIntervalForInstance(cu10_000, 6 hours);
feeOracleManager.setFeeUpdateIntervalForInstance(cu100_000, 6 hours);
feeOracleManager.setFeeUpdateIntervalForInstance(cu1_000_000, 6 hours);
// Finally, set all necessary data in the FeeOracleManager
feeOracleManager.setFeeOracle(address(cu100), address(curveFeeOracle));
feeOracleManager.setFeeOracle(address(cu1_000), address(curveFeeOracle));
feeOracleManager.setFeeOracle(address(cu10_000), address(curveFeeOracle));
feeOracleManager.setFeeOracle(address(cu100_000), address(curveFeeOracle));
feeOracleManager.setFeeOracle(address(cu1_000_000), address(curveFeeOracle));
// Update them all at the start
address router = feeOracleManager.feeUpdaterAddress();
feeOracleManager.setFeeUpdater(address(this));
feeOracleManager.updateFee(cu100, false);
feeOracleManager.updateFee(cu1_000, false);
feeOracleManager.updateFee(cu10_000, false);
feeOracleManager.updateFee(cu100_000, false);
feeOracleManager.updateFee(cu1_000_000, false);
feeOracleManager.setFeeUpdater(router);
}
/**
* @dev This function adds pools as fee oracles to the main curve fee oracle contract. The oracles are
* chained, this means that multiple pools can be used as one oracle using the library which can be found
* in the contract file. This means:
*
* (...pool contracts as oracles) ===(`price_oracle`)===> CurveFeeOracle ===(`getFee()`)===>
* FeeOracleManager ===(`instanceFeeWithUpdate`)===> RelayerRegistry
*/
function _setCurveFeeChainedOracleForInstance(CurveFeeOracle _feeOracle, ITornadoInstance _instance)
internal
{
// Add the oracles which are the USDC/CRVUSD stableswap and tricryptoUSDC pools
ICurvePriceOracle[] memory _oracles = new ICurvePriceOracle[](2);
_oracles[0] = ICurvePriceOracle(crvUSDUSDCStableswap2Pool);
_oracles[1] = ICurvePriceOracle(tricryptoUSDCPool);
// Add the selectors, so which functions to call because tricrypto pools supports getting prices for
// multiple tokens, denominated in the first token, which is usually a stable
bytes4[] memory _selectors = new bytes4[](2);
_selectors[0] = CurveChainedOracles.PRICE_ORACLE_SELECTOR;
_selectors[1] = CurveChainedOracles.PRICE_ORACLE_UINT256_SELECTOR;
// Specify for the second that the ether price must be retrieved
uint8[] memory _coins = new uint8[](2);
_coins[1] = 1; // ETHER
// In order to receive the CRVUSD price, its price in USDC must be read out (the USDC price in crvUSD
// is worthless because we do not have a common denominator in the oracle then) and then the second
// price must be inverted to receive the accurate ETH/CRVUSD price, meaning ETH per CRVUSD, which will
// then be divided by ETH per TORN, and then (ETH/CRVUSD)/(ETH/TORN) = (ETH/CRVUSD)*(TORN/ETH) =
// (TORN/CRVUSD) which is the price that the oracle should be supplying
bool[] memory _invert = new bool[](2);
_invert[0] = false; // DO NOT INVERT, PRICE IS CRVUSD IN USDC
_invert[1] = true; // INVERT, PRICE IS ETH IN USDC, BUT WE NEED USDC IN ETH
// (USDC/CRVUSD)*(ETH/USDC) = (ETH/CRVUSD)
_feeOracle.modifyChainedOracleForInstance(
_instance, _oracles, _selectors, _coins, _invert, "ETH/CRVUSD"
);
}
}

@ -35,8 +35,6 @@ import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "src/v2/C
import { InfrastructureUpgradeProposal } from "src/proposals/InfrastructureUpgradeProposal.sol"; import { InfrastructureUpgradeProposal } from "src/proposals/InfrastructureUpgradeProposal.sol";
import { CRVUSDInstancesProposal } from "src/proposals/CRVUSDInstancesProposal.sol";
// Test imports // Test imports
import { TornadoProposalTest, ProposalState } from "./TornadoProposalTest.sol"; import { TornadoProposalTest, ProposalState } from "./TornadoProposalTest.sol";
@ -77,14 +75,6 @@ contract Instances {
ITornadoInstance public constant wbtc01 = ITornadoInstance(0x178169B423a011fff22B9e3F3abeA13414dDD0F1); ITornadoInstance public constant wbtc01 = ITornadoInstance(0x178169B423a011fff22B9e3F3abeA13414dDD0F1);
ITornadoInstance public constant wbtc1 = ITornadoInstance(0x610B717796ad172B316836AC95a2ffad065CeaB4); ITornadoInstance public constant wbtc1 = ITornadoInstance(0x610B717796ad172B316836AC95a2ffad065CeaB4);
ITornadoInstance public constant wbtc10 = ITornadoInstance(0xbB93e510BbCD0B7beb5A853875f9eC60275CF498); ITornadoInstance public constant wbtc10 = ITornadoInstance(0xbB93e510BbCD0B7beb5A853875f9eC60275CF498);
/* CRVUSD instances */
ITornadoInstance public constant cu100 = ITornadoInstance(0x913a73486Dc4AA3832A56d461542836C1eeB93be);
ITornadoInstance public constant cu1_000 = ITornadoInstance(0x5A6b3C829dB3e938C885000c6E93CF35E74876a4);
ITornadoInstance public constant cu10_000 = ITornadoInstance(0x49f173CDAB99a2C3800F1255393DF9B7a17B82Bb);
ITornadoInstance public constant cu100_000 = ITornadoInstance(0x4640Dffc9fD0B113B983e3A350b070a119CA143C);
ITornadoInstance public constant cu1_000_000 =
ITornadoInstance(0xc4eA8Bd3Fd76f3c255395793B47F7c55aD59d991);
} }
contract ProposalTests is Instances, TornadoProposalTest { contract ProposalTests is Instances, TornadoProposalTest {
@ -165,188 +155,6 @@ contract ProposalTests is Instances, TornadoProposalTest {
_advanceTORNETHMarket(); _advanceTORNETHMarket();
} }
function test_crvusdInstancesBasic() public {
// Do the proposal first
test_crvusdInstancesProposalBasic();
// We have to set to address this again
_feeManagerShouldRevertAndSetFeeUpdater();
// Advance
_advanceTORNETHMarket();
// Try to update crvusd 10000
feeOracleManager.updateFee(cu10_000, false);
// Try to update all
ITornadoInstance[] memory _toUpdate = new ITornadoInstance[](5);
_toUpdate[0] = cu100;
_toUpdate[1] = cu1_000;
_toUpdate[2] = cu10_000;
_toUpdate[3] = cu100_000;
_toUpdate[4] = cu1_000_000;
// We will need to prank an update on the uniswapFeeOracle
// this should otherwise happen automatically though other tokens being withdrawn
vm.startPrank(address(feeOracleManager));
for (uint256 i = 0; i < _toUpdate.length; i++) {
uniswapFeeOracle.update(TORN, feeOracleManager.populateInstanceWithFeeData(_toUpdate[i]));
}
vm.stopPrank();
// Now update all fees
uint160[] memory fees = feeOracleManager.updateFees(_toUpdate, false);
// Print fees to console.
console2.log("\n~~~~~~~~~~~~~~~~~~ LAST FEES ~~~~~~~~~~~~~~~~~~\n");
console2.log("cu100: ", uint256(feeOracleManager.getLastFeeForInstance(cu100)));
console2.log("cu1_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu1_000)));
console2.log("cu10_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu10_000)));
console2.log("cu100_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu100_000)));
console2.log("cu1_000_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu1_000_000)));
console2.log("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
delimit();
console2.log("\n~~~~~~~~~~~~~~~~~~ DATA ~~~~~~~~~~~~~~~~~~\n");
InstanceState memory data = instanceRegistry.getInstanceState(cu100);
delimit();
console2.log("cu100:");
console2.log("token: ", address(data.token));
console2.log("index: ", uint256(data.index));
console2.log("iserc20: ", data.isERC20);
console2.log("isenabled: ", data.isEnabled);
delimit();
data = instanceRegistry.getInstanceState(cu1_000);
console2.log("cu1_000:");
console2.log("token: ", address(data.token));
console2.log("index: ", uint256(data.index));
console2.log("iserc20: ", data.isERC20);
console2.log("isenabled: ", data.isEnabled);
delimit();
data = instanceRegistry.getInstanceState(cu10_000);
console2.log("cu10_000:");
console2.log("token: ", address(data.token));
console2.log("index: ", uint256(data.index));
console2.log("iserc20: ", data.isERC20);
console2.log("isenabled: ", data.isEnabled);
delimit();
data = instanceRegistry.getInstanceState(cu100_000);
console2.log("cu100_000:");
console2.log("token: ", address(data.token));
console2.log("index: ", uint256(data.index));
console2.log("iserc20: ", data.isERC20);
console2.log("isenabled: ", data.isEnabled);
delimit();
data = instanceRegistry.getInstanceState(cu1_000_000);
console2.log("cu1_000_000:");
console2.log("token: ", address(data.token));
console2.log("index: ", uint256(data.index));
console2.log("iserc20: ", data.isERC20);
console2.log("isenabled: ", data.isEnabled);
delimit();
console2.log("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
// No access
curveFeeOracle.update(TORN, feeOracleManager.populateInstanceWithFeeData(cu10_000));
// No access view
curveFeeOracle.getFee(TORN, feeOracleManager.populateInstanceWithFeeData(cu10_000));
// Some assertions
require(
strcomp(curveFeeOracle.getChainedOracleNameForInstance(cu100), "ETH/CRVUSD"),
"oracle name doesnt match"
);
require(
strcomp(
curveFeeOracle.getChainedOracleNameForOracleHash(
curveFeeOracle.getChainedOracleHashForInstance(cu1_000)
),
"ETH/CRVUSD"
),
"oracle name doesnt match"
);
// Now since we will test updating all fees... the oracle will get updated
// but first, warp forward
vm.warp(now + 2 days);
// Should be able to update all fees
fees = feeOracleManager.updateAllFees(true);
feeOracleManager.version();
delimit();
console2.log("\n~~~~~~~~~~~~~~~~~~ LAST FEES ~~~~~~~~~~~~~~~~~~\n");
console2.log("cu100: ", uint256(feeOracleManager.getLastFeeForInstance(cu100)));
console2.log("cu1_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu1_000)));
console2.log("cu10_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu10_000)));
console2.log("cu100_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu100_000)));
console2.log("cu1_000_000: ", uint256(feeOracleManager.getLastFeeForInstance(cu1_000_000)));
console2.log("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
delimit();
console2.log(
"\n 💱 I would like to note that I have verified via calculation that post-price move, the fees work.\n Basically: (1000000*30/10000) == fee * 9 / 10^18, should be constant because block is fix. \n"
);
// Just for some gas values for this call
instanceRegistry.instanceData(cu100);
instanceRegistry.instanceData(cu1_000);
instanceRegistry.version();
router.version();
// Let's just check all instances one by one
InstanceState[] memory states = instanceRegistry.getAllInstanceStates();
for (uint256 i = 0; i < states.length; i++) {
if (i <= 3) {
require(!states[i].isERC20);
require(states[i].isEnabled);
} else if (i <= 7) {
require(states[i].token == DAI);
require(states[i].isERC20);
require(states[i].isEnabled);
} else if (i <= 11) {
require(states[i].token == CDAI);
require(states[i].isERC20);
require(states[i].isEnabled);
} else if (i <= 13) {
require(states[i].token == USDT);
require(states[i].isERC20);
require(states[i].isEnabled);
} else if (i <= 16) {
require(states[i].token == WBTC);
require(states[i].isERC20);
require(states[i].isEnabled);
} else if (i <= 21) {
require(states[i].token == CRVUSD);
require(states[i].isERC20);
require(states[i].isEnabled);
}
}
// Now do a specific interval
states = instanceRegistry.getInstanceState(8, 11);
for (uint256 i = 0; i < 4; i++) {
require(states[i].token == CDAI);
require(states[i].isERC20);
require(states[i].isEnabled);
}
// Other for coverage
require(instanceRegistry.isRegisteredInstance(cu10_000));
vm.prank(address(governance));
instanceRegistry.setTornadoRouter(address(0));
require(address(instanceRegistry.router()) == address(0));
}
function test_infrastructureBasic() public { function test_infrastructureBasic() public {
// Do the proposal first // Do the proposal first
test_infrastructureUpgradeProposalBasic(); test_infrastructureUpgradeProposalBasic();
@ -629,24 +437,6 @@ contract ProposalTests is Instances, TornadoProposalTest {
feeOracleManager.setInstanceRegistry(address(instanceRegistry)); feeOracleManager.setInstanceRegistry(address(instanceRegistry));
} }
function test_crvusdInstancesProposalBasic() public {
// First pass the former proposal
test_infrastructureUpgradeProposalBasic();
// Then create the crvUSD proposal
address proposal =
address(new CRVUSDInstancesProposal(address(curveFeeOracle), address(uniswapFeeOracle)));
// Propose
uint256 id = easyPropose(proposal);
// Wait
waitUntilExecutable(id);
// Exec
governance.execute(id);
}
function test_infrastructureUpgradeProposalBasic() public { function test_infrastructureUpgradeProposalBasic() public {
// Create proposal // Create proposal
address proposal = address( address proposal = address(