-
Notifications
You must be signed in to change notification settings - Fork 50
feat: Use latestAnswer instead of latestRoundData for reserve price on AaveOracle #1221
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| { | ||
| "getUserAccountData: supplies: 0, borrows: 0": "13014", | ||
| "getUserAccountData: supplies: 1, borrows: 0": "49426", | ||
| "getUserAccountData: supplies: 2, borrows: 0": "81102", | ||
| "getUserAccountData: supplies: 2, borrows: 1": "101454", | ||
| "getUserAccountData: supplies: 2, borrows: 2": "120714" | ||
| "getUserAccountData: supplies: 1, borrows: 0": "49057", | ||
| "getUserAccountData: supplies: 2, borrows: 0": "80364", | ||
| "getUserAccountData: supplies: 2, borrows: 1": "100347", | ||
| "getUserAccountData: supplies: 2, borrows: 2": "119238" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| // Imported from https://github.com/smartcontractkit/chainlink/blob/e8490e910274279a2c394ba37eb328943322ac6b/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| // solhint-disable-next-line interface-starts-with-i | ||
| interface AggregatorInterface { | ||
| function latestAnswer() external view returns (int256); | ||
|
|
||
| function latestTimestamp() external view returns (uint256); | ||
|
|
||
| function latestRound() external view returns (uint256); | ||
|
|
||
| function getAnswer(uint256 roundId) external view returns (int256); | ||
|
|
||
| function getTimestamp(uint256 roundId) external view returns (uint256); | ||
|
|
||
| event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); | ||
|
|
||
| event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| // Imported from https://github.com/smartcontractkit/chainlink/blob/e8490e910274279a2c394ba37eb328943322ac6b/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import {AggregatorInterface} from "./AggregatorInterface.sol"; | ||
| import {AggregatorV3Interface} from "./AggregatorV3Interface.sol"; | ||
|
|
||
| // solhint-disable-next-line interface-starts-with-i | ||
| interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,14 +2,16 @@ | |
| // Copyright (c) 2025 Aave Labs | ||
| pragma solidity 0.8.28; | ||
|
|
||
| import {AggregatorV2V3Interface} from 'src/dependencies/chainlink/AggregatorV2V3Interface.sol'; | ||
| import {AggregatorV3Interface} from 'src/dependencies/chainlink/AggregatorV3Interface.sol'; | ||
| import {AggregatorInterface} from 'src/dependencies/chainlink/AggregatorInterface.sol'; | ||
| import {SafeCast} from 'src/dependencies/openzeppelin/SafeCast.sol'; | ||
|
|
||
| /// @title UnitPriceFeed contract | ||
| /// @author Aave Labs | ||
| /// @notice Price feed that returns the unit price (1), with decimals precision. | ||
| /// @dev This price feed can be set for reserves that use the base currency as collateral. | ||
| contract UnitPriceFeed is AggregatorV3Interface { | ||
| contract UnitPriceFeed is AggregatorV2V3Interface { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine just using V2 |
||
| using SafeCast for uint256; | ||
|
|
||
| /// @inheritdoc AggregatorV3Interface | ||
|
|
@@ -46,7 +48,7 @@ contract UnitPriceFeed is AggregatorV3Interface { | |
| uint80 answeredInRound | ||
| ) | ||
| { | ||
| if (_roundId <= uint80(block.timestamp)) { | ||
| if (_roundId <= block.timestamp.toUint80()) { | ||
| roundId = _roundId; | ||
| answer = UNITS; | ||
| startedAt = _roundId; | ||
|
|
@@ -67,7 +69,7 @@ contract UnitPriceFeed is AggregatorV3Interface { | |
| uint80 answeredInRound | ||
| ) | ||
| { | ||
| roundId = uint80(block.timestamp); | ||
| roundId = block.timestamp.toUint80(); | ||
| answer = UNITS; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. answer = latestAnswer();
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i thought the point of this unit price feed was hard coding it to UNITS
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes that's what latestAnswer returns
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion is to avoid logic duplication, can be done either way
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hm then we need to make
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes make it public |
||
| startedAt = block.timestamp; | ||
| updatedAt = block.timestamp; | ||
|
|
@@ -78,4 +80,35 @@ contract UnitPriceFeed is AggregatorV3Interface { | |
| function decimals() external view returns (uint8) { | ||
| return DECIMALS; | ||
| } | ||
|
|
||
| /// @inheritdoc AggregatorInterface | ||
| function latestAnswer() external view returns (int256) { | ||
| return UNITS; | ||
| } | ||
|
|
||
| /// @inheritdoc AggregatorInterface | ||
| function latestTimestamp() external view returns (uint256) { | ||
| return block.timestamp; | ||
| } | ||
|
|
||
| /// @inheritdoc AggregatorInterface | ||
| function latestRound() external view returns (uint256) { | ||
| return block.timestamp; | ||
| } | ||
|
|
||
| /// @inheritdoc AggregatorInterface | ||
| function getAnswer(uint256 roundId) external view returns (int256) { | ||
| if (roundId <= block.timestamp) { | ||
| return UNITS; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| /// @inheritdoc AggregatorInterface | ||
| function getTimestamp(uint256 roundId) external view returns (uint256) { | ||
| if (roundId <= block.timestamp) { | ||
| return roundId; | ||
| } | ||
| return 0; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,9 +2,9 @@ | |||||||||
| // Copyright (c) 2025 Aave Labs | ||||||||||
| pragma solidity ^0.8.0; | ||||||||||
|
|
||||||||||
| import {AggregatorV3Interface} from 'src/dependencies/chainlink/AggregatorV3Interface.sol'; | ||||||||||
| import {AggregatorV2V3Interface} from 'src/dependencies/chainlink/AggregatorV2V3Interface.sol'; | ||||||||||
|
|
||||||||||
| contract MockPriceFeed is AggregatorV3Interface { | ||||||||||
| contract MockPriceFeed is AggregatorV2V3Interface { | ||||||||||
| uint8 public immutable override decimals; | ||||||||||
| string public override description; | ||||||||||
|
|
||||||||||
|
|
@@ -47,4 +47,24 @@ contract MockPriceFeed is AggregatorV3Interface { | |||||||||
| updatedAt = block.timestamp; | ||||||||||
| answeredInRound = roundId; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function latestAnswer() external view override returns (int256) { | ||||||||||
| return _price; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function latestTimestamp() external view override returns (uint256) { | ||||||||||
| return block.timestamp; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function latestRound() external view override returns (uint256) { | ||||||||||
| return block.timestamp; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| function getAnswer(uint256) external view override returns (int256) { | ||||||||||
|
||||||||||
| function getAnswer(uint256) external view override returns (int256) { | |
| /// @notice Returns the current mocked price. | |
| /// @dev This mock does not support historical rounds; `roundId` is ignored. | |
| function getAnswer(uint256 /* roundId */) external view override returns (int256) { |
Copilot
AI
Feb 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getTimestamp function ignores the roundId parameter and always returns the current block.timestamp. According to the Chainlink AggregatorInterface specification, getTimestamp should return the timestamp of a specific round. This implementation is inconsistent with UnitPriceFeed.getTimestamp which does check the roundId parameter. Consider either documenting this deviation from the standard interface behavior or implementing historical round tracking if accurate behavior is required.
| function getTimestamp(uint256) external view override returns (uint256) { | |
| return block.timestamp; | |
| function getTimestamp(uint256 roundId) external view override returns (uint256) { | |
| return roundId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The imports AggregatorV3Interface and AggregatorInterface are redundant since AggregatorV2V3Interface already extends both of these interfaces. Consider removing these imports to keep the code clean and reduce unnecessary dependencies.