Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor oracles #70

Merged
merged 23 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9c3d9df
refactor: draft
MerlinEgalite Aug 20, 2023
028c76a
refactor: fix inheritance graph
MerlinEgalite Aug 20, 2023
e50caf4
chore: disable via ir to allow compilation
MerlinEgalite Aug 20, 2023
1bf5581
fix: correct visibility
MerlinEgalite Aug 21, 2023
3057612
refactor: explicit overriding
MerlinEgalite Aug 21, 2023
909bc7e
docs: add oracle doc
MerlinEgalite Aug 21, 2023
7e24a8d
feat: use lib
MerlinEgalite Aug 21, 2023
5218701
refactor(oracle): remove redundant overrides
Rubilmax Aug 21, 2023
57ead6e
refactor(oracle): remove redundant getters
Rubilmax Aug 21, 2023
63ba502
refactor(format): format BundleAction
Rubilmax Aug 21, 2023
baa19fa
Merge branch 'refactor/oracles' of github.com:morpho-labs/morpho-blue…
Rubilmax Aug 21, 2023
d14ed62
test(oracle): fix tests
Rubilmax Aug 21, 2023
2604607
fix: static
MerlinEgalite Aug 21, 2023
555d822
Merge pull request #74 from morpho-labs/refactor/oracles-base
MerlinEgalite Aug 21, 2023
b990b59
test: remove console.log oops
MerlinEgalite Aug 21, 2023
d51bbca
docs: apply suggestions
MerlinEgalite Aug 21, 2023
6754f81
chore: roll back foundry config
MerlinEgalite Aug 21, 2023
5929304
refactor: capital letters + immutables
MerlinEgalite Aug 21, 2023
22d9a75
refactor: less verbose naming
MerlinEgalite Aug 21, 2023
ab57765
refactor: use immutables in BaseOracle directly
MerlinEgalite Aug 21, 2023
f8019b3
Merge pull request #77 from morpho-labs/refactor/oracles-3
MerlinEgalite Aug 21, 2023
d5baa2f
Merge pull request #76 from morpho-labs/refactor/oracles-2
MerlinEgalite Aug 21, 2023
1634554
docs: apply suggestion
MerlinEgalite Aug 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions contracts/oracles/BaseOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IOracle} from "./interfaces/IOracle.sol";

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

abstract contract BaseOracle is IOracle {
/// @dev The scale must be 1e36 * 10^(decimals of borrowable token - decimals of collateral token).
uint256 public immutable PRICE_SCALE;

constructor(uint256 priceScale) {
PRICE_SCALE = priceScale;
}

function price() external view returns (uint256) {
return FullMath.mulDiv(
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved
collateralToBasePrice() * borrowableScale(),
PRICE_SCALE, // Using FullMath to avoid overflowing because of PRICE_SCALE.
borrowableToBasePrice() * collateralScale()
);
}

function collateralScale() public view virtual returns (uint256) {}
function borrowableScale() public view virtual returns (uint256) {}
function collateralToBasePrice() public view virtual returns (uint256) {}
function borrowableToBasePrice() public view virtual returns (uint256) {}
}
28 changes: 14 additions & 14 deletions contracts/oracles/ChainlinkOracle.sol
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

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

import {OracleFeed} from "./libraries/OracleFeed.sol";
import {ChainlinkAggregatorV3Lib} from "./libraries/ChainlinkAggregatorV3Lib.sol";

import {BaseOracle} from "./BaseOracle.sol";
import {NeutralBorrowableAdapter} from "./adapters/NeutralBorrowableAdapter.sol";
import {ChainlinkCollateralAdapter} from "./adapters/ChainlinkCollateralAdapter.sol";

