Closed wtj2021 closed 9 months ago
@wtj2021 l think it would be great to specify on deployment whether the dynamic feed will be used or not, so the system is able to fetch the correct chainlink responses.
constructor(
address _fallbackCallerAddress,
address _authorityAddress,
address _collEthCLFeed,
address _ethBtcCLFeed,
+ bool _useDynamicFeed
) {
fallbackCaller = IFallbackCaller(_fallbackCallerAddress);
_initializeAuthority(_authorityAddress);
emit FallbackCallerChanged(address(0), _fallbackCallerAddress);
ETH_BTC_CL_FEED = AggregatorV3Interface(_ethBtcCLFeed);
STETH_ETH_CL_FEED = AggregatorV3Interface(_collEthCLFeed);
STETH_ETH_FIXED_FEED = new FixedAdapter();
uint8 ethBtcDecimals = ETH_BTC_CL_FEED.decimals();
require(ethBtcDecimals <= MAX_DECIMALS);
uint8 stEthEthDecimals = STETH_ETH_CL_FEED.decimals();
require(stEthEthDecimals <= MAX_DECIMALS);
DENOMINATOR =
10 ** ((stEthEthDecimals > ethBtcDecimals ? stEthEthDecimals : ethBtcDecimals) * 2);
SCALED_DECIMAL = stEthEthDecimals > ethBtcDecimals
? 10 ** (stEthEthDecimals - ethBtcDecimals)
: 10 ** (ethBtcDecimals - stEthEthDecimals);
+ useDynamicFeed = _useDynamicFeed;
// Get an initial price from Chainlink to serve as first reference for lastGoodPrice
ChainlinkResponse memory chainlinkResponse = _getCurrentChainlinkResponse();
ChainlinkResponse memory prevChainlinkResponse = _getPrevChainlinkResponse(
chainlinkResponse.roundEthBtcId,
chainlinkResponse.roundStEthEthId
);
require(
!_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse) &&
!_chainlinkIsFrozen(chainlinkResponse),
"PriceFeed: Chainlink must be working and current"
);
_storeChainlinkPrice(chainlinkResponse.answer);
// Explicitly set initial system status after `require` checks
status = Status.chainlinkWorking;
// emit STETH_ETH_FIXED_FEED address
emit CollateralFeedSourceUpdated(address(_collateralFeed()));
}
Job ID | aac3bd22-a4b4-4b01-9abf-9e4413c42930 |
Command | yarn && git submodule init && git submodule update && solc-select use 0.8.17 && cd packages/contracts/ && yarn echidna --test-mode assertion --test-limit 600000 |
Instance ID | i-0610f6ccfcde4a836 |
Instance Type | c5.2xlarge |
Status | Started |
Elapsed |
Job ID | aac3bd22-a4b4-4b01-9abf-9e4413c42930 |
Command | yarn && git submodule init && git submodule update && solc-select use 0.8.17 && cd packages/contracts/ && yarn echidna --test-mode assertion --test-limit 600000 |
Instance ID | i-0610f6ccfcde4a836 |
Instance Type | c5.2xlarge |
Status | Running |
Elapsed | 1 minute 12 seconds |
Job ID | aac3bd22-a4b4-4b01-9abf-9e4413c42930 |
Command | yarn && git submodule init && git submodule update && solc-select use 0.8.17 && cd packages/contracts/ && yarn echidna --test-mode assertion --test-limit 600000 |
Instance ID | i-0610f6ccfcde4a836 |
Instance Type | c5.2xlarge |
Status | Running |
Elapsed | 1 minute 13 seconds |
Job ID | aac3bd22-a4b4-4b01-9abf-9e4413c42930 |
Command | yarn && git submodule init && git submodule update && solc-select use 0.8.17 && cd packages/contracts/ && yarn echidna --test-mode assertion --test-limit 600000 |
Instance ID | i-0610f6ccfcde4a836 |
Instance Type | c5.2xlarge |
Status | Success |
Elapsed | 1 day 8 hours 45 minutes 33 seconds |
This change rounds out the rest of the PRs , especially for ChainlinkAdapter
By adding the fixed price oracle we can quickly write E2E integration tests
See a quick and dirty example that I wrote on ebtc-chainlink-oracle-adapter
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import "forge-std/Test.sol";
import {MockAggregator} from "../contracts/TestContracts/MockAggregator.sol";
import {ChainlinkAdapter} from "../contracts/ChainlinkAdapter.sol";
import {PriceFeedTester} from "../contracts/TestContracts/PriceFeedTester.sol";
// Integration test of the Price Feed
contract PriceFeedChainlinkAdapter is Test {
MockAggregator internal usdBtcAggregator;
MockAggregator internal ethUsdAggregator;
ChainlinkAdapter internal chainlinkAdapter;
PriceFeedTester internal priceFeed;
function setUp() public {
usdBtcAggregator = new MockAggregator();
ethUsdAggregator = new MockAggregator();
chainlinkAdapter = new ChainlinkAdapter(usdBtcAggregator, ethUsdAggregator);
usdBtcAggregator.setLatestRoundId(110680464442257320246);
usdBtcAggregator.setPrevRoundId(110680464442257320245);
usdBtcAggregator.setPrice(3983705362408);
usdBtcAggregator.setPrevPrice(3983705362408);
usdBtcAggregator.setUpdateTime(block.timestamp);
ethUsdAggregator.setLatestRoundId(110680464442257320664);
ethUsdAggregator.setPrevRoundId(110680464442257320663);
ethUsdAggregator.setPrice(221026137517);
ethUsdAggregator.setPrevPrice(221026137517);
ethUsdAggregator.setUpdateTime(block.timestamp);
priceFeed = new PriceFeedTester(
address(0),
address(0),
address(chainlinkAdapter),
address(chainlinkAdapter) // NOTE: WRONG | /// TODO: Replace with this feed in this pr!
);
}
function testIntegrationLatestRound() public {
usdBtcAggregator.setLatestRoundId(110680464442257320247);
usdBtcAggregator.setPrevRoundId(110680464442257320246);
usdBtcAggregator.setPrice(3983705362408);
usdBtcAggregator.setUpdateTime(1706208946);
ethUsdAggregator.setLatestRoundId(110680464442257320665);
ethUsdAggregator.setPrevRoundId(110680464442257320664);
ethUsdAggregator.setPrice(221026137517);
ethUsdAggregator.setUpdateTime(1706208947);
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
chainlinkAdapter.latestRoundData();
assertEq(answer, 55482551396170026);
assertEq(roundId, chainlinkAdapter.CURRENT_ROUND());
assertEq(updatedAt, 1706208946);
priceFeed.fetchPrice();
}
}
I would recommend merging down to one PR and then doing more extensive integration tests
Specifically:
Fully tracking the precision loss is ideal