diff --git a/contracts/WstETHApi3ReaderProxyV1.sol b/contracts/WstETHApi3ReaderProxyV1.sol new file mode 100644 index 0000000..7e5eb1d --- /dev/null +++ b/contracts/WstETHApi3ReaderProxyV1.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.27; + +import "@api3/contracts/interfaces/IApi3ReaderProxy.sol"; +import "./interfaces/IWstETH.sol"; + +/// @title An immutable proxy contract that reads the stETH per wstETH ratio +/// directly from the WstETH contract on Ethereum. +/// @dev This contract implements only the IApi3ReaderProxy interface and not the +/// AggregatorV2V3Interface which is usually implemented by Api3 proxies. The +/// user of this contract needs to be aware of this limitation and only use this +/// contract where the IApi3ReaderProxy interface is expected. +contract WstETHApi3ReaderProxyV1 is IApi3ReaderProxy { + /// @notice The address of the wstETH contract on Ethereum mainnet. + address public constant WST_ETH = + 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + + /// @inheritdoc IApi3ReaderProxy + /// @dev Returns the stETH/wstETH exchange rate with 18 decimals precision. + /// The timestamp returned is the current block timestamp. + function read() + public + view + override + returns (int224 value, uint32 timestamp) + { + uint256 stEthPerToken = IWstETH(WST_ETH).stEthPerToken(); + + value = int224(int256(stEthPerToken)); // stEthPerToken value has 18 decimals. + timestamp = uint32(block.timestamp); + } +} diff --git a/contracts/interfaces/IWstETH.sol b/contracts/interfaces/IWstETH.sol new file mode 100644 index 0000000..019e4b6 --- /dev/null +++ b/contracts/interfaces/IWstETH.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.27; + +/// @title A minimal interface for the wstETH contract on Ethereum +/// @dev This interface only includes the stEthPerToken function needed to read +/// the exchange rate between stETH and wstETH. +interface IWstETH { + /// @notice Returns the amount of stETH that corresponds to 1 wstETH + /// @return The stETH/wstETH exchange rate with 18 decimals precision + function stEthPerToken() external view returns (uint256); +} diff --git a/scripts/deploy-morpho.ts b/scripts/deploy-morpho.ts new file mode 100644 index 0000000..dd93ae5 --- /dev/null +++ b/scripts/deploy-morpho.ts @@ -0,0 +1,22 @@ +import { ethers } from 'ethers'; + +import { ProductApi3ReaderProxyV1__factory } from '../typechain-types'; + +const deployPriceFeedProxy = async () => { + const provider = new ethers.JsonRpcProvider(process.env.PROVIDER); + const signer = new ethers.Wallet(process.env.PK!, provider); + const productApi3ReaderProxyV1Factory = new ProductApi3ReaderProxyV1__factory(signer); + console.info('Deploying product proxy...'); + const tx = await productApi3ReaderProxyV1Factory.deploy( + '', // TODO: Deploy WstETHApi3ReaderProxyV1.sol + '0x37422cC8e1487a0452cc0D0BF75877d86c63c88A' // https://market.api3.org/ethereum/eth-usd/integrate?dappAlias=morpho-wsteth-usdc-860-lltv + ); + const productApi3ReaderProxyV1 = await tx.waitForDeployment(); + console.info('Deployed ProductApi3ReaderProxyV1:', await productApi3ReaderProxyV1.getAddress()); + console.info('ProductApi3ReaderProxyV1.read():', await productApi3ReaderProxyV1.read()); + // Deployed on Base: 0x707991d5533021021cC360dF093f1B396340Ef3E +}; + +deployPriceFeedProxy(); + +// NOTE: https://market.api3.org/ethereum/usdc-usd/integrate?dappAlias=morpho-wsteth-usdc-860-lltv