-
Notifications
You must be signed in to change notification settings - Fork 9
/
SwEthSpotOracle.sol
67 lines (57 loc) · 2.32 KB
/
SwEthSpotOracle.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;
import { TickMath } from "../../libraries/uniswap/TickMath.sol";
import { UniswapOracleLibrary } from "../../libraries/uniswap/UniswapOracleLibrary.sol";
import { WAD } from "../../libraries/math/WadRayMath.sol";
import { SpotOracle } from "./SpotOracle.sol";
import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
/**
* @notice The swETH spot oracle.
*
* @custom:security-contact security@molecularlabs.io
*/
contract SwEthSpotOracle is SpotOracle {
using Math for uint256;
error InvalidSecondsAgo(uint32 invalidSecondsAgo);
IUniswapV3Pool public immutable POOL;
uint32 public immutable SECONDS_AGO;
/**
* @notice Creates a new `SwEthSpotOracle` instance.
* @param _ltv The loan to value ratio for swETH.
* @param _reserveOracle The associated reserve oracle.
* @param _uniswapPool swETH/Eth Uniswap pool address.
* @param _secondsAgo The TWAP period in seconds.
*/
constructor(
uint256 _ltv,
address _reserveOracle,
address _uniswapPool,
uint32 _secondsAgo
)
SpotOracle(_ltv, _reserveOracle)
{
if (_secondsAgo == 0) revert InvalidSecondsAgo(_secondsAgo);
POOL = IUniswapV3Pool(_uniswapPool);
SECONDS_AGO = _secondsAgo;
}
/**
* @notice Gets the price of swETH in ETH.
* @dev Uniswap returns price in swETH per ETH. This needs to be inversed.
* @return ethPerSwEth price of swETH in ETH. [WAD]
*/
function getPrice() public view override returns (uint256 ethPerSwEth) {
(int24 arithmeticMeanTick,) = UniswapOracleLibrary.consult(address(POOL), SECONDS_AGO);
uint256 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(arithmeticMeanTick);
// swETH per ETH
uint256 swEthPerEth = _getPriceInWadFromSqrtPriceX96(sqrtPriceX96); // [wad]
ethPerSwEth = WAD * WAD / swEthPerEth; // [wad] * [wad] / [wad]
}
/**
* @notice Converts a sqrtPriceX96 to a price in WAD.
* @param sqrtPriceX96 Price in sqrtPriceX96.
*/
function _getPriceInWadFromSqrtPriceX96(uint256 sqrtPriceX96) internal pure returns (uint256) {
return (sqrtPriceX96 * sqrtPriceX96).mulDiv(WAD, 2 ** 192); // [wad]
}
}