mirror of
https://github.com/Instadapp/fluid-contracts-public.git
synced 2024-07-29 21:57:37 +00:00
155 lines
7.9 KiB
Solidity
155 lines
7.9 KiB
Solidity
// todo //SPDX-License-Identifier: MIT
|
||
pragma solidity 0.8.21;
|
||
|
||
import { IRedstoneOracle } from "../../../contracts/oracle/interfaces/external/IRedstoneOracle.sol";
|
||
import { IUniswapV3Pool } from "../../../contracts/oracle/interfaces/external/IUniswapV3Pool.sol";
|
||
import { UniV3CheckCLRSOracle } from "../../../contracts/oracle/oracles/uniV3CheckCLRSOracle.sol";
|
||
import { ChainlinkStructs, RedstoneStructs } from "../../../contracts/oracle/implementations/structs.sol";
|
||
import { IChainlinkAggregatorV3 } from "../../../contracts/oracle/interfaces/external/IChainlinkAggregatorV3.sol";
|
||
import { UniV3OracleImpl } from "../../../contracts/oracle/implementations/uniV3OracleImpl.sol";
|
||
import { ChainlinkOracleImpl } from "../../../contracts/oracle/implementations/chainlinkOracleImpl.sol";
|
||
import { RedstoneOracleImpl } from "../../../contracts/oracle/implementations/redstoneOracleImpl.sol";
|
||
import { TickMath } from "../../../contracts/oracle/libraries/TickMath.sol";
|
||
import { IFluidOracle } from "../../../contracts/oracle/fluidOracle.sol";
|
||
|
||
import { ErrorTypes } from "../../../contracts/oracle/errorTypes.sol";
|
||
import { Error } from "../../../contracts/oracle/error.sol";
|
||
|
||
import { FluidOracleL2 } from "../../../contracts/oracle/fluidOracleL2.sol";
|
||
import { OracleL2TestSuite } from "./oracleL2TestSuite.t.sol";
|
||
import { OracleTestSuite } from "../oracle/oracleTestSuite.t.sol";
|
||
import { MockChainlinkSequencerUptimeFeed } from "./mocks/mockChainlinkSequencerUptimeFeed.sol";
|
||
|
||
import { CLRS2UniV3CheckCLRSOracleL2 } from "../../../contracts/oracle/oraclesL2/cLRS2UniV3CheckCLRSOracleL2.sol";
|
||
import { UniV3CheckCLRSOracleL2 } from "../../../contracts/oracle/oraclesL2/uniV3CheckCLRSOracleL2.sol";
|
||
import { UniV3CheckCLRSOracleTest } from "../oracle/uniV3CheckCLRSOracle.t.sol";
|
||
|
||
import "forge-std/console2.sol";
|
||
|
||
contract CLRS2UniV3CheckCLRSOracleL2Test is OracleL2TestSuite {
|
||
UniV3CheckCLRSOracle.UniV3CheckCLRSConstructorParams uniV3CheckOracleParams;
|
||
CLRS2UniV3CheckCLRSOracleL2.CLRS2ConstructorParams cLRS2Params;
|
||
|
||
IChainlinkAggregatorV3 internal constant CHAINLINK_FEED_BTC_ETH =
|
||
IChainlinkAggregatorV3(0xdeb288F737066589598e9214E782fa5A8eD689e8);
|
||
|
||
function setUp() public override {
|
||
super.setUp();
|
||
|
||
mockFeed = new MockChainlinkSequencerUptimeFeed();
|
||
|
||
// ETH -> USDC
|
||
uniV3CheckOracleParams = UniV3CheckCLRSOracle.UniV3CheckCLRSConstructorParams({
|
||
uniV3Params: UniV3OracleImpl.UniV3ConstructorParams({
|
||
pool: UNIV3_POOL,
|
||
invertRate: true,
|
||
tWAPMaxDeltaPercents: _getDefaultUniswapTwapDeltasFixed(),
|
||
secondsAgos: _getDefaultSecondAgosFixed()
|
||
}),
|
||
chainlinkParams: ChainlinkStructs.ChainlinkConstructorParams({
|
||
hops: 1,
|
||
feed1: ChainlinkStructs.ChainlinkFeedData({
|
||
feed: CHAINLINK_FEED,
|
||
invertRate: true,
|
||
token0Decimals: 6 // USDC has 6 decimals
|
||
}),
|
||
feed2: ChainlinkStructs.ChainlinkFeedData({
|
||
feed: IChainlinkAggregatorV3(address(0)),
|
||
invertRate: true,
|
||
token0Decimals: 0
|
||
}),
|
||
feed3: ChainlinkStructs.ChainlinkFeedData({
|
||
feed: IChainlinkAggregatorV3(address(0)),
|
||
invertRate: true,
|
||
token0Decimals: 0
|
||
})
|
||
}),
|
||
redstoneOracle: RedstoneStructs.RedstoneOracleData({
|
||
oracle: IRedstoneOracle(address(CHAINLINK_FEED)),
|
||
invertRate: false,
|
||
token0Decimals: 1
|
||
}),
|
||
/// @param rateSource_ which oracle to use as final rate source:
|
||
/// - 1 = UniV3 ONLY (no check),
|
||
/// - 2 = UniV3 with Chainlink / Redstone check
|
||
/// - 3 = Chainlink / Redstone with UniV3 used as check.
|
||
rateSource: 2, // which oracle to use as final rate source
|
||
/// @param mainSource_ which oracle to use as main source:
|
||
/// - 1 = Chainlink ONLY (no fallback)
|
||
/// - 2 = Chainlink with Redstone Fallback
|
||
/// - 3 = Redstone with Chainlink Fallback
|
||
fallbackMainSource: 1, // which oracle to use as CL/RS main source
|
||
rateCheckMaxDeltaPercent: 300 // 3% max delta
|
||
});
|
||
|
||
cLRS2Params = CLRS2UniV3CheckCLRSOracleL2.CLRS2ConstructorParams({
|
||
fallbackMainSource: 1,
|
||
chainlinkParams: ChainlinkStructs.ChainlinkConstructorParams({
|
||
hops: 1,
|
||
feed1: ChainlinkStructs.ChainlinkFeedData({
|
||
feed: CHAINLINK_FEED_BTC_ETH,
|
||
invertRate: false,
|
||
token0Decimals: 8 // BTC has 8 decimals
|
||
}),
|
||
feed2: ChainlinkStructs.ChainlinkFeedData({
|
||
feed: IChainlinkAggregatorV3(address(0)),
|
||
invertRate: false,
|
||
token0Decimals: 0
|
||
}),
|
||
feed3: ChainlinkStructs.ChainlinkFeedData({
|
||
feed: IChainlinkAggregatorV3(address(0)),
|
||
invertRate: false,
|
||
token0Decimals: 0
|
||
})
|
||
}),
|
||
redstoneOracle: RedstoneStructs.RedstoneOracleData({
|
||
oracle: IRedstoneOracle(address(MOCK_REDSTONE_FEED)),
|
||
invertRate: false,
|
||
token0Decimals: 1
|
||
})
|
||
});
|
||
|
||
oracle = new CLRS2UniV3CheckCLRSOracleL2(infoName, cLRS2Params, uniV3CheckOracleParams, address(mockFeed));
|
||
|
||
oracleL2 = FluidOracleL2(address(oracle));
|
||
}
|
||
|
||
function test_getExchangeRate() public {
|
||
// @dev Note test runs at block 18664561 from oracleTestSuite.t.sol rollFork. (Nov-27-2023 05:46:47 PM +UTC)
|
||
|
||
// BTC -> ETH
|
||
(, int256 exchangeRateBtcEth_, , , ) = CHAINLINK_FEED_BTC_ETH.latestRoundData();
|
||
assertEq(exchangeRateBtcEth_, 18360186110774997000); // 18.36 ETH for 1 BTC
|
||
|
||
// uniV3 Oracle for ETH -> USDC
|
||
(int56[] memory tickCumulatives, ) = IUniswapV3Pool(UNIV3_POOL).observe(_getDefaultSecondAgos());
|
||
// tick(imprecise as it's an integer) to price
|
||
int256 twapInterval = 1; // <- prev last (seconds ago) - last (seconds ago), looking at default values its 1 - 0
|
||
uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(
|
||
int24((tickCumulatives[4] - tickCumulatives[3]) / int56(twapInterval))
|
||
);
|
||
uint256 uniV3RateEthUsdc = _invertUniV3Price(_getPriceFromSqrtPriceX96(sqrtPriceX96));
|
||
assertEq(uniV3RateEthUsdc, 2016507218835155315); // ETH -> USDC, scaled to 1e27 precision (* 1e27 / 1e18), 9 decimals more
|
||
|
||
(, , , , , uint256 uniV3OracleexchangeRate_) = UniV3OracleImpl(address(oracle)).uniV3OracleData();
|
||
assertEq(uniV3OracleexchangeRate_, uniV3RateEthUsdc);
|
||
|
||
// final rate combines BTC rate and uniV3 oracle rate.
|
||
uint256 expectedRate = (uint256(exchangeRateBtcEth_) * uniV3RateEthUsdc) / 1e8;
|
||
// 3,70234478315347360392312635137×10¹⁹
|
||
assertEq(expectedRate, 370234478315347360392312635136); // 37.023.447 USDC.
|
||
// result is in 25 decimals: BTC 8 decimals to USDC 6 decimals, scaled to 1e27 -> (1e6* 1e27 / 1e8), 33-8 = 25
|
||
_assertExchangeRatesAllMethods(oracle, expectedRate);
|
||
}
|
||
|
||
function test_getExchangeRate_FailExchangeRatesWEETHChainlinkZero() public {
|
||
cLRS2Params.chainlinkParams.feed1.feed = IChainlinkAggregatorV3(address(MOCK_CHAINLINK_FEED));
|
||
|
||
oracle = new CLRS2UniV3CheckCLRSOracleL2(infoName, cLRS2Params, uniV3CheckOracleParams, address(mockFeed));
|
||
|
||
MOCK_CHAINLINK_FEED.setExchangeRate(0);
|
||
|
||
_assertExchangeRatesAllMethodsReverts(oracle, ErrorTypes.CLRS2UniV3CheckCLRSOracleL2__ExchangeRateZero);
|
||
}
|
||
}
|