-
Notifications
You must be signed in to change notification settings - Fork 164
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: smardex usdn native rate price feed (#1352)
- Loading branch information
1 parent
3dde2cb
commit 85a5afe
Showing
5 changed files
with
163 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
/* | ||
This file is part of the Enzyme Protocol. | ||
(c) Enzyme Foundation <security@enzyme.finance> | ||
For the full license information, please view the LICENSE | ||
file that was distributed with this source code. | ||
*/ | ||
|
||
pragma solidity >=0.6.0 <0.9.0; | ||
|
||
/// @title ISmarDexUsdnProtocol Interface | ||
/// @author Enzyme Foundation <security@enzyme.finance> | ||
interface ISmarDexUsdnProtocol { | ||
function usdnPrice(uint128 _wstethInUsdRateWithWeiPrecision) external view returns (uint256 price_); | ||
} |
71 changes: 71 additions & 0 deletions
71
...acts/release/infrastructure/price-feeds/primitives/SmarDexUsdnNativeRateUsdAggregator.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
/* | ||
This file is part of the Enzyme Protocol. | ||
(c) Enzyme Foundation <security@enzyme.finance> | ||
For the full license information, please view the LICENSE | ||
file that was distributed with this source code. | ||
*/ | ||
|
||
pragma solidity 0.8.19; | ||
|
||
import {IChainlinkAggregator} from "../../../../external-interfaces/IChainlinkAggregator.sol"; | ||
import {ISmarDexUsdnProtocol} from "../../../../external-interfaces/ISmarDexUsdnProtocol.sol"; | ||
import {PriceFeedHelpersLib} from "../utils/PriceFeedHelpersLib.sol"; | ||
import {RateAggregatorBase} from "./utils/RateAggregatorBase.sol"; | ||
import {RateUsdAggregatorBase} from "./utils/RateUsdAggregatorBase.sol"; | ||
|
||
/// @title SmarDexUsdnNativeRateUsdAggregator Contract | ||
/// @author Enzyme Foundation <security@enzyme.finance> | ||
/// @notice USD-quoted aggregator for SmarDex USDN using their native rate | ||
contract SmarDexUsdnNativeRateUsdAggregator is RateUsdAggregatorBase { | ||
/// @dev `USDN_RATES_PRECISION`: the precision used in USDN for both wsteth/usd rate input and USDN rate output | ||
uint256 private constant USDN_RATES_PRECISION = 10 ** 18; | ||
|
||
// Immutables: deployer-input | ||
/// @dev `USDN_PROTOCOL`: the main SmarDex USDN protocol contract | ||
ISmarDexUsdnProtocol public immutable USDN_PROTOCOL; | ||
/// @dev `WSTETH_IN_USD_AGGREGATOR_ADDRESS`: the wstETH/USD aggregator to use as input for the USDN rate function | ||
address public immutable WSTETH_IN_USD_AGGREGATOR_ADDRESS; | ||
// Immutables: derived | ||
/// @dev `WSTETH_IN_USD_AGGREGATOR_PRECISION`: the precision of WSTETH_IN_USD_AGGREGATOR_ADDRESS | ||
uint256 private immutable WSTETH_IN_USD_AGGREGATOR_PRECISION; | ||
|
||
constructor(address _usdnProtocolAddress, address _wstethInUsdAggregatorAddress) | ||
RateUsdAggregatorBase(address(0), false) | ||
{ | ||
USDN_PROTOCOL = ISmarDexUsdnProtocol(_usdnProtocolAddress); | ||
WSTETH_IN_USD_AGGREGATOR_ADDRESS = _wstethInUsdAggregatorAddress; | ||
|
||
WSTETH_IN_USD_AGGREGATOR_PRECISION = | ||
PriceFeedHelpersLib.parsePrecisionFromChainlinkAggregator(_wstethInUsdAggregatorAddress); | ||
} | ||
|
||
//================================================================================================================== | ||
// Required overrides: RateAggregatorBase | ||
//================================================================================================================== | ||
|
||
/// @inheritdoc RateAggregatorBase | ||
/// @dev Returns the value of 1 unit of USDN: | ||
/// - quoted in USD | ||
/// - with 18-decimals of precision | ||
/// - with the wstETH/USD aggregator's timestamp | ||
function baseRate() public view override returns (uint256 rate_, uint256 ratePrecision_, uint256 timestamp_) { | ||
// Get the wstETH/USD rate | ||
(uint256 wstethInUsdRateInAggregatorPrecision, uint256 wstethInUsdRateTimestamp) = | ||
PriceFeedHelpersLib.parseRateFromChainlinkAggregator(WSTETH_IN_USD_AGGREGATOR_ADDRESS); | ||
|
||
// Convert wstETH/USD rate to USDN's expected precision | ||
uint256 wstethInUsdRateWithWeiPrecision = PriceFeedHelpersLib.convertRatePrecision({ | ||
_rate: wstethInUsdRateInAggregatorPrecision, | ||
_fromPrecision: WSTETH_IN_USD_AGGREGATOR_PRECISION, | ||
_toPrecision: USDN_RATES_PRECISION | ||
}); | ||
|
||
rate_ = USDN_PROTOCOL.usdnPrice({_wstethInUsdRateWithWeiPrecision: uint128(wstethInUsdRateWithWeiPrecision)}); | ||
ratePrecision_ = USDN_RATES_PRECISION; | ||
timestamp_ = wstethInUsdRateTimestamp; | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
tests/tests/protocols/smar-dex/SmarDexUsdnNativeRateUsdAggregator.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity 0.8.19; | ||
|
||
import {IntegrationTest} from "tests/bases/IntegrationTest.sol"; | ||
import {IChainlinkAggregator} from "tests/interfaces/external/IChainlinkAggregator.sol"; | ||
|
||
address constant USDN_PROTOCOL_ADDRESS = 0x656cB8C6d154Aad29d8771384089be5B5141f01a; | ||
// Enzyme's `ChainlinkLikeWstethPriceFeed` | ||
address constant WSTETH_ETH_AGGREGATOR = 0x92829C41115311cA43D5c9f722f0E9e7b9fcd30a; | ||
|
||
contract Test is IntegrationTest { | ||
IChainlinkAggregator usdnAggregator; | ||
address wstethUsdAggregatorAddress; | ||
|
||
function setUp() public override { | ||
vm.createSelectFork("mainnet", ETHEREUM_BLOCK_LATEST); | ||
|
||
// TODO: can replace with live address once it's deployed | ||
// Deploy the wstETH/USD aggregator | ||
wstethUsdAggregatorAddress = __deployWstethInUsdAggregator(); | ||
|
||
// Deploy the USDN aggregator | ||
usdnAggregator = __deployUsdnAggregator(wstethUsdAggregatorAddress); | ||
} | ||
|
||
// DEPLOYMENT HELPERS | ||
|
||
function __deployUsdnAggregator(address _wstethInUsdAggregatorAddress) | ||
private | ||
returns (IChainlinkAggregator usdnAggregator_) | ||
{ | ||
bytes memory args = abi.encode(USDN_PROTOCOL_ADDRESS, _wstethInUsdAggregatorAddress); | ||
|
||
return IChainlinkAggregator(deployCode("SmarDexUsdnNativeRateUsdAggregator.sol", args)); | ||
} | ||
|
||
function __deployWstethInUsdAggregator() private returns (address wstethAggregatorAddress_) { | ||
// Convert wstETH from ETH to USD quote using ETH/USD | ||
return deployCode( | ||
"ConvertedQuoteAggregator.sol", | ||
abi.encode(CHAINLINK_AGGREGATOR_DECIMALS_USD, ETHEREUM_ETH_USD_AGGREGATOR, false, WSTETH_ETH_AGGREGATOR) | ||
); | ||
} | ||
|
||
// TESTS | ||
|
||
function test_decimals_success() public { | ||
assertEq(usdnAggregator.decimals(), CHAINLINK_AGGREGATOR_DECIMALS_USD, "Incorrect decimals"); | ||
} | ||
|
||
function test_latestRoundData_success() public { | ||
(, uint256 wstethUsdTimestamp) = parseRateFromChainlinkAggregator(wstethUsdAggregatorAddress); | ||
(uint256 usdnRate, uint256 usdnTimestamp) = parseRateFromChainlinkAggregator(address(usdnAggregator)); | ||
|
||
// Should be very close to 1, unless the rate starts to depeg | ||
uint256 expectedRate = 1e8; // "1" in USD aggregator precision | ||
uint256 percentTolerance = WEI_ONE_PERCENT; // 1% tolerance | ||
assertApproxEqRel(usdnRate, expectedRate, percentTolerance, "Incorrect rate"); | ||
// Timestamp should be that of the wsteth aggregator | ||
assertEq(usdnTimestamp, wstethUsdTimestamp, "Incorrect timestamp"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters