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

wstETH/ETH oracle using exchange rate only #65

Merged
merged 50 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
56832e2
feat: add oracle + tests
MerlinEgalite Jan 23, 2024
b667bbe
feat: silence warnings
MerlinEgalite Jan 23, 2024
801b8bd
test: improve test
MerlinEgalite Jan 23, 2024
a9e37df
refactor: remove useless oracle
MerlinEgalite Jan 23, 2024
7e5a972
fix: typo
MerlinEgalite Jan 23, 2024
53cfbcc
refactor: rename to answer
MerlinEgalite Jan 25, 2024
d71392b
refactor: use errors lib
MerlinEgalite Jan 29, 2024
a87343c
refactor: rename file
MerlinEgalite Jan 29, 2024
82cc894
refactor: remove price word
MerlinEgalite Jan 29, 2024
bf53cf6
refactor: use max int + add tests
MerlinEgalite Jan 29, 2024
d0e1327
refactor: rename test file as well
MerlinEgalite Jan 29, 2024
330faa2
refactor: revert on version and getRoundData
MerlinEgalite Jan 30, 2024
2a02855
fix: formatting issue
MerlinEgalite Jan 30, 2024
a5e9b02
refactor: apply suggestions
MerlinEgalite Jan 31, 2024
de4e765
refactor: remover conversion
MerlinEgalite Feb 8, 2024
d59d62b
refactor: remove error
MerlinEgalite Feb 8, 2024
bddff40
refactor: renaming
MerlinEgalite Feb 8, 2024
5a3cc1f
test: add simple tests with ChainlinkOracle
MerlinEgalite Feb 8, 2024
a98d971
Merge branch 'feat/wsteth-oracle' of github.com:morpho-labs/morpho-bl…
MerlinEgalite Feb 8, 2024
935744b
chore: format
MerlinEgalite Feb 8, 2024
5d354fb
refactor: create minimal CL interface
MerlinEgalite Feb 9, 2024
d278495
chore: fmt
MerlinEgalite Feb 9, 2024
e57e0fb
docs: add missing word
MerlinEgalite Feb 10, 2024
ececffb
refactor: update answer computation
MerlinEgalite Feb 12, 2024
282095c
refactor: remove IStEth
MerlinEgalite Feb 12, 2024
589468f
feat: add description
MerlinEgalite Feb 13, 2024
8d13031
refactor: simplify code
MerlinEgalite Feb 13, 2024
bb11beb
Merge pull request #72 from morpho-org/refactor/answer
MerlinEgalite Feb 15, 2024
b20ad57
Merge pull request #71 from morpho-org/refactor/cl-interface
MerlinEgalite Feb 15, 2024
281921c
Merge branch 'main' of github.com:morpho-labs/morpho-blue-oracles int…
MerlinEgalite Feb 15, 2024
2c3f9ff
refactor: rollback change on chainlink
MathisGD Feb 18, 2024
a4b964c
refactor: put oracles in sub folders
MathisGD Feb 18, 2024
bf37d41
chore: fmt
MathisGD Feb 18, 2024
42b004b
Merge pull request #75 from morpho-org/refactor/repo
MathisGD Feb 18, 2024
d21e940
docs: minor improvement
MathisGD Feb 19, 2024
3743f80
refactor: use stETH instead of wstETH
MerlinEgalite Feb 27, 2024
5145e14
docs: adapt comment
MerlinEgalite Feb 27, 2024
c46887b
refactor: hardcode stETH address
MerlinEgalite Feb 27, 2024
5d2a173
refactor: clarify exchange rate
MerlinEgalite Feb 27, 2024
7d8d321
docs: fix and add missing natspecs
MerlinEgalite Feb 27, 2024
c251bed
docs: apply suggestions
MerlinEgalite Feb 28, 2024
999a243
docs: add contract only deployable on ethereum comment
MerlinEgalite Feb 28, 2024
2b1f55a
Merge branch 'refactor/various-improvements' of github.com:morpho-lab…
MerlinEgalite Feb 28, 2024
f984682
docs: apply suggestions
MerlinEgalite Feb 28, 2024
03039ae
docs: apply suggestion
MerlinEgalite Mar 1, 2024
ad5e168
Merge pull request #81 from morpho-org/refactor/use-steth-directly
MathisGD Mar 5, 2024
9cc2150
Merge pull request #82 from morpho-org/refactor/hardcode-steth
MathisGD Mar 5, 2024
fa310b1
Merge remote-tracking branch 'origin/feat/wsteth-oracle' into refacto…
MathisGD Mar 5, 2024
e370ed9
Merge remote-tracking branch 'origin/refactor/various-improvements' i…
MathisGD Mar 5, 2024
ac54cd1
Merge pull request #83 from morpho-org/refactor/various-improvements
MerlinEgalite Mar 5, 2024
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
33 changes: 33 additions & 0 deletions src/adapters/WstEthOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.21;

