-
-
Notifications
You must be signed in to change notification settings - Fork 13
add OrbOracle adapter #26
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
Open
sach2004
wants to merge
1
commit into
main
Choose a base branch
from
week7-orb-oracle-adapter
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,14 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| library OracleScalingLib { | ||
| function scaleToWad(uint256 value, uint8 valueDecimals) internal pure returns (uint256) { | ||
| if (valueDecimals == 18) { | ||
| return value; | ||
| } | ||
| if (valueDecimals < 18) { | ||
| return value * (10 ** (18 - uint256(valueDecimals))); | ||
| } | ||
| return value / (10 ** (uint256(valueDecimals) - 18)); | ||
| } | ||
| } |
This file contains hidden or 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,54 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {IOracle} from "../interfaces/IOracle.sol"; | ||
| import {OracleScalingLib} from "./OracleScalingLib.sol"; | ||
|
|
||
| interface OrbOracleInterface { | ||
| function readValue() external view returns (int256); | ||
| function readMaxValue(uint256 sampleSize) external view returns (int256); | ||
| function readMinValue(uint256 sampleSize) external view returns (int256); | ||
| function lastSubmissionTime() external view returns (uint256); | ||
| function description() external view returns (string memory); | ||
| } | ||
|
|
||
| contract OrbOracleToOracleAdapter is IOracle { | ||
| OrbOracleInterface public immutable feed; | ||
| uint8 public immutable valueDecimals; | ||
| uint256 public immutable sampleSize; | ||
|
|
||
| constructor(address feedParam, uint8 valueDecimalsParam, uint256 sampleSizeParam) { | ||
| require(feedParam != address(0), "invalid feed"); | ||
| require(sampleSizeParam > 0, "invalid sample size"); | ||
|
|
||
| feed = OrbOracleInterface(feedParam); | ||
| valueDecimals = valueDecimalsParam; | ||
| sampleSize = sampleSizeParam; | ||
| } | ||
|
|
||
| function readValue() public view returns (uint256 value) { | ||
| return _scaleIntToWad(feed.readValue()); | ||
| } | ||
|
|
||
| function readMaxValue() external view returns (uint256 maxValue) { | ||
| return _scaleIntToWad(feed.readMaxValue(sampleSize)); | ||
| } | ||
|
|
||
| function readMinValue() external view returns (uint256 minValue) { | ||
| return _scaleIntToWad(feed.readMinValue(sampleSize)); | ||
| } | ||
|
|
||
| function lastUpdated() external view returns (uint256 timestamp) { | ||
| return feed.lastSubmissionTime(); | ||
| } | ||
|
|
||
| function description() external view returns (string memory) { | ||
| return feed.description(); | ||
| } | ||
|
|
||
| function _scaleIntToWad(int256 value) internal view returns (uint256) { | ||
| require(value > 0, "bad value"); | ||
| // forge-lint: disable-next-line(unsafe-typecast) | ||
| return OracleScalingLib.scaleToWad(uint256(value), valueDecimals); | ||
| } | ||
| } | ||
This file contains hidden or 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,125 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {Test} from "forge-std/Test.sol"; | ||
| import {OrbOracleToOracleAdapter} from "../src/oracles/OrbOracleToOracleAdapter.sol"; | ||
|
|
||
| contract MockOrbOracle { | ||
| int256 public valueVal; | ||
| int256 public maxVal; | ||
| int256 public minVal; | ||
| uint256 public lastSubmissionTimeVal; | ||
| uint256 public expectedSampleSize; | ||
| string private descriptionVal; | ||
|
|
||
| constructor(int256 value_, int256 max_, int256 min_, uint256 sampleSize_, string memory description_) { | ||
| valueVal = value_; | ||
| maxVal = max_; | ||
| minVal = min_; | ||
| expectedSampleSize = sampleSize_; | ||
| descriptionVal = description_; | ||
| lastSubmissionTimeVal = block.timestamp; | ||
| } | ||
|
|
||
| function readValue() external view returns (int256) { | ||
| return valueVal; | ||
| } | ||
|
|
||
| function readMaxValue(uint256 sampleSize) external view returns (int256) { | ||
| require(sampleSize == expectedSampleSize, "wrong sample size"); | ||
| return maxVal; | ||
| } | ||
|
|
||
| function readMinValue(uint256 sampleSize) external view returns (int256) { | ||
| require(sampleSize == expectedSampleSize, "wrong sample size"); | ||
| return minVal; | ||
| } | ||
|
|
||
| function lastSubmissionTime() external view returns (uint256) { | ||
| return lastSubmissionTimeVal; | ||
| } | ||
|
|
||
| function description() external view returns (string memory) { | ||
| return descriptionVal; | ||
| } | ||
| } | ||
|
|
||
| contract OrbOracleAdapterTest is Test { | ||
| function testScalesEightDecimalsToWad() public { | ||
| MockOrbOracle feed = new MockOrbOracle(3000 * 1e8, 3100 * 1e8, 2900 * 1e8, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 8, 3); | ||
|
|
||
| assertEq(adapter.readValue(), 3000 * 1e18, "8 dec scaling failed"); | ||
| } | ||
|
|
||
| function testSupportsEighteenDecimals() public { | ||
| MockOrbOracle feed = new MockOrbOracle(2000 * 1e18, 2100 * 1e18, 1900 * 1e18, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 18, 3); | ||
|
|
||
| assertEq(adapter.readValue(), 2000 * 1e18, "18 dec scaling failed"); | ||
| } | ||
|
|
||
| function testSupportsMoreThanEighteenDecimals() public { | ||
| MockOrbOracle feed = new MockOrbOracle(2000 * 1e20, 2100 * 1e20, 1900 * 1e20, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 20, 3); | ||
|
|
||
| assertEq(adapter.readValue(), 2000 * 1e18, "20 dec scaling failed"); | ||
| } | ||
|
|
||
| function testMinAndMaxUseSampleSize() public { | ||
| MockOrbOracle feed = new MockOrbOracle(3000 * 1e8, 3200 * 1e8, 2800 * 1e8, 5, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 8, 5); | ||
|
|
||
| assertEq(adapter.readMaxValue(), 3200 * 1e18, "wrong max value"); | ||
| assertEq(adapter.readMinValue(), 2800 * 1e18, "wrong min value"); | ||
| } | ||
|
|
||
| function testLastUpdatedReturnsSubmissionTime() public { | ||
| MockOrbOracle feed = new MockOrbOracle(100 * 1e8, 110 * 1e8, 90 * 1e8, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 8, 3); | ||
|
|
||
| assertEq(adapter.lastUpdated(), block.timestamp, "wrong timestamp"); | ||
| } | ||
|
|
||
| function testDescriptionReturnsFeedDescription() public { | ||
| MockOrbOracle feed = new MockOrbOracle(100 * 1e8, 110 * 1e8, 90 * 1e8, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 8, 3); | ||
|
|
||
| assertEq(adapter.description(), "ORB / USD", "wrong description"); | ||
| } | ||
|
|
||
| function testRevertsOnZeroValue() public { | ||
| MockOrbOracle feed = new MockOrbOracle(0, 110 * 1e8, 90 * 1e8, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 8, 3); | ||
|
|
||
| vm.expectRevert("bad value"); | ||
| adapter.readValue(); | ||
| } | ||
|
|
||
| function testRevertsOnNegativeValue() public { | ||
| MockOrbOracle feed = new MockOrbOracle(-1, 110 * 1e8, 90 * 1e8, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 8, 3); | ||
|
|
||
| vm.expectRevert("bad value"); | ||
| adapter.readValue(); | ||
| } | ||
|
|
||
| function testRevertsOnZeroFeedAddress() public { | ||
| vm.expectRevert("invalid feed"); | ||
| new OrbOracleToOracleAdapter(address(0), 8, 3); | ||
| } | ||
|
|
||
| function testRevertsOnZeroSampleSize() public { | ||
| MockOrbOracle feed = new MockOrbOracle(100 * 1e8, 110 * 1e8, 90 * 1e8, 3, "ORB / USD"); | ||
|
|
||
| vm.expectRevert("invalid sample size"); | ||
| new OrbOracleToOracleAdapter(address(feed), 8, 0); | ||
| } | ||
|
|
||
| function testScalesZeroDecimalsToWad() public { | ||
| MockOrbOracle feed = new MockOrbOracle(1234, 1300, 1200, 3, "ORB / USD"); | ||
| OrbOracleToOracleAdapter adapter = new OrbOracleToOracleAdapter(address(feed), 0, 3); | ||
|
|
||
| assertEq(adapter.readValue(), 1234 * 1e18, "0 dec scaling failed"); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
We shouldn't need an adapter for orb oracles. Instead, by having Gluon and Orb agreeing on the oracle interface, Gluon should be able to use Orb oracles directly.
It seems that there are two disagreements that are forcing you to implement this adapter:
1 - Orb is returning int256 but Gluon is expecting uint256.
2 - Orb has a configurable number of decimals, but Gluon is expecting 18 decimals.
To solve 2, let's make Orb always use 18 decimals too.
To solve 2, let's make Orb always return uint256.