2023-06-10 03:14:20 +03:00
|
|
|
// 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
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
import { TornadoProposalTest } from "./TornadoProposalTest.sol";
|
2023-06-16 04:12:39 +03:00
|
|
|
|
2023-06-10 03:14:20 +03:00
|
|
|
import { IGovernance, Proposal } from "common/interfaces/IGovernance.sol";
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
import { IUniswapV2Pair } from "src/v2/interfaces/IUniswapV2Pair.sol";
|
|
|
|
|
2023-06-10 03:14:20 +03:00
|
|
|
import { TornadoAddresses } from "common/TornadoAddresses.sol";
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
import { FeeOracleManager, FeeDataForOracle, InstanceWithFee } from "src/v2/FeeOracleManager.sol";
|
|
|
|
|
2023-06-16 04:12:39 +03:00
|
|
|
import { UniswapFeeOracle } from "src/v2/UniswapFeeOracle.sol";
|
2023-06-10 03:14:20 +03:00
|
|
|
|
|
|
|
import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "src/v2/CurveFeeOracle.sol";
|
|
|
|
|
2023-06-16 19:12:22 +03:00
|
|
|
import { InstanceState } from "src/v2/InstanceRegistry.sol";
|
2023-06-10 03:14:20 +03:00
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
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 {
|
2023-06-16 04:12:39 +03:00
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
// Tokens - constant
|
|
|
|
|
|
|
|
IERC20 internal constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
|
|
|
|
|
|
|
|
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
|
|
|
|
|
|
|
// Contracts - constant
|
|
|
|
|
2023-06-16 04:12:39 +03:00
|
|
|
FeeOracleManager public constant feeOracleManager =
|
|
|
|
FeeOracleManager(0x5f6c97C6AD7bdd0AE7E0Dd4ca33A4ED3fDabD4D7);
|
2023-06-10 03:14:20 +03:00
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
IUniswapV2Pair public constant uniTornPool = IUniswapV2Pair(0x0C722a487876989Af8a05FFfB6e32e45cc23FB3A);
|
|
|
|
|
2023-06-10 03:14:20 +03:00
|
|
|
address public constant crvUSDUSDCStableswap2Pool = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
|
|
|
|
|
|
|
|
address public constant tricryptoUSDCPool = 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B;
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
// Contracts - mutable
|
2023-06-10 03:14:20 +03:00
|
|
|
|
2023-06-16 04:12:39 +03:00
|
|
|
UniswapFeeOracle uniswapFeeOracle;
|
2023-06-10 03:14:20 +03:00
|
|
|
|
|
|
|
CurveFeeOracle feeOracle;
|
|
|
|
|
2023-06-16 04:12:39 +03:00
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TESTING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
2023-06-10 03:14:20 +03:00
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
function setUp() public virtual override {
|
2023-06-10 03:14:20 +03:00
|
|
|
vm.createSelectFork(vm.envString("MAINNET_RPC_URL"));
|
2023-06-16 22:49:44 +03:00
|
|
|
vm.rollFork(17_493_778);
|
|
|
|
|
|
|
|
uniswapFeeOracle = new UniswapFeeOracle(address(this), address(this));
|
2023-06-10 03:14:20 +03:00
|
|
|
|
2023-06-16 04:12:39 +03:00
|
|
|
uniswapFeeOracle.setMinObservationCardinality(10);
|
2023-06-16 22:49:44 +03:00
|
|
|
uniswapFeeOracle.setPoolFeeForToken(WETH, 0);
|
2023-06-10 03:14:20 +03:00
|
|
|
|
|
|
|
feeOracle = new CurveFeeOracle(address(this));
|
2023-06-16 19:12:22 +03:00
|
|
|
feeOracle.setTornOracleIsUniswap(false);
|
2023-06-16 04:12:39 +03:00
|
|
|
feeOracle.setUniswapFeeOracle(uniswapFeeOracle);
|
2023-06-10 03:14:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function test_curveFeeSingleTricrypto() public {
|
|
|
|
_setCurveFeeSimpleTricryptoOracleForInstance(feeOracle, cu10_000); // CRVUSD 10_000
|
|
|
|
|
|
|
|
console2.log(
|
|
|
|
"\nShould be 30 * (ETH/USD) ------------------------------------------------\n",
|
|
|
|
uint256(
|
|
|
|
feeOracle.getFee(
|
2023-06-16 19:12:22 +03:00
|
|
|
TORN,
|
|
|
|
InstanceWithFee({
|
|
|
|
logic: cu10_000,
|
|
|
|
state: InstanceState(IERC20(cu10_000.token()), 0, true, true),
|
|
|
|
fee: FeeDataForOracle(0, 30, 10_000, 2 days, 0)
|
|
|
|
})
|
2023-06-10 03:14:20 +03:00
|
|
|
)
|
|
|
|
),
|
|
|
|
"\n------------------------------------------------------------------------\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function test_curveFeeChainedTORN() public {
|
2023-06-16 22:49:44 +03:00
|
|
|
uint256 timeBeforeSwap = now;
|
|
|
|
|
2023-06-16 19:12:22 +03:00
|
|
|
feeOracle.setTornOracleIsUniswap(true);
|
2023-06-10 03:14:20 +03:00
|
|
|
|
|
|
|
_setCurveFeeChainedOracleForInstance(feeOracle, cu10_000); // CRVUSD 10_000
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
_advanceTORNETHMarket();
|
|
|
|
|
|
|
|
uniswapFeeOracle.update(
|
|
|
|
TORN,
|
|
|
|
InstanceWithFee({
|
|
|
|
logic: cu10_000,
|
|
|
|
state: InstanceState(IERC20(address(0)), 0, false, false),
|
|
|
|
fee: FeeDataForOracle(0, 0, 0, 0, uint32(timeBeforeSwap))
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
2023-06-10 03:14:20 +03:00
|
|
|
console2.log(
|
|
|
|
"\nTORN Fee calculated ------------------------------------------------------\n",
|
|
|
|
uint256(
|
|
|
|
feeOracle.getFee(
|
2023-06-16 19:12:22 +03:00
|
|
|
TORN,
|
|
|
|
InstanceWithFee({
|
|
|
|
logic: cu10_000,
|
|
|
|
state: InstanceState(IERC20(cu10_000.token()), 0, true, true),
|
2023-06-16 22:49:44 +03:00
|
|
|
fee: FeeDataForOracle(0, 30, 10_000, 2 days, uint32(timeBeforeSwap))
|
2023-06-16 19:12:22 +03:00
|
|
|
})
|
2023-06-10 03:14:20 +03:00
|
|
|
)
|
|
|
|
),
|
|
|
|
"\n------------------------------------------------------------------------\n"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
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"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-16 04:12:39 +03:00
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
2023-06-10 03:14:20 +03:00
|
|
|
|
2023-06-16 22:49:44 +03:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2023-06-10 03:14:20 +03:00
|
|
|
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"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|