-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.15; | ||
|
||
import "../vendor/renzo/IBalancerRateProvider.sol"; | ||
import "../IPriceFeed.sol"; | ||
|
||
/** | ||
* @title ezETH Scaling price feed | ||
* @notice A custom price feed that scales up or down the price received from an underlying Renzo ezETH / ETH exchange rate price feed and returns the result | ||
* @author Compound | ||
*/ | ||
contract EzETHExchangeRatePriceFeed is IPriceFeed { | ||
/** Custom errors **/ | ||
error InvalidInt256(); | ||
|
||
/// @notice Version of the price feed | ||
uint public constant override version = 1; | ||
Check notice Code scanning / Semgrep OSS Semgrep Finding: compound.solidity.constant-not-in-uppercase Note
A constant name is not in UPPER_CASE like other constant variables.
|
||
|
||
/// @notice Description of the price feed | ||
string public description; | ||
|
||
/// @notice Number of decimals for returned prices | ||
uint8 public immutable override decimals; | ||
|
||
/// @notice ezETH price feed where prices are fetched from | ||
address public immutable underlyingPriceFeed; | ||
|
||
/// @notice Whether or not the price should be upscaled | ||
bool internal immutable shouldUpscale; | ||
|
||
/// @notice The amount to upscale or downscale the price by | ||
int256 internal immutable rescaleFactor; | ||
|
||
/** | ||
* @notice Construct a new ezETH scaling price feed | ||
* @param ezETHRateProvider The address of the underlying price feed to fetch prices from | ||
* @param decimals_ The number of decimals for the returned prices | ||
**/ | ||
constructor(address ezETHRateProvider, uint8 decimals_, string memory description_) { | ||
underlyingPriceFeed = ezETHRateProvider; | ||
decimals = decimals_; | ||
description = description_; | ||
|
||
uint8 ezETHRateProviderDecimals = 18; | ||
// Note: Solidity does not allow setting immutables in if/else statements | ||
shouldUpscale = ezETHRateProviderDecimals < decimals_ ? true : false; | ||
rescaleFactor = (shouldUpscale | ||
? signed256(10 ** (decimals_ - ezETHRateProviderDecimals)) | ||
: signed256(10 ** (ezETHRateProviderDecimals - decimals_)) | ||
); | ||
} | ||
Check warning Code scanning / Semgrep OSS There're no sanity checks for the constructor argument description_. Warning
There're no sanity checks for the constructor argument description_.
Check warning Code scanning / Semgrep OSS There're no sanity checks for the constructor argument ezETHRateProvider. Warning
There're no sanity checks for the constructor argument ezETHRateProvider.
Check warning Code scanning / Semgrep OSS Semgrep Finding: compound.solidity.missing-constructor-sanity-checks Warning
There're no sanity checks for the constructor argument ezETHRateProvider.
Check warning Code scanning / Semgrep OSS Consider making costructor payable to save gas. Warning
Consider making costructor payable to save gas.
|
||
|
||
/** | ||
* @notice Price for the latest round | ||
* @return roundId Round id from the underlying price feed | ||
* @return answer Latest price for the asset in terms of ETH | ||
* @return startedAt Timestamp when the round was started; passed on from underlying price feed | ||
* @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed | ||
* @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed | ||
**/ | ||
function latestRoundData() override external view returns ( | ||
uint80 roundId, | ||
int256 answer, | ||
uint256 startedAt, | ||
uint256 updatedAt, | ||
uint80 answeredInRound | ||
) { | ||
uint256 rate = IBalancerRateProvider(underlyingPriceFeed).getRate(); | ||
Check warning Code scanning / Semgrep OSS IBalancerRateProvider(underlyingPriceFeed).getRate() call on a Balancer pool is not protected from the read-only reentrancy. Warning
IBalancerRateProvider(underlyingPriceFeed).getRate() call on a Balancer pool is not protected from the read-only reentrancy.
|
||
// protocol uses only the answer value. Other data fields are not provided by the underlying pricefeed and are not used in Comet protocol | ||
// https://etherscan.io/address/0x387dBc0fB00b26fb085aa658527D5BE98302c84C#readProxyContract | ||
return (0, scalePrice(int256(rate)), 0, 0, 0); | ||
} | ||
|
||
function signed256(uint256 n) internal pure returns (int256) { | ||
if (n > uint256(type(int256).max)) revert InvalidInt256(); | ||
return int256(n); | ||
} | ||
|
||
function scalePrice(int256 price) internal view returns (int256) { | ||
int256 scaledPrice; | ||
if (shouldUpscale) { | ||
scaledPrice = price * rescaleFactor; | ||
} else { | ||
scaledPrice = price / rescaleFactor; | ||
} | ||
return scaledPrice; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.15; | ||
|
||
import "../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; | ||
import "../IPriceFeed.sol"; | ||
|
||
/** | ||
* @title Reverse multiplicative price feed | ||
* @notice A custom price feed that multiplies the price from one price feed and the inverse price from another price feed and returns the result | ||
* @author Compound | ||
*/ | ||
contract ReverseMultiplicativePriceFeed is IPriceFeed { | ||
/** Custom errors **/ | ||
error BadDecimals(); | ||
error InvalidInt256(); | ||
|
||
/// @notice Version of the price feed | ||
uint public constant VERSION = 1; | ||
|
||
/// @notice Description of the price feed | ||
string public override description; | ||
|
||
/// @notice Number of decimals for returned prices | ||
uint8 public immutable override decimals; | ||
|
||
/// @notice Chainlink price feed A | ||
address public immutable priceFeedA; | ||
|
||
/// @notice Chainlink price feed B | ||
address public immutable priceFeedB; | ||
|
||
/// @notice Combined scale of the two underlying Chainlink price feeds | ||
int public immutable priceFeedAScalling; | ||
|
||
/// @notice Scale of this price feed | ||
int public immutable priceFeedScale; | ||
|
||
/** | ||
* @notice Construct a new reverse multiplicative price feed | ||
* @param priceFeedA_ The address of the first price feed to fetch prices from | ||
* @param priceFeedB_ The address of the second price feed to fetch prices from that should be reversed | ||
* @param decimals_ The number of decimals for the returned prices | ||
* @param description_ The description of the price feed | ||
**/ | ||
constructor(address priceFeedA_, address priceFeedB_, uint8 decimals_, string memory description_) { | ||
priceFeedA = priceFeedA_; | ||
priceFeedB = priceFeedB_; | ||
uint8 priceFeedADecimals = AggregatorV3Interface(priceFeedA_).decimals(); | ||
priceFeedAScalling = signed256(10 ** (priceFeedADecimals)); | ||
|
||
if (decimals_ > 18) revert BadDecimals(); | ||
decimals = decimals_; | ||
description = description_; | ||
priceFeedScale = int256(10 ** decimals); | ||
} | ||
Check warning Code scanning / Semgrep OSS There're no sanity checks for the constructor argument description_. Warning
There're no sanity checks for the constructor argument description_.
Check warning Code scanning / Semgrep OSS There're no sanity checks for the constructor argument priceFeedA_. Warning
There're no sanity checks for the constructor argument priceFeedA_.
Check warning Code scanning / Semgrep OSS There're no sanity checks for the constructor argument priceFeedB_. Warning
There're no sanity checks for the constructor argument priceFeedB_.
Check warning Code scanning / Semgrep OSS Consider making costructor payable to save gas. Warning
Consider making costructor payable to save gas.
|
||
|
||
/** | ||
* @notice Calculates the latest round data using data from the two price feeds | ||
* @return roundId Round id from price feed B | ||
* @return answer Latest price | ||
* @return startedAt Timestamp when the round was started; passed on from price feed B | ||
* @return updatedAt Timestamp when the round was last updated; passed on from price feed B | ||
* @return answeredInRound Round id in which the answer was computed; passed on from price feed B | ||
* @dev Note: Only the `answer` really matters for downstream contracts that use this price feed (e.g. Comet) | ||
**/ | ||
function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) { | ||
(, int256 priceA, , , ) = AggregatorV3Interface(priceFeedA).latestRoundData(); | ||
(uint80 roundId_, int256 priceB, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(priceFeedB).latestRoundData(); | ||
|
||
if (priceA <= 0 || priceB <= 0) return (roundId_, 0, startedAt_, updatedAt_, answeredInRound_); | ||
|
||
// int256 price = priceA * priceB * priceFeedScale / combinedScale; | ||
int256 price = priceA * int256(10**(AggregatorV3Interface(priceFeedB).decimals())) * priceFeedScale / priceB / priceFeedAScalling; | ||
return (roundId_, price, startedAt_, updatedAt_, answeredInRound_); | ||
} | ||
|
||
function signed256(uint256 n) internal pure returns (int256) { | ||
if (n > uint256(type(int256).max)) revert InvalidInt256(); | ||
return int256(n); | ||
} | ||
|
||
/** | ||
* @notice Price for the latest round | ||
* @return The version of the price feed contract | ||
**/ | ||
function version() external pure returns (uint256) { | ||
return VERSION; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
interface IBalancerRateProvider { | ||
function getRate() external view returns (uint256); | ||
} |