contract ChainlinkOracle is ChainlinkCollateralAdapter, IOracle {
using ChainlinkAggregatorV3Lib for IChainlinkAggregatorV3;
contract ChainlinkOracle is BaseOracle, ChainlinkCollateralAdapter, NeutralBorrowableAdapter {
constructor(address feed, uint256 priceScale) BaseOracle(priceScale) ChainlinkCollateralAdapter(feed) {}

constructor(address feed) ChainlinkCollateralAdapter(feed) {}
function collateralScale() public view override(BaseOracle, ChainlinkCollateralAdapter) returns (uint256) {
return super.collateralScale();
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
}

function FEED_COLLATERAL() external view returns (string memory, address) {
return (OracleFeed.CHAINLINK_V3, address(CHAINLINK_COLLATERAL_FEED));
function borrowableScale() public view override(BaseOracle, NeutralBorrowableAdapter) returns (uint256) {
return super.borrowableScale();
}

function FEED_BORROWABLE() external view returns (string memory, address) {}
function collateralToBasePrice() public view override(BaseOracle, ChainlinkCollateralAdapter) returns (uint256) {
return super.collateralToBasePrice();
}

function price() external view returns (uint256) {
return CHAINLINK_COLLATERAL_FEED.price();
function borrowableToBasePrice() public view override(BaseOracle, NeutralBorrowableAdapter) returns (uint256) {
return super.borrowableToBasePrice();
}
}
40 changes: 14 additions & 26 deletions contracts/oracles/ChainlinkPairOracle.sol
Original file line number Diff line number Diff line change
@@ -1,42 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

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

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

import {BaseOracle} from "./BaseOracle.sol";
import {ChainlinkCollateralAdapter} from "./adapters/ChainlinkCollateralAdapter.sol";
import {ChainlinkBorrowableAdapter} from "./adapters/ChainlinkBorrowableAdapter.sol";

contract ChainlinkPairOracle is ChainlinkCollateralAdapter, ChainlinkBorrowableAdapter, IOracle {
using ChainlinkAggregatorV3Lib for IChainlinkAggregatorV3;

/// @dev The scale must be 1e36 * 10^(decimals of borrowable token - decimals of collateral token).
uint256 public immutable PRICE_SCALE;

constructor(address collateralFeed, address borrowableFeed, uint256 scale)
contract ChainlinkPairOracle is BaseOracle, ChainlinkCollateralAdapter, ChainlinkBorrowableAdapter {
constructor(address collateralFeed, address borrowableFeed, uint256 priceScale)
BaseOracle(priceScale)
ChainlinkCollateralAdapter(collateralFeed)
ChainlinkBorrowableAdapter(borrowableFeed)
{
PRICE_SCALE = scale;
{}

function collateralScale() public view override(BaseOracle, ChainlinkCollateralAdapter) returns (uint256) {
return super.collateralScale();
}

function FEED_COLLATERAL() external view returns (string memory, address) {
return (OracleFeed.CHAINLINK_V3, address(CHAINLINK_COLLATERAL_FEED));
function borrowableScale() public view override(BaseOracle, ChainlinkBorrowableAdapter) returns (uint256) {
return super.borrowableScale();
}

function FEED_BORROWABLE() external view returns (string memory, address) {
return (OracleFeed.CHAINLINK_V3, address(CHAINLINK_BORROWABLE_FEED));
function collateralToBasePrice() public view override(BaseOracle, ChainlinkCollateralAdapter) returns (uint256) {
return super.collateralToBasePrice();
}

function price() external view returns (uint256) {
return FullMath.mulDiv(
CHAINLINK_COLLATERAL_FEED.price() * CHAINLINK_BORROWABLE_PRICE_SCALE,
PRICE_SCALE, // Using FullMath to avoid overflowing because of PRICE_SCALE.
CHAINLINK_BORROWABLE_FEED.price() * CHAINLINK_COLLATERAL_PRICE_SCALE
);
function borrowableToBasePrice() public view override(BaseOracle, ChainlinkBorrowableAdapter) returns (uint256) {
return super.borrowableToBasePrice();
}
}
45 changes: 14 additions & 31 deletions contracts/oracles/ChainlinkUniswapV3Oracle.sol
Original file line number Diff line number Diff line change
@@ -1,47 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IOracle} from "./interfaces/IOracle.sol";
import {IUniswapV3Pool} from "@uniswap/v3-core/interfaces/IUniswapV3Pool.sol";
import {IChainlinkAggregatorV3} from "./adapters/interfaces/IChainlinkAggregatorV3.sol";

import {OracleFeed} from "./libraries/OracleFeed.sol";
import {WAD, MathLib} from "@morpho-blue/libraries/MathLib.sol";
import {FullMath} from "@uniswap/v3-core/libraries/FullMath.sol";
import {UniswapV3PoolLib} from "./libraries/UniswapV3PoolLib.sol";
import {ChainlinkAggregatorV3Lib} from "./libraries/ChainlinkAggregatorV3Lib.sol";

import {BaseOracle} from "./BaseOracle.sol";
import {ChainlinkCollateralAdapter} from "./adapters/ChainlinkCollateralAdapter.sol";
import {UniswapV3BorrowableAdapter} from "./adapters/UniswapV3BorrowableAdapter.sol";

contract ChainlinkUniswapV3Oracle is ChainlinkCollateralAdapter, UniswapV3BorrowableAdapter, IOracle {
using MathLib for uint256;
using UniswapV3PoolLib for IUniswapV3Pool;
using ChainlinkAggregatorV3Lib for IChainlinkAggregatorV3;

/// @dev The scale must be 1e36 * 10^(decimals of borrowable token - decimals of collateral token).
uint256 public immutable PRICE_SCALE;

constructor(address feed, address pool, uint32 borrowablePriceDelay, uint256 scale)
contract ChainlinkUniswapV3Oracle is BaseOracle, ChainlinkCollateralAdapter, UniswapV3BorrowableAdapter {
constructor(address feed, address pool, uint32 borrowablePriceDelay, uint256 priceScale)
BaseOracle(priceScale)
ChainlinkCollateralAdapter(feed)
UniswapV3BorrowableAdapter(pool, borrowablePriceDelay)
{
PRICE_SCALE = scale;
{}

function collateralScale() public view override(BaseOracle, ChainlinkCollateralAdapter) returns (uint256) {
return super.collateralScale();
}

function FEED_COLLATERAL() external view returns (string memory, address) {
return (OracleFeed.CHAINLINK_V3, address(CHAINLINK_COLLATERAL_FEED));
function borrowableScale() public view override(BaseOracle, UniswapV3BorrowableAdapter) returns (uint256) {
return super.borrowableScale();
}

function FEED_BORROWABLE() external view returns (string memory, address) {
return (OracleFeed.UNISWAP_V3, address(UNI_V3_BORROWABLE_POOL));
function collateralToBasePrice() public view override(BaseOracle, ChainlinkCollateralAdapter) returns (uint256) {
return super.collateralToBasePrice();
}

function price() external view returns (uint256) {
return FullMath.mulDiv(
CHAINLINK_COLLATERAL_FEED.price() * WAD,
PRICE_SCALE, // Using FullMath to avoid overflowing because of PRICE_SCALE.
UNI_V3_BORROWABLE_POOL.price(UNI_V3_BORROWABLE_DELAY) * CHAINLINK_COLLATERAL_PRICE_SCALE
);
function borrowableToBasePrice() public view override(BaseOracle, UniswapV3BorrowableAdapter) returns (uint256) {
return super.borrowableToBasePrice();
}
}
45 changes: 14 additions & 31 deletions contracts/oracles/UniswapV3ChainlinkOracle.sol
Original file line number Diff line number Diff line change
@@ -1,47 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IOracle} from "./interfaces/IOracle.sol";
import {IUniswapV3Pool} from "@uniswap/v3-core/interfaces/IUniswapV3Pool.sol";
import {IChainlinkAggregatorV3} from "./adapters/interfaces/IChainlinkAggregatorV3.sol";

import {OracleFeed} from "./libraries/OracleFeed.sol";
import {WAD, MathLib} from "@morpho-blue/libraries/MathLib.sol";
import {FullMath} from "@uniswap/v3-core/libraries/FullMath.sol";
import {UniswapV3PoolLib} from "./libraries/UniswapV3PoolLib.sol";
import {ChainlinkAggregatorV3Lib} from "./libraries/ChainlinkAggregatorV3Lib.sol";

import {BaseOracle} from "./BaseOracle.sol";
import {UniswapV3CollateralAdapter} from "./adapters/UniswapV3CollateralAdapter.sol";
import {ChainlinkBorrowableAdapter} from "./adapters/ChainlinkBorrowableAdapter.sol";

contract UniswapV3ChainlinkOracle is UniswapV3CollateralAdapter, ChainlinkBorrowableAdapter, IOracle {
using MathLib for uint256;
using UniswapV3PoolLib for IUniswapV3Pool;
using ChainlinkAggregatorV3Lib for IChainlinkAggregatorV3;

/// @dev The scale must be 1e36 * 10^(decimals of borrowable token - decimals of collateral token).
uint256 public immutable PRICE_SCALE;

constructor(address pool, address feed, uint32 collateralPriceDelay, uint256 scale)
contract UniswapV3ChainlinkOracle is BaseOracle, UniswapV3CollateralAdapter, ChainlinkBorrowableAdapter {
constructor(address pool, address feed, uint32 collateralPriceDelay, uint256 priceScale)
BaseOracle(priceScale)
UniswapV3CollateralAdapter(pool, collateralPriceDelay)
ChainlinkBorrowableAdapter(feed)
{
PRICE_SCALE = scale;
{}

function collateralScale() public view override(BaseOracle, UniswapV3CollateralAdapter) returns (uint256) {
return super.collateralScale();
}

function FEED_COLLATERAL() external view returns (string memory, address) {
return (OracleFeed.UNISWAP_V3, address(UNI_V3_COLLATERAL_POOL));
function borrowableScale() public view override(BaseOracle, ChainlinkBorrowableAdapter) returns (uint256) {
return super.borrowableScale();
}

function FEED_BORROWABLE() external view returns (string memory, address) {
return (OracleFeed.CHAINLINK_V3, address(CHAINLINK_BORROWABLE_FEED));
function collateralToBasePrice() public view override(BaseOracle, UniswapV3CollateralAdapter) returns (uint256) {
return super.collateralToBasePrice();
}

function price() external view returns (uint256) {
return FullMath.mulDiv(
UNI_V3_COLLATERAL_POOL.price(UNI_V3_COLLATERAL_DELAY) * CHAINLINK_BORROWABLE_PRICE_SCALE,
PRICE_SCALE, // Using FullMath to avoid overflowing because of PRICE_SCALE.
CHAINLINK_BORROWABLE_FEED.price() * WAD
);
function borrowableToBasePrice() public view override(BaseOracle, ChainlinkBorrowableAdapter) returns (uint256) {
return super.borrowableToBasePrice();
}
}
31 changes: 17 additions & 14 deletions contracts/oracles/UniswapV3Oracle.sol
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IOracle} from "./interfaces/IOracle.sol";
import {IUniswapV3Pool} from "@uniswap/v3-core/interfaces/IUniswapV3Pool.sol";

import {OracleFeed} from "./libraries/OracleFeed.sol";
import {UniswapV3PoolLib} from "./libraries/UniswapV3PoolLib.sol";

import {BaseOracle} from "./BaseOracle.sol";
import {NeutralBorrowableAdapter} from "./adapters/NeutralBorrowableAdapter.sol";
import {UniswapV3CollateralAdapter} from "./adapters/UniswapV3CollateralAdapter.sol";

contract UniswapV3Oracle is UniswapV3CollateralAdapter, IOracle {
using UniswapV3PoolLib for IUniswapV3Pool;
contract UniswapV3Oracle is BaseOracle, UniswapV3CollateralAdapter, NeutralBorrowableAdapter {
constructor(address pool, uint32 delay, uint256 priceScale)
BaseOracle(priceScale)
UniswapV3CollateralAdapter(pool, delay)
{}

constructor(address pool, uint32 delay) UniswapV3CollateralAdapter(pool, delay) {}
function collateralScale() public view override(BaseOracle, UniswapV3CollateralAdapter) returns (uint256) {
return super.collateralScale();
}

function FEED_COLLATERAL() external view returns (string memory, address) {
return (OracleFeed.UNISWAP_V3, address(UNI_V3_COLLATERAL_POOL));
function borrowableScale() public view override(BaseOracle, NeutralBorrowableAdapter) returns (uint256) {
return super.borrowableScale();
}

function FEED_BORROWABLE() external view returns (string memory, address) {}
function collateralToBasePrice() public view override(BaseOracle, UniswapV3CollateralAdapter) returns (uint256) {
return super.collateralToBasePrice();
}

function price() external view returns (uint256) {
return UNI_V3_COLLATERAL_POOL.price(UNI_V3_COLLATERAL_DELAY);
function borrowableToBasePrice() public view override(BaseOracle, NeutralBorrowableAdapter) returns (uint256) {
return super.borrowableToBasePrice();
}
}
42 changes: 14 additions & 28 deletions contracts/oracles/UniswapV3PairOracle.sol
Original file line number Diff line number Diff line change
@@ -1,50 +1,36 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IOracle} from "./interfaces/IOracle.sol";
import {IUniswapV3Pool} from "@uniswap/v3-core/interfaces/IUniswapV3Pool.sol";

import {OracleFeed} from "./libraries/OracleFeed.sol";
import {MathLib} from "@morpho-blue/libraries/MathLib.sol";
import {FullMath} from "@uniswap/v3-core/libraries/FullMath.sol";
import {UniswapV3PoolLib} from "./libraries/UniswapV3PoolLib.sol";

import {BaseOracle} from "./BaseOracle.sol";
import {UniswapV3CollateralAdapter} from "./adapters/UniswapV3CollateralAdapter.sol";
import {UniswapV3BorrowableAdapter} from "./adapters/UniswapV3BorrowableAdapter.sol";

contract UniswapV3Oracle is UniswapV3CollateralAdapter, UniswapV3BorrowableAdapter, IOracle {
using MathLib for uint256;
using UniswapV3PoolLib for IUniswapV3Pool;

/// @dev The scale must be 1e36 * 10^(decimals of borrowable token - decimals of collateral token).
uint256 public immutable PRICE_SCALE;

contract UniswapV3Oracle is BaseOracle, UniswapV3CollateralAdapter, UniswapV3BorrowableAdapter {
constructor(
address collateralPool,
address borrowablePool,
uint32 collateralPriceDelay,
uint32 borrowablePriceDelay,
uint256 scale
uint256 priceScale
)
BaseOracle(priceScale)
UniswapV3CollateralAdapter(collateralPool, collateralPriceDelay)
UniswapV3BorrowableAdapter(borrowablePool, borrowablePriceDelay)
{
PRICE_SCALE = scale;
{}

function collateralScale() public view override(BaseOracle, UniswapV3CollateralAdapter) returns (uint256) {
return super.collateralScale();
}

function FEED_COLLATERAL() external view returns (string memory, address) {
return (OracleFeed.UNISWAP_V3, address(UNI_V3_COLLATERAL_POOL));
function borrowableScale() public view override(BaseOracle, UniswapV3BorrowableAdapter) returns (uint256) {
return super.borrowableScale();
}

function FEED_BORROWABLE() external view returns (string memory, address) {
return (OracleFeed.UNISWAP_V3, address(UNI_V3_BORROWABLE_POOL));
function collateralToBasePrice() public view override(BaseOracle, UniswapV3CollateralAdapter) returns (uint256) {
return super.collateralToBasePrice();
}

function price() external view returns (uint256) {
return FullMath.mulDiv(
UNI_V3_COLLATERAL_POOL.price(UNI_V3_COLLATERAL_DELAY),
PRICE_SCALE,
UNI_V3_BORROWABLE_POOL.price(UNI_V3_BORROWABLE_DELAY)
);
function borrowableToBasePrice() public view override(BaseOracle, UniswapV3BorrowableAdapter) returns (uint256) {
return super.borrowableToBasePrice();
}
}
24 changes: 21 additions & 3 deletions contracts/oracles/adapters/ChainlinkBorrowableAdapter.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {IBorrowableAdapter} from "./interfaces/IBorrowableAdapter.sol";
import {IChainlinkAggregatorV3} from "./interfaces/IChainlinkAggregatorV3.sol";

abstract contract ChainlinkBorrowableAdapter {
import {OracleFeed} from "../libraries/OracleFeed.sol";
import {ChainlinkAggregatorV3Lib} from "../libraries/ChainlinkAggregatorV3Lib.sol";

abstract contract ChainlinkBorrowableAdapter is IBorrowableAdapter {
using ChainlinkAggregatorV3Lib for IChainlinkAggregatorV3;

IChainlinkAggregatorV3 public immutable CHAINLINK_BORROWABLE_FEED;
uint256 public immutable CHAINLINK_BORROWABLE_PRICE_SCALE;
uint256 public immutable BORROWABLE_SCALE;

constructor(address feed) {
CHAINLINK_BORROWABLE_FEED = IChainlinkAggregatorV3(feed);
CHAINLINK_BORROWABLE_PRICE_SCALE = 10 ** CHAINLINK_BORROWABLE_FEED.decimals();
BORROWABLE_SCALE = 10 ** CHAINLINK_BORROWABLE_FEED.decimals();
}

function BORROWABLE_FEED() external view returns (string memory, address) {
return (OracleFeed.CHAINLINK_V3, address(CHAINLINK_BORROWABLE_FEED));
}

function borrowableScale() public view virtual returns (uint256) {
return BORROWABLE_SCALE;
}

function borrowableToBasePrice() public view virtual returns (uint256) {
return CHAINLINK_BORROWABLE_FEED.price();
}
}
Loading
Loading