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

ezETH/WETH Market Deployment on Base #121

Open
wants to merge 3 commits into
base: jun/base-deployment
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
6 changes: 6 additions & 0 deletions src/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,9 @@ IUniswapV3Pool constant BASE_WSTETH_WETH_UNISWAP = IUniswapV3Pool(0x20E068D76f9E
IChainlink constant BASE_SEQUENCER_UPTIME_FEED = IChainlink(0xBCF85224fc0756B9Fa45aA7892530B47e10b6433);
IERC20 constant BASE_WEETH = IERC20(0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A);
IWETH9 constant BASE_WETH = IWETH9(0x4200000000000000000000000000000000000006);

// Renzo
IERC20 constant BASE_EZETH = IERC20(0x2416092f143378750bb29b79eD961ab195CcEea5);
IUniswapV3Pool constant BASE_EZETH_WETH_AERODROME = IUniswapV3Pool(0xDC7EAd706795eDa3FEDa08Ad519d9452BAdF2C0d);
IChainlink constant BASE_EZETH_ETH_EXCHANGE_RATE_CHAINLINK = IChainlink(0xC4300B7CF0646F0Fe4C5B2ACFCCC4dCA1346f5d8);
IChainlink constant BASE_EZETH_ETH_PRICE_CHAINLINK = IChainlink(0x960BDD1dFD20d7c98fa482D793C3dedD73A113a3);
41 changes: 41 additions & 0 deletions src/flash/lrt/base/BaseEzEthWethHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { IonPool } from "./../../../IonPool.sol";
import { IonPool } from "./../../../IonPool.sol";
import { GemJoin } from "./../../../join/GemJoin.sol";
import { Whitelist } from "./../../../Whitelist.sol";
import { IonHandlerBase } from "./../../IonHandlerBase.sol";
import { IWETH9 } from "./../../../interfaces/IWETH9.sol";
import { UniswapFlashswapHandler } from "./../../UniswapFlashswapHandler.sol";
import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";

/**
* @notice Handler for the ezETH collateral in the ezETH/WETH market on Base.
*
* @custom:security-contact [email protected]
*/
contract BaseEzEthWethHandler is UniswapFlashswapHandler {
/**
* @notice Creates a new `EzEthWethHandler` instance.
* @param _ilkIndex Ilk index of the pool.
* @param _ionPool address.
* @param _gemJoin address.
* @param _whitelist address.
* @param _pool address of the ezETH/WETH Aerodrome pool.
* @param _wethIsToken0 Whether WETH is token0 or token1.
* @param _weth The WETH address of this chain.
*/
constructor(
uint8 _ilkIndex,
IonPool _ionPool,
GemJoin _gemJoin,
Whitelist _whitelist,
IUniswapV3Pool _pool,
bool _wethIsToken0,
IWETH9 _weth
)
IonHandlerBase(_ilkIndex, _ionPool, _gemJoin, _whitelist, _weth)
UniswapFlashswapHandler(_pool, _wethIsToken0)
{ }
}
71 changes: 71 additions & 0 deletions src/oracles/reserve/lrt/base/BaseEzEthWethReserveOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { WadRayMath } from "../../../../libraries/math/WadRayMath.sol";
import { ReserveOracle } from "../../ReserveOracle.sol";
import { BASE_EZETH_ETH_EXCHANGE_RATE_CHAINLINK, BASE_SEQUENCER_UPTIME_FEED } from "../../../../Constants.sol";
import { SafeCast } from "openzeppelin-contracts/contracts/utils/math/SafeCast.sol";

/**
* @notice Reserve Oracle for ezETH denominated in WETH.
*
* @custom:security-contact [email protected]
*/
contract BaseEzEthWethReserveOracle is ReserveOracle {
using WadRayMath for uint256;
using SafeCast for int256;

error SequencerDown();
error GracePeriodNotOver();
error MaxTimeFromLastUpdateExceeded(uint256, uint256);

uint256 public immutable MAX_TIME_FROM_LAST_UPDATE; // seconds
uint256 public immutable GRACE_PERIOD;

/**
* @notice Creates a new `BaseEzEthWethReserveOracle` instance. Provides
* the amount of WETH equal to one ezETH (ETH / ezETH).
* @dev The value of ezETH denominated in WETH by Chainlink.
* @param _feeds List of alternative data sources for the WETH/ezETH exchange rate.
* @param _quorum The amount of alternative data sources to aggregate.
* @param _maxChange Maximum percent change between exchange rate updates. [RAY]
*/
constructor(
uint8 _ilkIndex,
address[] memory _feeds,
uint8 _quorum,
uint256 _maxChange,
uint256 _maxTimeFromLastUpdate,
uint256 _gracePeriod
)
ReserveOracle(_ilkIndex, _feeds, _quorum, _maxChange)
{
MAX_TIME_FROM_LAST_UPDATE = _maxTimeFromLastUpdate;
GRACE_PERIOD = _gracePeriod;
_initializeExchangeRate();
}

function _getProtocolExchangeRate() internal view override returns (uint256) {
(
/*uint80 roundID*/
,
int256 answer,
uint256 startedAt,
/*uint256 updatedAt*/
,
/*uint80 answeredInRound*/
) = BASE_SEQUENCER_UPTIME_FEED.latestRoundData();

if (answer == 1) revert SequencerDown();
if (block.timestamp - startedAt <= GRACE_PERIOD) revert GracePeriodNotOver();

(, int256 ethPerEzEth,, uint256 ethPerEzEthUpdatedAt,) =
BASE_EZETH_ETH_EXCHANGE_RATE_CHAINLINK.latestRoundData();

if (block.timestamp - ethPerEzEthUpdatedAt > MAX_TIME_FROM_LAST_UPDATE) {
revert MaxTimeFromLastUpdateExceeded(block.timestamp - ethPerEzEthUpdatedAt, MAX_TIME_FROM_LAST_UPDATE);
} else {
return ethPerEzEth.toUint256();
}
}
}
87 changes: 87 additions & 0 deletions src/oracles/spot/lrt/base/BaseEzEthWethSpotOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.21;

import { SpotOracle } from "../../../../oracles/spot/SpotOracle.sol";
import { WadRayMath } from "../../../../libraries/math/WadRayMath.sol";
import { BASE_SEQUENCER_UPTIME_FEED, BASE_EZETH_ETH_PRICE_CHAINLINK } from "../../../../Constants.sol";

import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";

/**
* @notice The ezETH spot oracle denominated in WETH on Base.
*
* @custom:security-contact [email protected]
*/
contract BaseEzEthWethSpotOracle is SpotOracle {
using WadRayMath for uint256;
using SafeCast for int256;

error SequencerDown();
error GracePeriodNotOver();

/**
* @notice The maximum delay for the oracle update in seconds before the
* data is considered stale.
*/
uint256 public immutable MAX_TIME_FROM_LAST_UPDATE; // seconds

/**
* @notice Amount of time to wait after the sequencer restarts.
*/
uint256 public immutable GRACE_PERIOD;

/**
* @notice Creates a new `WeEthWethSpotOracle` instance.
* @param _ltv The loan to value ratio for the weETH/WETH market.
* @param _reserveOracle The associated reserve oracle.
* @param _maxTimeFromLastUpdate The maximum delay for the oracle update in seconds
*/
constructor(
uint256 _ltv,
address _reserveOracle,
uint256 _maxTimeFromLastUpdate,
uint256 _gracePeriod
)
SpotOracle(_ltv, _reserveOracle)
{
MAX_TIME_FROM_LAST_UPDATE = _maxTimeFromLastUpdate;
GRACE_PERIOD = _gracePeriod;
}

/**
* @notice Gets the price of weETH in WETH.
* @dev Redstone oracle returns ETH per weETH with 8 decimals. This
* @return wethPerWeEth price of weETH in WETH. [WAD]
*/
function getPrice() public view override returns (uint256) {
(
/*uint80 roundID*/
,
int256 answer,
uint256 startedAt,
/*uint256 updatedAt*/
,
/*uint80 answeredInRound*/
) = BASE_SEQUENCER_UPTIME_FEED.latestRoundData();

if (answer == 1) revert SequencerDown();
if (block.timestamp - startedAt <= GRACE_PERIOD) revert GracePeriodNotOver();

(
/*uint80 roundID*/
,
int256 ethPerEzEth,
/*uint startedAt*/
,
uint256 ethPerEzEthUpdatedAt,
/*uint80 answeredInRound*/
) = BASE_EZETH_ETH_PRICE_CHAINLINK.latestRoundData(); // [WAD]

if (block.timestamp - ethPerEzEthUpdatedAt > MAX_TIME_FROM_LAST_UPDATE) {
return 0; // collateral valuation is zero if oracle data is stale
} else {
return ethPerEzEth.toUint256(); // [wad]
}
}
}
Loading
Loading