import {IStEth} from "../interfaces/IStEth.sol";
import {AggregatorV3Interface} from "../interfaces/AggregatorV3Interface.sol";

/// @title WstEthOracle
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice wstETH/ETH exchange rate price feed.
/// @dev This contract should only be used as price feed for `ChainlinkOracle`.
contract WstEthOracle is AggregatorV3Interface {
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
uint8 public constant decimals = uint8(18);
string public constant description = "wstETH/ETH exchange rate price";
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
uint256 public constant version = 1;

IStEth public immutable ST_ETH;

constructor(address stEth) {
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
require(stEth != address(0), "WstEthOracle: ZERO_ADDRESS");
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
ST_ETH = IStEth(stEth);
}

function getRoundData(uint80) external view returns (uint80, int256, uint256, uint256, uint80) {
return latestRoundData();
}

function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80) {
uint256 ethByShares = ST_ETH.getPooledEthByShares(10 ** decimals);
require(ethByShares < type(uint256).max, "WstEthOracle: OVERFLOW");
return (0, int256(ethByShares), 0, 0, 0);
}
}
6 changes: 6 additions & 0 deletions src/interfaces/IStEth.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

interface IStEth {
function getPooledEthByShares(uint256) external view returns (uint256);
}
76 changes: 76 additions & 0 deletions test/WstEthOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "../lib/forge-std/src/Test.sol";
import "../src/adapters/WstEthOracle.sol";

contract ChainlinkOracleTest is Test {
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
IStEth internal constant ST_ETH = IStEth(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84);

WstEthOracle internal oracle;

function setUp() public {
vm.createSelectFork(vm.envString("ETH_RPC_URL"));
oracle = new WstEthOracle(address(ST_ETH));
}

function testLastRoundDataUintMax() public {
vm.mockCall(
address(ST_ETH),
abi.encodeWithSelector(ST_ETH.getPooledEthByShares.selector, 10 ** 18),
abi.encode(type(uint256).max)
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
);
vm.expectRevert("WstEthOracle: OVERFLOW");
oracle.latestRoundData();
}

function testGetRoundDataUintMax() public {
vm.mockCall(
address(ST_ETH),
abi.encodeWithSelector(ST_ETH.getPooledEthByShares.selector, 10 ** 18),
abi.encode(type(uint256).max)
);
vm.expectRevert("WstEthOracle: OVERFLOW");
oracle.getRoundData(1);
}

function testDecimals() public {
assertEq(oracle.decimals(), uint8(18));
}

function testDeployZeroAddress() public {
vm.expectRevert("WstEthOracle: ZERO_ADDRESS");
new WstEthOracle(address(0));
}

function testConfig() public {
assertEq(oracle.description(), "wstETH/ETH exchange rate price");
assertEq(oracle.version(), 1);
}

function testLastRoundData() public {
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
oracle.latestRoundData();
assertEq(roundId, 0);
assertEq(uint256(answer), ST_ETH.getPooledEthByShares(10 ** 18));
assertEq(startedAt, 0);
assertEq(updatedAt, 0);
assertEq(answeredInRound, 0);
}

function testGetLastRoundData() public {
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
oracle.getRoundData(1);
assertEq(roundId, 0);
assertEq(uint256(answer), ST_ETH.getPooledEthByShares(10 ** 18));
assertEq(startedAt, 0);
assertEq(updatedAt, 0);
assertEq(answeredInRound, 0);
}

function testLastRoundDataBounds() public {
(, int256 answer,,,) = oracle.latestRoundData();
assertGe(uint256(answer), 1154690031824824994); // Exchange rate queried at block 19070943
assertLe(uint256(answer), 1.5e18); // Max bounds of the exchange rate. Should work for a long enough time.
}
}