diff --git a/src/wsteth-exchange-rate-adapter/WstEthEthExchangeRateChainlinkAdapter.sol b/src/wsteth-exchange-rate-adapter/WstEthStEthExchangeRateChainlinkAdapter.sol similarity index 57% rename from src/wsteth-exchange-rate-adapter/WstEthEthExchangeRateChainlinkAdapter.sol rename to src/wsteth-exchange-rate-adapter/WstEthStEthExchangeRateChainlinkAdapter.sol index f9bd79a..6341c13 100644 --- a/src/wsteth-exchange-rate-adapter/WstEthEthExchangeRateChainlinkAdapter.sol +++ b/src/wsteth-exchange-rate-adapter/WstEthStEthExchangeRateChainlinkAdapter.sol @@ -4,17 +4,24 @@ pragma solidity 0.8.21; import {IStEth} from "./interfaces/IStEth.sol"; import {MinimalAggregatorV3Interface} from "./interfaces/MinimalAggregatorV3Interface.sol"; -/// @title WstEthEthExchangeRateChainlinkAdapter +/// @title WstEthStEthExchangeRateChainlinkAdapter /// @author Morpho Labs /// @custom:contact security@morpho.org -/// @notice wstETH/ETH exchange rate price feed. -/// @dev This contract should only be used as price feed for `ChainlinkOracle`. -contract WstEthEthExchangeRateChainlinkAdapter is MinimalAggregatorV3Interface { +/// @notice wstETH/stETH exchange rate price feed. +/// @dev This contract should only be deployed on Ethereum and used as a price feed for Morpho oracles. +contract WstEthStEthExchangeRateChainlinkAdapter is MinimalAggregatorV3Interface { + /// @inheritdoc MinimalAggregatorV3Interface // @dev The calculated price has 18 decimals precision, whatever the value of `decimals`. uint8 public constant decimals = 18; - string public constant description = "wstETH/ETH exchange rate"; + + /// @notice The description of the price feed. + string public constant description = "wstETH/stETH exchange rate"; + + /// @notice The address of stETH on Ethereum. IStEth public constant ST_ETH = IStEth(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); + /// @inheritdoc MinimalAggregatorV3Interface + /// @dev Returns zero for roundId, startedAt, updatedAt and answeredInRound. /// @dev Silently overflows if `getPooledEthByShares`'s return value is greater than `type(int256).max`. function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) { // It is assumed that `getPooledEthByShares` returns a price with 18 decimals precision. diff --git a/src/wsteth-exchange-rate-adapter/interfaces/MinimalAggregatorV3Interface.sol b/src/wsteth-exchange-rate-adapter/interfaces/MinimalAggregatorV3Interface.sol index 30a9bae..22887af 100644 --- a/src/wsteth-exchange-rate-adapter/interfaces/MinimalAggregatorV3Interface.sol +++ b/src/wsteth-exchange-rate-adapter/interfaces/MinimalAggregatorV3Interface.sol @@ -3,9 +3,13 @@ pragma solidity >=0.5.0; /// @dev Inspired by /// https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol +/// @dev This is the minimal feed interface required by `MorphoChainlinkOracleV2`. interface MinimalAggregatorV3Interface { + /// @notice Returns the precision of the feed. function decimals() external view returns (uint8); + /// @notice Returns Chainlink's `latestRoundData` return values. + /// @notice Only the `answer` field is used by `MorphoChainlinkOracleV2`. function latestRoundData() external view diff --git a/test/WstEthEthExchangeRateChainlinkAdapterTest.sol b/test/WstEthStEthExchangeRateChainlinkAdapterTest.sol similarity index 80% rename from test/WstEthEthExchangeRateChainlinkAdapterTest.sol rename to test/WstEthStEthExchangeRateChainlinkAdapterTest.sol index ec01d42..0ee91ef 100644 --- a/test/WstEthEthExchangeRateChainlinkAdapterTest.sol +++ b/test/WstEthStEthExchangeRateChainlinkAdapterTest.sol @@ -4,17 +4,17 @@ pragma solidity ^0.8.0; import "./helpers/Constants.sol"; import "../lib/forge-std/src/Test.sol"; import {ChainlinkOracle} from "../src/morpho-chainlink-v1/ChainlinkOracle.sol"; -import "../src/wsteth-exchange-rate-adapter/WstEthEthExchangeRateChainlinkAdapter.sol"; +import "../src/wsteth-exchange-rate-adapter/WstEthStEthExchangeRateChainlinkAdapter.sol"; -contract WstEthEthExchangeRateChainlinkAdapterTest is Test { +contract WstEthStEthExchangeRateChainlinkAdapterTest is Test { IStEth internal constant ST_ETH = IStEth(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); - WstEthEthExchangeRateChainlinkAdapter internal oracle; + WstEthStEthExchangeRateChainlinkAdapter internal oracle; ChainlinkOracle internal chainlinkOracle; function setUp() public { vm.createSelectFork(vm.envString("ETH_RPC_URL")); - oracle = new WstEthEthExchangeRateChainlinkAdapter(); + oracle = new WstEthStEthExchangeRateChainlinkAdapter(); chainlinkOracle = new ChainlinkOracle( vaultZero, AggregatorV3Interface(address(oracle)), feedZero, feedZero, feedZero, 1, 18, 18 ); @@ -25,7 +25,7 @@ contract WstEthEthExchangeRateChainlinkAdapterTest is Test { } function testDescription() public { - assertEq(oracle.description(), "wstETH/ETH exchange rate"); + assertEq(oracle.description(), "wstETH/stETH exchange rate"); } function testLatestRoundData() public { @@ -44,7 +44,7 @@ contract WstEthEthExchangeRateChainlinkAdapterTest is Test { assertLe(uint256(answer), 1.5e18); // Max bounds of the exchange rate. Should work for a long enough time. } - function testOracleWstEthEthExchangeRate() public { + function testOracleWstEthStEthExchangeRate() public { (, int256 expectedPrice,,,) = oracle.latestRoundData(); assertEq(chainlinkOracle.price(), uint256(expectedPrice) * 10 ** (36 + 18 - 18 - 18)); }