Skip to content

Commit

Permalink
feat: add stader ethx internal rate aggregator
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanJCasey authored Dec 17, 2024
1 parent e2254ef commit 64baa55
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
2 changes: 2 additions & 0 deletions contracts/external-interfaces/IStaderStakePoolsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ pragma solidity >=0.6.0 <0.9.0;
/// @author Enzyme Foundation <[email protected]>
interface IStaderStakePoolsManager {
function deposit(address _receiver) external payable returns (uint256 shares_);

function getExchangeRate() external view returns (uint256 rate_);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-3.0

/*
This file is part of the Enzyme Protocol.
(c) Enzyme Foundation <[email protected]>
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 {IStaderStakePoolsManager} from "../../../../external-interfaces/IStaderStakePoolsManager.sol";

/// @title StaderEthXRateEthAggregator Contract
/// @author Enzyme Foundation <[email protected]>
/// @notice Chainlink-like aggregator for Stader's internal ETHx rate
contract StaderEthXRateEthAggregator is IChainlinkAggregator {
IStaderStakePoolsManager public immutable STADER_STAKE_POOLS_MANAGER;

constructor(address _staderStakePoolsManagerAddress) {
STADER_STAKE_POOLS_MANAGER = IStaderStakePoolsManager(_staderStakePoolsManagerAddress);
}

/// @notice The decimals used for rate precision of this aggregator
/// @return decimals_ The number of decimals
function decimals() external pure override returns (uint8 decimals_) {
return 18;
}

/// @notice The latest round data for this aggregator
/// @return roundId_ Unused
/// @return answer_ The ETHx rate from Stader
/// @return startedAt_ Unused
/// @return updatedAt_ The current block timestamp
/// @return answeredInRound_ Unused
function latestRoundData()
external
view
override
returns (uint80 roundId_, int256 answer_, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_)
{
answer_ = int256(STADER_STAKE_POOLS_MANAGER.getExchangeRate());

// No timestamp; set to current block to be ignored
updatedAt_ = block.timestamp;

return (roundId_, answer_, startedAt_, updatedAt_, answeredInRound_);
}
}
49 changes: 49 additions & 0 deletions tests/tests/protocols/stader/StaderEthXRateEthAggregatorTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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";
import {IERC20} from "tests/interfaces/external/IERC20.sol";

address constant STADER_STAKE_POOLS_MANAGER_ADDRESS = 0xcf5EA1b38380f6aF39068375516Daf40Ed70D299;

contract StaderEthXRateEthAggregatorTest is IntegrationTest {
IChainlinkAggregator internal aggregator;

function setUp() public override {
setUpMainnetEnvironment(ETHEREUM_BLOCK_TIME_SENSITIVE);
aggregator = __deployAggregator();
}

// DEPLOYMENT HELPERS

function __deployAggregator() private returns (IChainlinkAggregator) {
address addr = deployCode("StaderEthXRateEthAggregator.sol", abi.encode(STADER_STAKE_POOLS_MANAGER_ADDRESS));
return IChainlinkAggregator(addr);
}

// TESTS

function test_decimals() public {
assertEq(aggregator.decimals(), uint8(18), "Incorrect decimals");
}

function test_latestRoundData() public {
// Set block timestamp to validate reported timestamp
uint256 timestamp = 1234;
vm.warp(timestamp);

(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
aggregator.latestRoundData();

assertEq(roundId, 0, "Non-zero roundId");
assertEq(startedAt, 0, "Non-zero startedAt");
assertEq(answeredInRound, 0, "Non-zero answeredInRound");

assertEq(updatedAt, timestamp, "Incorrect updatedAt");

// ETHx/ETH price on Sept 9th 2024
assertEq(answer, int256(1039637773504362819), "Incorrect answer");
}
}

0 comments on commit 64baa55

Please sign in to comment.