Skip to content
This repository has been archived by the owner on Aug 26, 2024. It is now read-only.

Commit

Permalink
wrote tests for getUnderlyingPrice
Browse files Browse the repository at this point in the history
  • Loading branch information
jourdanDunkley committed May 20, 2024
1 parent d978fb0 commit 2e02584
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 1 deletion.
46 changes: 45 additions & 1 deletion contracts/oracles/MasterPriceOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,31 @@ contract MasterPriceOracle is Initializable, BasePriceOracle {
}
}

/**
* @dev Sets `_oracles` for `underlyings`.
*/
function addFallbacks(address[] calldata underlyings, BasePriceOracle[] calldata _oracles) external onlyAdmin {
// Input validation
require(
underlyings.length > 0 && underlyings.length == _oracles.length,
"Lengths of both arrays must be equal and greater than 0."
);

// Assign oracles to underlying tokens
for (uint256 i = 0; i < underlyings.length; i++) {
address underlying = underlyings[i];
address oldOracle = address(fallbackOracles[underlying]);
if (noAdminOverwrite)
require(
oldOracle == address(0),
"Admin cannot overwrite existing assignments of oracles to underlying tokens."
);
BasePriceOracle newOracle = _oracles[i];
fallbackOracles[underlying] = newOracle;
emit NewOracle(underlying, oldOracle, address(newOracle));
}
}

/**
* @dev Changes the default price oracle
*/
Expand Down Expand Up @@ -159,7 +184,26 @@ contract MasterPriceOracle is Initializable, BasePriceOracle {
function getUnderlyingPrice(ICErc20 cToken) external view override returns (uint256) {
// Get underlying ERC20 token address
address underlying = address(ICErc20(address(cToken)).underlying());
return price(underlying);

if (underlying == wtoken) return 1e18;

BasePriceOracle oracle = oracles[underlying];
BasePriceOracle fallbackOracle = fallbackOracles[underlying];

if (address(oracle) != address(0)) {
try oracle.getUnderlyingPrice(cToken) returns (uint256 underlyingPrice) {
if (underlyingPrice == 0) {
if (address(fallbackOracle) != address(0)) return fallbackOracle.getUnderlyingPrice(cToken);
} else {
return underlyingPrice;
}
} catch {
if (address(fallbackOracle) != address(0)) return fallbackOracle.getUnderlyingPrice(cToken);
}
} else {
if (address(fallbackOracle) != address(0)) return fallbackOracle.getUnderlyingPrice(cToken);
}
revert("Price oracle not found for this underlying token address.");
}

/**
Expand Down
115 changes: 115 additions & 0 deletions contracts/test/oracles/default/MasterPriceOracleTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;

import { BaseTest } from "../../config/BaseTest.t.sol";
import { MasterPriceOracle } from "../../../oracles/MasterPriceOracle.sol";
import { BasePriceOracle } from "../../../oracles/BasePriceOracle.sol";
import { ICErc20 } from "../../../compound/CTokenInterfaces.sol";
import { SimplePriceOracle } from "../../../oracles/default/SimplePriceOracle.sol";
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

contract MasterPriceOracleTest is BaseTest {
MasterPriceOracle mpo;
SimplePriceOracle mainOracle;
SimplePriceOracle fallbackOracle;
ICErc20 mockCToken;
address someAdminAccount = address(94949);
address ezETH = 0x2416092f143378750bb29b79eD961ab195CcEea5;
address ionezETH = 0x59e710215d45F584f44c0FEe83DA6d43D762D857;

function afterForkSetUp() internal override {
MasterPriceOracle newMpo = new MasterPriceOracle();
SimplePriceOracle defaultOracle = new SimplePriceOracle();

address[] memory underlyings = new address[](0);
BasePriceOracle[] memory oracles = new BasePriceOracle[](0);

vm.prank(someAdminAccount);
newMpo.initialize(underlyings, oracles, defaultOracle, someAdminAccount, true, address(0));

mpo = newMpo;

SimplePriceOracle impl = new SimplePriceOracle();
vm.prank(address(someAdminAccount));
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(impl),
address(dpa),
abi.encodePacked(impl.initialize.selector)
);
mainOracle = SimplePriceOracle(address(proxy));

SimplePriceOracle fallbackImpl = new SimplePriceOracle();
vm.prank(address(someAdminAccount));
TransparentUpgradeableProxy fallbackProxy = new TransparentUpgradeableProxy(
address(fallbackImpl),
address(dpa),
abi.encodePacked(impl.initialize.selector)
);
fallbackOracle = SimplePriceOracle(address(fallbackProxy));

vm.startPrank(someAdminAccount);
mainOracle.setDirectPrice(ezETH, 2000);
fallbackOracle.setDirectPrice(ezETH, 2000);
vm.stopPrank();

address[] memory tokens = new address[](1);
tokens[0] = ezETH;

BasePriceOracle[] memory oraclesToAdd = new BasePriceOracle[](1);
oraclesToAdd[0] = BasePriceOracle(mainOracle);
BasePriceOracle[] memory fallbackOraclesToAdd = new BasePriceOracle[](1);
fallbackOraclesToAdd[0] = BasePriceOracle(fallbackOracle);

vm.startPrank(someAdminAccount);
mpo.add(tokens, oraclesToAdd);
mpo.addFallbacks(tokens, fallbackOraclesToAdd);
vm.stopPrank();
}

function testGetUnderlyingPrice() public fork(MODE_MAINNET) {
vm.prank(someAdminAccount);
uint256 price = mpo.getUnderlyingPrice(ICErc20(ionezETH));
assertEq(price, 2000, "Price should match the mock price");
}

function testGetUnderlyingPriceZero() public fork(MODE_MAINNET) {
vm.prank(someAdminAccount);
mainOracle.setDirectPrice(ezETH, 0);
uint256 price = mpo.getUnderlyingPrice(ICErc20(ionezETH));
assertEq(price, 2000, "Price should match the mock price");
}

function testGetUnderlyingPriceZeroAddressOracle() public fork(MODE_MAINNET) {
address[] memory tokens = new address[](1);
tokens[0] = ezETH;

BasePriceOracle[] memory oraclesToAdd = new BasePriceOracle[](1);
oraclesToAdd[0] = BasePriceOracle(0x0000000000000000000000000000000000000000);

vm.prank(someAdminAccount);
mpo.add(tokens, oraclesToAdd);

uint256 price = mpo.getUnderlyingPrice(ICErc20(ionezETH));
assertEq(price, 2000, "Price should match the mock price");
}

function testGetUnderlyingPriceOracleReverts() public fork(MODE_MAINNET) {
revert("TODO");
}

function testPrice() public fork(MODE_MAINNET) {
revert("TODO");
}

function testPriceZero() public fork(MODE_MAINNET) {
revert("TODO");
}

function testPriceZeroAddressOracle() public fork(MODE_MAINNET) {
revert("TODO");
}

function testPriceOracleReverts() public fork(MODE_MAINNET) {
revert("TODO");
}
}

0 comments on commit 2e02584

Please sign in to comment.