Skip to content

Commit

Permalink
test: add ChainlinkPairOracle tests
Browse files Browse the repository at this point in the history
  • Loading branch information
MerlinEgalite committed Aug 19, 2023
1 parent 96cef4e commit 721e0ff
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
91 changes: 91 additions & 0 deletions test/forge/ChainlinkPairOracle.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "./mocks/ChainlinkAggregatorV3Mock.sol";
import "./mocks/ERC20Mock.sol";

import "contracts/oracles/ChainlinkPairOracle.sol";

import {FullMath} from "@uniswap/v3-core/libraries/FullMath.sol";

import "@forge-std/Test.sol";

contract ChainlinkOracleTest is Test {
ChainlinkAggregatorV3Mock collateralFeed;
ChainlinkAggregatorV3Mock borrowableFeed;
ChainlinkPairOracle chainlinkOracle;
ERC20Mock collateral;
ERC20Mock borrowable;
uint256 SCALE;
uint8 COLLATERAL_DECIMALS = 8;
uint8 BORROWABLE_DECIMALS = 10;

function setUp() public {
collateral = new ERC20Mock("Collateral", "COL", 18);
borrowable = new ERC20Mock("Borrowable", "BOR", 8);

collateralFeed = new ChainlinkAggregatorV3Mock();
borrowableFeed = new ChainlinkAggregatorV3Mock();

collateralFeed.setDecimals(COLLATERAL_DECIMALS);
borrowableFeed.setDecimals(BORROWABLE_DECIMALS);

SCALE = 1e26; // 1e36 * 10 ** (8 - 18);

chainlinkOracle = new ChainlinkPairOracle(address(collateralFeed), address(borrowableFeed), SCALE);
}

function testConfig() public {
assertEq(address(chainlinkOracle.CHAINLINK_COLLATERAL_FEED()), address(collateralFeed));
assertEq(address(chainlinkOracle.CHAINLINK_BORROWABLE_FEED()), address(borrowableFeed));
assertEq(chainlinkOracle.CHAINLINK_COLLATERAL_PRICE_SCALE(), 10 ** COLLATERAL_DECIMALS);
assertEq(chainlinkOracle.CHAINLINK_BORROWABLE_PRICE_SCALE(), 10 ** BORROWABLE_DECIMALS);
assertEq(chainlinkOracle.PRICE_SCALE(), SCALE);
}

function testPrice(
uint256 collateralDecimals,
uint256 borrowableDecimals,
uint256 collateralPrice,
uint256 borrowablePrice,
uint256 collateralFeedDecimals,
uint256 borrowableFeedDecimals
) public {
collateralDecimals = bound(collateralDecimals, 6, 18);
borrowableDecimals = bound(borrowableDecimals, 6, 18);
collateralFeedDecimals = bound(collateralFeedDecimals, 6, 18);
borrowableFeedDecimals = bound(borrowableFeedDecimals, 6, 18);
// Cap prices at $10M.
collateralPrice = bound(collateralPrice, 1, 10_000_000);
borrowablePrice = bound(borrowablePrice, 1, 10_000_000);

// Create tokens.
collateral = new ERC20Mock("Collateral", "COL", uint8(collateralDecimals));
borrowable = new ERC20Mock("Borrowable", "BOR", uint8(borrowableDecimals));

collateralPrice = collateralPrice * 10 ** collateralFeedDecimals;
borrowablePrice = borrowablePrice * 10 ** borrowableFeedDecimals;

collateralFeed = new ChainlinkAggregatorV3Mock();
borrowableFeed = new ChainlinkAggregatorV3Mock();

collateralFeed.setDecimals(uint8(collateralFeedDecimals));
borrowableFeed.setDecimals(uint8(borrowableFeedDecimals));

collateralFeed.setLatestAnswer(int256(collateralPrice));
borrowableFeed.setLatestAnswer(int256(borrowablePrice));

uint256 scale = collateralDecimals > borrowableDecimals
? 1e36 / 10 ** (collateralDecimals - borrowableDecimals)
: 1e36 * (borrowableDecimals - collateralDecimals); // 1e36 * 10 ** (borrow decimals - collateral decimals);

chainlinkOracle = new ChainlinkPairOracle(address(collateralFeed), address(borrowableFeed), scale);

assertEq(
chainlinkOracle.price(),
FullMath.mulDiv(
collateralPrice * 10 ** borrowableFeedDecimals, scale, borrowablePrice * 10 ** collateralFeedDecimals
)
);
}
}
35 changes: 35 additions & 0 deletions test/forge/mocks/ChainlinkAggregatorV3Mock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IChainlinkAggregatorV3} from "contracts/oracles/adapters/interfaces/IChainlinkAggregatorV3.sol";

contract ChainlinkAggregatorV3Mock is IChainlinkAggregatorV3 {
string public description = "desciption";
uint256 public version = 1;
uint8 public decimals;
int256 latestAnswer;

function setDecimals(uint8 newDecimals) external {
decimals = newDecimals;
}

function setLatestAnswer(int256 newAnswer) external {
latestAnswer = newAnswer;
}

function getRoundData(uint80)
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
{
return (1, latestAnswer, 0, 0, 0);
}

function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
{
return (1, latestAnswer, 0, 0, 0);
}
}

0 comments on commit 721e0ff

Please sign in to comment.