infrastructure-upgrade/test/OracleTests.sol

276 lines
10 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
// OZ Imports
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// Tornado imports
import { ITornadoInstance } from "tornado-anonymity-mining/contracts/interfaces/ITornadoInstance.sol";
// STD Imports
import { Test } from "forge-std/Test.sol";
import { console2 } from "forge-std/console2.sol";
// Local imports
import { TornadoProposalTest } from "./TornadoProposalTest.sol";
import { IGovernance, Proposal } from "common/interfaces/IGovernance.sol";
import { IUniswapV2Pair } from "src/v2/interfaces/IUniswapV2Pair.sol";
import { TornadoAddresses } from "common/TornadoAddresses.sol";
import { FeeOracleManager, FeeDataForOracle, InstanceWithFee } from "src/v2/FeeOracleManager.sol";
import { UniswapFeeOracle } from "src/v2/UniswapFeeOracle.sol";
import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "src/v2/CurveFeeOracle.sol";
import { InstanceState } from "src/v2/InstanceRegistry.sol";
interface IWethDepositable {
function deposit() external payable;
}
contract Instances {
/* ETH instances */
ITornadoInstance public constant eth01 = ITornadoInstance(0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc);
ITornadoInstance public constant eth1 = ITornadoInstance(0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936);
ITornadoInstance public constant eth10 = ITornadoInstance(0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF);
ITornadoInstance public constant eth100 = ITornadoInstance(0xA160cdAB225685dA1d56aa342Ad8841c3b53f291);
/* DAI instances */
ITornadoInstance public constant dai100 = ITornadoInstance(0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3);
ITornadoInstance public constant dai1000 = ITornadoInstance(0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144);
ITornadoInstance public constant dai10000 = ITornadoInstance(0x07687e702b410Fa43f4cB4Af7FA097918ffD2730);
ITornadoInstance public constant dai100000 = ITornadoInstance(0x23773E65ed146A459791799d01336DB287f25334);
/* cDAI instances */
ITornadoInstance public constant cdai100 = ITornadoInstance(0x22aaA7720ddd5388A3c0A3333430953C68f1849b);
ITornadoInstance public constant cdai1000 = ITornadoInstance(0x03893a7c7463AE47D46bc7f091665f1893656003);
ITornadoInstance public constant cdai10000 = ITornadoInstance(0x2717c5e28cf931547B621a5dddb772Ab6A35B701);
ITornadoInstance public constant cdai100000 = ITornadoInstance(0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af);
/* USDT instances */
ITornadoInstance public constant usdt100 = ITornadoInstance(0x169AD27A470D064DEDE56a2D3ff727986b15D52B);
ITornadoInstance public constant usdt1000 = ITornadoInstance(0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f);
/* WBTC instances */
ITornadoInstance public constant wbtc01 = ITornadoInstance(0x178169B423a011fff22B9e3F3abeA13414dDD0F1);
ITornadoInstance public constant wbtc1 = ITornadoInstance(0x610B717796ad172B316836AC95a2ffad065CeaB4);
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 OracleTests is Instances, TornadoProposalTest {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
// Tokens - constant
IERC20 internal constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
// Contracts - constant
FeeOracleManager public constant feeOracleManager =
FeeOracleManager(0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7);
IUniswapV2Pair public constant uniTornPool = IUniswapV2Pair(0x0C722a487876989Af8a05FFfB6e32e45cc23FB3A);
address public constant crvUSDUSDCStableswap2Pool = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
address public constant tricryptoUSDCPool = 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B;
// Contracts - mutable
UniswapFeeOracle uniswapFeeOracle;
CurveFeeOracle feeOracle;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TESTING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
function setUp() public virtual override {
vm.createSelectFork(vm.envString("MAINNET_RPC_URL"));
vm.rollFork(17_493_778);
uniswapFeeOracle = new UniswapFeeOracle(address(this), address(this));
uniswapFeeOracle.setMinObservationCardinality(10);
uniswapFeeOracle.setPoolFeeForToken(WETH, 0);
feeOracle = new CurveFeeOracle(address(this));
feeOracle.setTornOracleIsUniswap(false);
feeOracle.setUniswapFeeOracle(uniswapFeeOracle);
}
function test_curveFeeSingleTricrypto() public {
_setCurveFeeSimpleTricryptoOracleForInstance(feeOracle, cu10_000); // CRVUSD 10_000
console2.log(
"\nShould be 30 * (ETH/USD) ------------------------------------------------\n",
uint256(
feeOracle.getFee(
TORN,
InstanceWithFee({
logic: cu10_000,
state: InstanceState(IERC20(cu10_000.token()), 0, true, true),
fee: FeeDataForOracle(0, 30, 10_000, 2 days, 0)
})
)
),
"\n------------------------------------------------------------------------\n"
);
}
function test_curveFeeChainedTORN() public {
uint256 timeBeforeSwap = now;
feeOracle.setTornOracleIsUniswap(true);
_setCurveFeeChainedOracleForInstance(feeOracle, cu10_000); // CRVUSD 10_000
_advanceTORNETHMarket();
uniswapFeeOracle.update(
TORN,
InstanceWithFee({
logic: cu10_000,
state: InstanceState(IERC20(address(0)), 0, false, false),
fee: FeeDataForOracle(0, 0, 0, 0, uint32(timeBeforeSwap))
})
);
console2.log(
"\nTORN Fee calculated ------------------------------------------------------\n",
uint256(
feeOracle.getFee(
TORN,
InstanceWithFee({
logic: cu10_000,
state: InstanceState(IERC20(cu10_000.token()), 0, true, true),
fee: FeeDataForOracle(0, 30, 10_000, 2 days, uint32(timeBeforeSwap))
})
)
),
"\n------------------------------------------------------------------------\n"
);
}
function test_UniswapTORNOracle() public {
uint256 timeBeforeSwap = now;
_advanceTORNETHMarket();
InstanceWithFee memory feepool = InstanceWithFee({
logic: eth100,
state: InstanceState(WETH, 0, false, true),
fee: FeeDataForOracle(0, 30, 10_000, 2 days, uint32(timeBeforeSwap))
});
uniswapFeeOracle.update(TORN, feepool);
console2.log(
"\nTORN Fee calculated ------------------------------------------------------\n",
uniswapFeeOracle.getFee(TORN, feepool),
"\n------------------------------------------------------------------------\n"
);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
function _advanceTORNETHMarket() internal {
console2.log("\ntrader is now going to move the price\n");
uint256 lastPriceAvg0 = uniTornPool.price0CumulativeLast();
uint256 lastPriceAvg1 = uniTornPool.price0CumulativeLast();
uint256 rn = now;
address trader = address(bytes20(keccak256("trader")));
vm.deal(trader, 20 ether);
vm.prank(trader);
IWethDepositable(address(WETH)).deposit{ value: 19 ether }();
require(WETH.balanceOf(trader) == 19 ether, "deposit for weth");
vm.warp(rn + 2 days + 1 hours);
vm.prank(trader);
WETH.transfer(address(uniTornPool), 19 ether);
uniTornPool.swap(6_600_000_000_000_000_000_000, 0, trader, new bytes(0));
console2.log("\ntrader received =>", TORN.balanceOf(trader), "TORN\n");
require(lastPriceAvg0 != uniTornPool.price0CumulativeLast(), "twap moving 0 fail");
require(lastPriceAvg1 != uniTornPool.price1CumulativeLast(), "twap moving 1 fail");
}
function _setCurveFeeSimpleTricryptoOracleForInstance(
CurveFeeOracle _feeOracle,
ITornadoInstance _instance
) internal {
ICurvePriceOracle[] memory _oracles = new ICurvePriceOracle[](1);
_oracles[0] = ICurvePriceOracle(tricryptoUSDCPool);
bytes4[] memory _selectors = new bytes4[](1);
_selectors[0] = CurveChainedOracles.PRICE_ORACLE_UINT256_SELECTOR;
uint8[] memory _coins = new uint8[](1);
_coins[0] = 1; // ETHER
bool[] memory _invert = new bool[](1);
_invert[0] = true;
_feeOracle.modifyChainedOracleForInstance(
_instance, _oracles, _selectors, _coins, _invert, "ETH/CRVUSD"
);
}
function _setCurveFeeChainedOracleForInstance(CurveFeeOracle _feeOracle, ITornadoInstance _instance)
internal
{
ICurvePriceOracle[] memory _oracles = new ICurvePriceOracle[](2);
_oracles[0] = ICurvePriceOracle(crvUSDUSDCStableswap2Pool);
_oracles[1] = ICurvePriceOracle(tricryptoUSDCPool);
bytes4[] memory _selectors = new bytes4[](2);
_selectors[0] = CurveChainedOracles.PRICE_ORACLE_SELECTOR;
_selectors[1] = CurveChainedOracles.PRICE_ORACLE_UINT256_SELECTOR;
uint8[] memory _coins = new uint8[](2);
_coins[1] = 1;
bool[] memory _invert = new bool[](2);
_invert[0] = false;
_invert[1] = true;
_feeOracle.modifyChainedOracleForInstance(
_instance, _oracles, _selectors, _coins, _invert, "ETH/CRVUSD"
);
}
}