From 35dc3d424cca9fd0a62eb9bad0121cb0b342f81e Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:06:41 +0100 Subject: [PATCH 01/21] SortedOracles tests --- .../protocol/test-sol/SortedOracles.t.sol | 657 ++++++++++++++++++ 1 file changed, 657 insertions(+) create mode 100644 packages/protocol/test-sol/SortedOracles.t.sol diff --git a/packages/protocol/test-sol/SortedOracles.t.sol b/packages/protocol/test-sol/SortedOracles.t.sol new file mode 100644 index 00000000000..93ea9a83dbe --- /dev/null +++ b/packages/protocol/test-sol/SortedOracles.t.sol @@ -0,0 +1,657 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.5.13; +pragma experimental ABIEncoderV2; + +import { Test } from "celo-foundry/Test.sol"; +import { SortedOracles } from "../contracts/stability/SortedOracles.sol"; +import "../contracts/common/FixidityLib.sol"; +import "../contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol"; +import "../contracts/common/linkedlists/SortedLinkedListWithMedian.sol"; +import "forge-std/console.sol"; + +contract SortedOraclesTest is Test { + using FixidityLib for FixidityLib.Fraction; + using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; + + SortedOracles sortedOracle; + + address oracleAccount; + address aToken = 0x00000000000000000000000000000000DeaDBeef; + uint256 reportExpiry = 3600; + + uint256 constant YEAR_IN_SECONDS = 31536000; + + event OracleAdded(address indexed token, address indexed oracleAddress); + event OracleRemoved(address indexed token, address indexed oracleAddress); + event OracleReported( + address indexed token, + address indexed oracle, + uint256 timestamp, + uint256 value + ); + event OracleReportRemoved(address indexed token, address indexed oracle); + event MedianUpdated(address indexed token, uint256 value); + event ReportExpirySet(uint256 reportExpiry); + event TokenReportExpirySet(address token, uint256 reportExpiry); + + function setUp() public { + vm.warp(YEAR_IN_SECONDS); + sortedOracle = new SortedOracles(true); + oracleAccount = actor("oracleAccount"); + sortedOracle.initialize(reportExpiry); + } +} + +contract Initialize is SortedOraclesTest { + function setUp() public { + super.setUp(); + } + + function test_ownerSet() public { + assertEq(sortedOracle.owner(), address(this)); + } + + function test_ShouldSetReportExpiry() public { + assertEq(sortedOracle.reportExpirySeconds(), reportExpiry); + } + + function test_ShouldRevertWhenCalledAgain() public { + vm.expectRevert("contract already initialized"); + sortedOracle.initialize(reportExpiry); + } +} + +contract SetReportExpiry is SortedOraclesTest { + function setUp() public { + super.setUp(); + } + + function test_ShouldSetReportExpiry() public { + uint256 newReportExpiry = 7200; + sortedOracle.setReportExpiry(newReportExpiry); + assertEq(sortedOracle.reportExpirySeconds(), newReportExpiry); + } + + function test_ShouldEmitReportExpirySetEvent() public { + uint256 newReportExpiry = 7200; + vm.expectEmit(true, true, true, true); + emit ReportExpirySet(newReportExpiry); + sortedOracle.setReportExpiry(newReportExpiry); + } + + function test_ShouldRevertWhenNotOwner() public { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(oracleAccount); + sortedOracle.setReportExpiry(7200); + } +} + +contract SetTokenReportExpiry is SortedOraclesTest { + function setUp() public { + super.setUp(); + } + + function test_ShouldSetTokenReportExpiry() public { + uint256 newReportExpiry = 7200; + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + assertEq(sortedOracle.tokenReportExpirySeconds(aToken), newReportExpiry); + } + + function test_ShouldEmitTokenReportExpirySetEvent() public { + uint256 newReportExpiry = 7200; + vm.expectEmit(true, true, true, true); + emit TokenReportExpirySet(aToken, newReportExpiry); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + } + + function test_ShouldRevertWhenNotOwner() public { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(oracleAccount); + sortedOracle.setTokenReportExpiry(aToken, 7200); + } +} + +contract AddOracle is SortedOraclesTest { + function setUp() public { + super.setUp(); + } + + function test_ShouldAddOracle() public { + sortedOracle.addOracle(aToken, oracleAccount); + assertEq(sortedOracle.isOracle(aToken, oracleAccount), true); + } + + function test_ShouldEmitOracleAddedEvent() public { + vm.expectEmit(true, true, true, true); + emit OracleAdded(aToken, oracleAccount); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldRevertWhenNotOwner() public { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(oracleAccount); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldRevertWhenAlreadyOracle() public { + sortedOracle.addOracle(aToken, oracleAccount); + vm.expectRevert( + "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" + ); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldRevertWhenOracleIsZeroAddress() public { + vm.expectRevert( + "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" + ); + sortedOracle.addOracle(aToken, address(0)); + } + + function test_ShouldRevertWhenTokenIsZeroAddress() public { + vm.expectRevert( + "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" + ); + sortedOracle.addOracle(address(0), oracleAccount); + } +} + +contract GetTokenReportExpirySeconds is SortedOraclesTest { + function setUp() public { + super.setUp(); + } + + function test_ShouldGetTokenReportExpirySeconds_WhenNoTokenLevelExpiryIsSet() public { + assertEq(sortedOracle.getTokenReportExpirySeconds(aToken), reportExpiry); + } + + function test_ShouldGetTokenReportExpirySeconds_WhenTokenLevelExpiryIsSet() public { + uint256 newReportExpiry = 7200; + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + assertEq(sortedOracle.getTokenReportExpirySeconds(aToken), newReportExpiry); + } +} + +contract RemoveExpiredReports is SortedOraclesTest { + function setUp() public { + super.setUp(); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldRevertWhenNoReportExists() public { + vm.expectRevert("token addr null or trying to remove too many reports"); + sortedOracle.removeExpiredReports(aToken, 1); + } + + function test_ShouldRevertWhenReportIsNotExpired() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + vm.expectRevert("token addr null or trying to remove too many reports"); + sortedOracle.removeExpiredReports(aToken, 1); + } + + function helper_AddMultipleReports(uint256 numReports) public { + vm.warp(YEAR_IN_SECONDS + reportExpiry / 2); + for (uint256 i = 0; i < numReports; i++) { + address oracle = actor(string(abi.encode("oracle", i))); + sortedOracle.addOracle(aToken, oracle); + vm.prank(oracle); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(2, 1).unwrap(), + oracleAccount, + address(0) + ); + } + } + + function test_ShouldDoNothingWhenOldestReportIsNotExpired() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + helper_AddMultipleReports(4); + sortedOracle.removeExpiredReports(aToken, 3); + assertEq(sortedOracle.numTimestamps(aToken), 5); + } + + function test_ShouldRemoveKAndStopWhenKIsLessThanNReportsAreExpired() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + helper_AddMultipleReports(4); + vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + sortedOracle.removeExpiredReports(aToken, 3); + assertEq(sortedOracle.numTimestamps(aToken), 4); + } + + function test_ShouldRevertWhenNGreaterOrEqualToNumTimestamps() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + helper_AddMultipleReports(4); + vm.expectRevert("token addr null or trying to remove too many reports"); + sortedOracle.removeExpiredReports(aToken, 5); + } + + function test_ShouldRemoveNWhenNIsLesserThanNumTimestamps() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + helper_AddMultipleReports(4); + vm.warp(YEAR_IN_SECONDS + 2 * reportExpiry); + sortedOracle.removeExpiredReports(aToken, 3); + assertEq(sortedOracle.numTimestamps(aToken), 2); + } +} + +contract IsOldestReportExpired is SortedOraclesTest { + function setUp() public { + super.setUp(); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldReturnTrueWhenNoReportExists() public { + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, true); + } + + function test_ShouldReturnTrueWhenOldestReportIsExpired() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, true); + } + + function test_ShouldReturnFalseWhenOldestReportIsNotExpired() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + vm.warp(YEAR_IN_SECONDS + reportExpiry - 1); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, false); + } + + function test_ShouldNotExpire_WhenNoTimeHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() + public + { + uint256 newReportExpiry = reportExpiry * 2; + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, false); + } + + function test_ShouldNotExpire_WhenDefaultExpiryHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() + public + { + uint256 newReportExpiry = reportExpiry * 2; + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, false); + } + + function test_ShouldNotExpire_WhenNoTimeHasPassedAndPerTokenExpiryIsSetToLowerThanDefault() + public + { + uint256 newReportExpiry = reportExpiry / 2; + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, false); + } + + function test_ShouldExpire_WhenDefaultExpiryHasPassedAndPerTokenExpiryIsSetToLowerThanDefault() + public + { + uint256 newReportExpiry = reportExpiry / 2; + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, true); + } + + function test_ShouldExpire_WhenTokenExpiryHasPassedAndPerTokenExpiryIsSetToLowerThanDefault() + public + { + uint256 newReportExpiry = reportExpiry / 2; + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + vm.warp(YEAR_IN_SECONDS + newReportExpiry + 1); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, true); + } +} + +contract RemoveOracle is SortedOraclesTest { + address oracleAccount2 = actor("oracleAccount2"); + + function setUp() public { + super.setUp(); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldRemoveOracle() public { + sortedOracle.removeOracle(aToken, oracleAccount, 0); + assertEq(sortedOracle.isOracle(aToken, oracleAccount), false); + } + + function helper_WhenThereIsMoreThanOneReportMade() public { + sortedOracle.addOracle(aToken, oracleAccount2); + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + vm.prank(oracleAccount2); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(5, 1).unwrap(), + oracleAccount, + address(0) + ); + } + + function test_ShouldDecreaseTheNumberOfRates_WhenThereIsMoreThanOneReportMade() public { + helper_WhenThereIsMoreThanOneReportMade(); + sortedOracle.removeOracle(aToken, oracleAccount, 0); + assertEq(sortedOracle.numRates(aToken), 1); + } + + function test_ShouldDecreaseTheNumberOfTimestamps_WhenThereIsMoreThanOneReportMade() public { + helper_WhenThereIsMoreThanOneReportMade(); + sortedOracle.removeOracle(aToken, oracleAccount, 0); + assertEq(sortedOracle.numTimestamps(aToken), 1); + } + + function test_ShouldEmitOracleRemoved_WhenTHereIsMOreThanOneReportMade() public { + helper_WhenThereIsMoreThanOneReportMade(); + vm.expectEmit(true, true, true, true); + emit OracleRemoved(aToken, oracleAccount2); + sortedOracle.removeOracle(aToken, oracleAccount2, 1); + } + + function test_OracleReportRemoved_WhenTHereIsMOreThanOneReportMade() public { + helper_WhenThereIsMoreThanOneReportMade(); + + vm.expectEmit(true, true, true, true); + emit OracleReportRemoved(aToken, oracleAccount2); + sortedOracle.removeOracle(aToken, oracleAccount2, 1); + } + + function test_MedianUpdatedEvents_WhenTHereIsMOreThanOneReportMade() public { + helper_WhenThereIsMoreThanOneReportMade(); + vm.expectEmit(true, true, true, true); + emit MedianUpdated(aToken, FixidityLib.newFixedFraction(1, 1).unwrap()); + sortedOracle.removeOracle(aToken, oracleAccount2, 1); + } + + function test_ShouldNotDecreaseTheNumberOfRates_WhenThereIsASingleReportLeft() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(10, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.removeOracle(aToken, oracleAccount, 0); + assertEq(sortedOracle.numRates(aToken), 1); + } + + function test_ShouldNotResetTheMedianRate_WhenThereIsASingleReportLeft() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(10, 1).unwrap(), + address(0), + address(0) + ); + (uint256 originalMedianRate, uint256 originalNumOfRates) = sortedOracle.medianRate(aToken); + + sortedOracle.removeOracle(aToken, oracleAccount, 0); + (uint256 newMedianRate, uint256 newNumOfRates) = sortedOracle.medianRate(aToken); + assertEq(originalMedianRate, newMedianRate); + assertEq(originalNumOfRates, newNumOfRates); + } + + function test_ShouldNotDecreaseTheNumberOfTimestamps_WhenThereIsASingleReportLeft() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(10, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.removeOracle(aToken, oracleAccount, 0); + assertEq(sortedOracle.numTimestamps(aToken), 1); + } + + function test_ShouldNotResetTheMedianTimestamp_WhenThereIsASingleReportLeft() public { + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(10, 1).unwrap(), + address(0), + address(0) + ); + uint256 originalMedianTimestamp = sortedOracle.medianTimestamp(aToken); + + sortedOracle.removeOracle(aToken, oracleAccount, 0); + uint256 newMedianTimestamp = sortedOracle.medianTimestamp(aToken); + assertEq(originalMedianTimestamp, newMedianTimestamp); + } + + // TODO: add test for not emitting any of the remove events once we migrate to 0.8 + + function test_ShouldEmitOracleRemovedEvent() public { + vm.expectEmit(true, true, true, true); + emit OracleRemoved(aToken, oracleAccount); + sortedOracle.removeOracle(aToken, oracleAccount, 0); + } + + function test_ShouldRevertWhenWrongIndexIsProvided() public { + vm.expectRevert( + "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" + ); + sortedOracle.removeOracle(aToken, oracleAccount, 1); + } + + function test_ShouldRevertWhenWrongAddressIsProvided() public { + vm.expectRevert( + "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" + ); + sortedOracle.removeOracle(aToken, address(this), 0); + } + + function test_ShouldRevertWhenCalledByNonOwner() public { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(oracleAccount); + sortedOracle.removeOracle(aToken, oracleAccount, 0); + } +} + +contract Report is SortedOraclesTest { + uint256 value = FixidityLib.newFixedFraction(10, 1).unwrap(); + uint256 newValue = FixidityLib.newFixedFraction(12, 1).unwrap(); + + address anotherOracle = actor("anotherOracle"); + uint256 oracleValue1 = FixidityLib.newFixedFraction(2, 1).unwrap(); + uint256 oracleValue2 = FixidityLib.newFixedFraction(3, 1).unwrap(); + uint256 anotherOracleValue = FixidityLib.newFixedFraction(1, 1).unwrap(); + + function setUp() public { + super.setUp(); + sortedOracle.addOracle(aToken, oracleAccount); + } + + function test_ShouldIncreaseTheNumberOfRates() public { + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + assertEq(sortedOracle.numRates(aToken), 1); + } + + function test_ShouldSetTheMedianRate() public { + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + (uint256 medianRate, uint256 denominator) = sortedOracle.medianRate(aToken); + assertEq(medianRate, value); + assertEq(denominator, FixidityLib.newFixedFraction(1, 1).unwrap()); + } + + function test_ShouldIncreaseTheNumberOfTimestamps() public { + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + assertEq(sortedOracle.numTimestamps(aToken), 1); + } + + function test_ShouldEmitOracleReportedEvent() public { + vm.expectEmit(true, true, true, true); + emit OracleReported(aToken, oracleAccount, now, value); + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + } + + function test_ShouldEmitMedianUpdatedEvent() public { + vm.expectEmit(true, true, true, true); + emit MedianUpdated(aToken, value); + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + } + + function test_ShouldRevertWhenCalledByNonOracle() public { + vm.expectRevert("sender was not an oracle for token addr"); + sortedOracle.report(aToken, value, address(0), address(0)); + } + + function test_ShouldSetTheMedianRate_WhenThereIsTwoReportsFromSameOracle() public { + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + (uint256 medianRateOriginal, uint256 denominatorOriginal) = sortedOracle.medianRate(aToken); + assertEq(medianRateOriginal, value); + assertEq(denominatorOriginal, FixidityLib.newFixedFraction(1, 1).unwrap()); + vm.prank(oracleAccount); + sortedOracle.report(aToken, newValue, address(0), address(0)); + (uint256 medianRate, uint256 denominator) = sortedOracle.medianRate(aToken); + assertEq(medianRate, newValue); + assertEq(denominator, FixidityLib.newFixedFraction(1, 1).unwrap()); + } + + function test_ShouldNotChangeTheNumberOfTotalReports_WhenThereIsTwoReportsFromSameOracle() + public + { + vm.prank(oracleAccount); + sortedOracle.report(aToken, value, address(0), address(0)); + vm.prank(oracleAccount); + sortedOracle.report(aToken, newValue, address(0), address(0)); + assertEq(sortedOracle.numRates(aToken), 1); + } + + function helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle() public { + sortedOracle.addOracle(aToken, anotherOracle); + vm.prank(anotherOracle); + sortedOracle.report(aToken, anotherOracleValue, address(0), address(0)); + vm.warp(YEAR_IN_SECONDS + 5); + vm.prank(oracleAccount); + sortedOracle.report(aToken, oracleValue1, anotherOracle, address(0)); + vm.warp(YEAR_IN_SECONDS + 10); + (, uint256[] memory rateValues, ) = sortedOracle.getRates(aToken); + assertEq(rateValues[0], oracleValue1); + assertEq(rateValues[1], anotherOracleValue); + + } + + function test_ShouldUpdateTheLIstOfRatesCorrectly_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle() + public + { + helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle(); + + vm.prank(oracleAccount); + sortedOracle.report(aToken, oracleValue2, anotherOracle, address(0)); + + (, uint256[] memory rateValues, ) = sortedOracle.getRates(aToken); + assertEq(rateValues[0], oracleValue2); + assertEq(rateValues[1], anotherOracleValue); + } + + function test_ShouldUpdateTheLAtestTimestamp_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle() + public + { + helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle(); + + (, uint256[] memory timestampValuesBefore, ) = sortedOracle.getTimestamps(aToken); + + vm.prank(oracleAccount); + sortedOracle.report(aToken, oracleValue2, anotherOracle, address(0)); + + (, uint256[] memory timestampValuesAfter, ) = sortedOracle.getTimestamps(aToken); + + assertGt(timestampValuesAfter[0], timestampValuesBefore[0]); + assertEq(timestampValuesBefore[1], timestampValuesAfter[1]); + } + +} From 9ab4faa32b1229108c41bd062a4a3966fe028e10 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:07:05 +0100 Subject: [PATCH 02/21] sorted oracles typescript tests removal --- .../protocol/test/stability/sortedoracles.ts | 638 ------------------ 1 file changed, 638 deletions(-) delete mode 100644 packages/protocol/test/stability/sortedoracles.ts diff --git a/packages/protocol/test/stability/sortedoracles.ts b/packages/protocol/test/stability/sortedoracles.ts deleted file mode 100644 index 519af36abc4..00000000000 --- a/packages/protocol/test/stability/sortedoracles.ts +++ /dev/null @@ -1,638 +0,0 @@ -import { NULL_ADDRESS } from '@celo/base/lib/address' -import { - assertEqualBN, - assertLogMatches2, - assertTransactionRevertWithReason, - matchAddress, - matchAny, - timeTravel, -} from '@celo/protocol/lib/test-utils' -import { fixed1, toFixed } from '@celo/utils/lib/fixidity' -import BigNumber from 'bignumber.js' -import _ from 'lodash' -import { SortedOraclesContract, SortedOraclesInstance } from 'types' -import Web3 from 'web3' - -const SortedOracles: SortedOraclesContract = artifacts.require('SortedOracles') - -// @ts-ignore -// TODO(mcortesi): Use BN.js -SortedOracles.numberFormat = 'BigNumber' - -contract('SortedOracles', (accounts: string[]) => { - let sortedOracles: SortedOraclesInstance - const anOracle = accounts[9] - const aToken = '0x00000000000000000000000000000000deadbeef' - const aReportExpiry: number = 3600 - - beforeEach(async () => { - sortedOracles = await SortedOracles.new(true) - await sortedOracles.initialize(aReportExpiry) - }) - - describe('#initialize()', () => { - it('should have set the owner', async () => { - const owner: string = await sortedOracles.owner() - assert.equal(owner, accounts[0]) - }) - - it('should have set reportExpiry', async () => { - assertEqualBN(await sortedOracles.reportExpirySeconds(), aReportExpiry) - }) - - it('should not be callable again', async () => { - await assertTransactionRevertWithReason( - sortedOracles.initialize(aReportExpiry), - 'contract already initialized' - ) - }) - }) - - describe('#setReportExpiry', () => { - const newReportExpiry = aReportExpiry + 1 - - it('should update reportExpiry', async () => { - await sortedOracles.setReportExpiry(newReportExpiry) - assertEqualBN(await sortedOracles.reportExpirySeconds(), newReportExpiry) - }) - - it('should emit the ReportExpirySet event', async () => { - const resp = await sortedOracles.setReportExpiry(newReportExpiry) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'ReportExpirySet', - args: { - reportExpiry: new BigNumber(newReportExpiry), - }, - }) - }) - - it('should revert when called by a non-owner', async () => { - await assertTransactionRevertWithReason( - sortedOracles.setReportExpiry(newReportExpiry, { from: accounts[1] }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#setTokenReportExpiry', () => { - const newReportExpiry = aReportExpiry + 1 - const token = Web3.utils.toChecksumAddress(Web3.utils.randomHex(20)) - - it('should update reportExpiry', async () => { - await sortedOracles.setTokenReportExpiry(token, newReportExpiry) - assertEqualBN(await sortedOracles.tokenReportExpirySeconds(token), newReportExpiry) - }) - - it('should emit the TokenReportExpirySet event', async () => { - const resp = await sortedOracles.setTokenReportExpiry(token, newReportExpiry) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'TokenReportExpirySet', - args: { - token, - reportExpiry: new BigNumber(newReportExpiry), - }, - }) - }) - - it('should revert when called by a non-owner', async () => { - await assertTransactionRevertWithReason( - sortedOracles.setReportExpiry(newReportExpiry, { from: accounts[1] }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#addOracle', () => { - it('should add an Oracle', async () => { - await sortedOracles.addOracle(aToken, anOracle) - assert.isTrue(await sortedOracles.isOracle(aToken, anOracle)) - }) - - it('should emit the OracleAdded event', async () => { - const resp = await sortedOracles.addOracle(aToken, anOracle) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'OracleAdded', - args: { - token: matchAddress(aToken), - oracleAddress: matchAddress(anOracle), - }, - }) - }) - - it('should revert when token is the null address', async () => { - await assertTransactionRevertWithReason( - sortedOracles.addOracle(NULL_ADDRESS, anOracle), - 'token addr was null or oracle addr was null or oracle addr is not an oracle for token addr' - ) - }) - - it('should revert when the oracle is the null address', async () => { - await assertTransactionRevertWithReason( - sortedOracles.addOracle(aToken, NULL_ADDRESS), - 'token addr was null or oracle addr was null or oracle addr is not an oracle for token addr' - ) - }) - - it('should revert when the oracle has already been added', async () => { - await sortedOracles.addOracle(aToken, anOracle) - await assertTransactionRevertWithReason( - sortedOracles.addOracle(aToken, anOracle), - 'token addr was null or oracle addr was null or oracle addr is not an oracle for token addr' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - sortedOracles.addOracle(aToken, anOracle, { from: accounts[1] }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#getTokenReportExpirySeconds', () => { - describe('when no token level expiry is set', () => { - it('returns the contract level one', async () => { - assert.isTrue((await sortedOracles.getTokenReportExpirySeconds(aToken)).eq(aReportExpiry)) - }) - }) - - describe('when a token level expiry is set', () => { - const anotherReportExpirt = 2 * aReportExpiry - - beforeEach(async () => { - await sortedOracles.setTokenReportExpiry(aToken, anotherReportExpirt) - }) - - it('returns the contract level one', async () => { - assert.isTrue( - (await sortedOracles.getTokenReportExpirySeconds(aToken)).eq(anotherReportExpirt) - ) - }) - }) - }) - - describe('#removeExpiredReports', () => { - beforeEach(async () => { - await sortedOracles.addOracle(aToken, anOracle) - }) - - it('should revert when no report exists', async () => { - await assertTransactionRevertWithReason( - sortedOracles.removeExpiredReports(aToken, 1), - 'token addr null or trying to remove too many reports' - ) - }) - - describe('when a report has been made', () => { - beforeEach(async () => { - await sortedOracles.report(aToken, toFixed(1), NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - }) - - it('should revert when only 1 report exists', async () => { - await assertTransactionRevertWithReason( - sortedOracles.removeExpiredReports(aToken, 1), - 'token addr null or trying to remove too many reports' - ) - }) - - describe('when multiple reports have been made', () => { - beforeEach(async () => { - await timeTravel(aReportExpiry / 2, web3) - for (let i = 7; i > 3; i--) { - const anotherOracle = accounts[i] - await sortedOracles.addOracle(aToken, anotherOracle) - await sortedOracles.report(aToken, toFixed(2), anOracle, NULL_ADDRESS, { - from: anotherOracle, - }) - } - }) - - it('should do nothing when oldest report is not expired', async () => { - await sortedOracles.removeExpiredReports(aToken, 3) - assert.equal(await sortedOracles.numTimestamps.call(aToken), 5) - }) - - it('should remove k and stop when k { - await timeTravel(aReportExpiry / 2, web3) - await sortedOracles.removeExpiredReports(aToken, 3) - assert.equal(await sortedOracles.numTimestamps.call(aToken), 4) - }) - - it('should revert when n>=numTimestamps', async () => { - await assertTransactionRevertWithReason( - sortedOracles.removeExpiredReports(aToken, 5), - 'token addr null or trying to remove too many reports' - ) - }) - - it('should remove n when n { - await timeTravel(aReportExpiry, web3) - await sortedOracles.removeExpiredReports(aToken, 3) - assert.equal(await sortedOracles.numTimestamps.call(aToken), 2) - }) - }) - }) - }) - - describe('#isOldestReportExpired', () => { - beforeEach(async () => { - await sortedOracles.addOracle(aToken, anOracle) - }) - - it('should return true if there are no reports', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isTrue(isReportExpired[0]) - }) - - describe('when a report has been made', () => { - beforeEach(async () => { - await sortedOracles.report(aToken, toFixed(new BigNumber(1)), NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - }) - - describe('using the default expiry', () => { - it('should return true if report is expired', async () => { - await timeTravel(aReportExpiry, web3) - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isTrue(isReportExpired[0]) - }) - - it('should return false if report is not expired', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isFalse(isReportExpired[0]) - }) - }) - - describe('when a per token expiry is set, which is greater than the default', () => { - const tokenReportExpiry = 2 * aReportExpiry - - beforeEach(async () => { - await sortedOracles.setTokenReportExpiry(aToken, tokenReportExpiry) - }) - - describe('and no time has passed', () => { - it('it should not be expired', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isFalse(isReportExpired[0]) - }) - }) - - describe('and the default expiry time has passed', () => { - beforeEach(() => timeTravel(aReportExpiry, web3)) - - it('should return false', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isFalse(isReportExpired[0]) - }) - }) - - describe('and the token expiry time has passed', () => { - beforeEach(() => timeTravel(tokenReportExpiry, web3)) - - it('should return true if the report is expired', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isTrue(isReportExpired[0]) - }) - }) - }) - - describe('when a per token expiry is set, which is lower than the default', () => { - const tokenReportExpiry = aReportExpiry / 2 - - beforeEach(async () => { - await sortedOracles.setTokenReportExpiry(aToken, tokenReportExpiry) - }) - - describe('and no time has passed', () => { - it('it should not be expired', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isFalse(isReportExpired[0]) - }) - }) - - describe('and the default expiry time has passed', () => { - beforeEach(() => timeTravel(aReportExpiry, web3)) - - it('should return true', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isTrue(isReportExpired[0]) - }) - }) - - describe('and the token expiry time has passed', () => { - beforeEach(() => timeTravel(tokenReportExpiry, web3)) - - it('should return true if the report is expired', async () => { - const isReportExpired = await sortedOracles.isOldestReportExpired(aToken) - assert.isTrue(isReportExpired[0]) - }) - }) - }) - }) - }) - - describe('#removeOracle', () => { - beforeEach(async () => { - await sortedOracles.addOracle(aToken, anOracle) - }) - - it('should remove an Oracle', async () => { - await sortedOracles.removeOracle(aToken, anOracle, 0) - assert.isFalse(await sortedOracles.isOracle(aToken, anOracle)) - }) - - describe('when there is more than one report made', () => { - const anotherOracle = accounts[6] - - beforeEach(async () => { - await sortedOracles.report(aToken, toFixed(1), NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - - await sortedOracles.addOracle(aToken, anotherOracle) - await sortedOracles.report(aToken, toFixed(5), anOracle, NULL_ADDRESS, { - from: anotherOracle, - }) - }) - - it('should decrease the number of rates', async () => { - await sortedOracles.removeOracle(aToken, anotherOracle, 1) - assert.equal((await sortedOracles.numRates(aToken)).toNumber(), 1) - }) - - it('should decrease the number of timestamps', async () => { - await sortedOracles.removeOracle(aToken, anotherOracle, 1) - assert.equal((await sortedOracles.numTimestamps(aToken)).toNumber(), 1) - }) - - it('should emit the OracleRemoved, OracleReportRemoved and MedianUpdated events', async () => { - const resp = await sortedOracles.removeOracle(aToken, anotherOracle, 1) - assert.equal(resp.logs.length, 3) - assertLogMatches2(resp.logs[0], { - event: 'OracleReportRemoved', - args: { - oracle: matchAddress(anotherOracle), - token: matchAddress(aToken), - }, - }) - - const medianUpdatedEvent = _.find(resp.logs, { - event: 'MedianUpdated', - }) - assert.exists(medianUpdatedEvent) - - assertLogMatches2(resp.logs[2], { - event: 'OracleRemoved', - args: { - token: matchAddress(aToken), - oracleAddress: matchAddress(anotherOracle), - }, - }) - }) - }) - - describe('when there is a single report left', () => { - beforeEach(async () => { - await sortedOracles.report(aToken, toFixed(10), NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - }) - - it('should not decrease the number of rates', async () => { - await sortedOracles.removeOracle(aToken, anOracle, 0) - assert.equal((await sortedOracles.numRates(aToken)).toNumber(), 1) - }) - - it('should not reset the median rate', async () => { - const [actualNumeratorBefore] = await sortedOracles.medianRate(aToken) - await sortedOracles.removeOracle(aToken, anOracle, 0) - const [actualNumeratorAfter] = await sortedOracles.medianRate(aToken) - assert.equal(actualNumeratorBefore.toNumber(), actualNumeratorAfter.toNumber()) - }) - - it('should not decrease the number of timestamps', async () => { - await sortedOracles.removeOracle(aToken, anOracle, 0) - assert.equal((await sortedOracles.numTimestamps(aToken)).toNumber(), 1) - }) - - it('should not reset the median timestamp', async () => { - const medianTimestampBefore = await sortedOracles.medianTimestamp(aToken) - await sortedOracles.removeOracle(aToken, anOracle, 0) - const medianTimestampAfter = await sortedOracles.medianTimestamp(aToken) - assert.equal(medianTimestampBefore.toNumber(), medianTimestampAfter.toNumber()) - }) - - it('should not emit the OracleReportRemoved and MedianUpdated events, but the OracleRemoved', async () => { - const resp = await sortedOracles.removeOracle(aToken, anOracle, 0) - - const oracleReportRemovedEvent = _.find(resp.logs, { - event: 'OracleReportRemoved', - }) - assert.equal(oracleReportRemovedEvent, undefined) - - const medianUpdatedEvent = _.find(resp.logs, { - event: 'MedianUpdated', - }) - assert.equal(medianUpdatedEvent, undefined) - - assertLogMatches2(resp.logs[0], { - event: 'OracleRemoved', - args: { - token: matchAddress(aToken), - oracleAddress: matchAddress(anOracle), - }, - }) - }) - }) - - it('should emit the OracleRemoved event', async () => { - const resp = await sortedOracles.removeOracle(aToken, anOracle, 0) - assert.equal(resp.logs.length, 1) - const log = resp.logs[0] - assertLogMatches2(log, { - event: 'OracleRemoved', - args: { - token: matchAddress(aToken), - oracleAddress: matchAddress(anOracle), - }, - }) - }) - - it('should revert when the wrong index is provided', async () => { - await assertTransactionRevertWithReason( - sortedOracles.removeOracle(aToken, anOracle, 1), - 'token addr null or oracle addr null or index of token oracle not mapped to oracle addr' - ) - }) - - it('should revert when the wrong address is provided', async () => { - await assertTransactionRevertWithReason( - sortedOracles.removeOracle(aToken, accounts[0], 0), - 'token addr null or oracle addr null or index of token oracle not mapped to oracle addr' - ) - }) - - it('should revert when called by anyone other than the owner', async () => { - await assertTransactionRevertWithReason( - sortedOracles.removeOracle(aToken, anOracle, 0, { from: accounts[1] }), - 'Ownable: caller is not the owner' - ) - }) - }) - - describe('#report', () => { - const value = toFixed(10) - beforeEach(async () => { - await sortedOracles.addOracle(aToken, anOracle) - }) - - it('should increase the number of rates', async () => { - await sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - assert.equal((await sortedOracles.numRates(aToken)).toNumber(), 1) - }) - - it('should set the median rate', async () => { - await sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - const [actualNumerator, actualDenominator] = await sortedOracles.medianRate(aToken) - assertEqualBN(actualNumerator, value) - assertEqualBN(actualDenominator, fixed1) - }) - - it('should increase the number of timestamps', async () => { - await sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - assertEqualBN(await sortedOracles.numTimestamps(aToken), 1) - }) - - it('should set the median timestamp', async () => { - await sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - const blockTimestamp = (await web3.eth.getBlock('latest')).timestamp - assert.equal((await sortedOracles.medianTimestamp(aToken)).toNumber(), blockTimestamp) - }) - - it('should emit the OracleReported and MedianUpdated events', async () => { - const resp = await sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - assert.equal(resp.logs.length, 2) - assertLogMatches2(resp.logs[0], { - event: 'OracleReported', - args: { - token: matchAddress(aToken), - oracle: matchAddress(anOracle), - timestamp: matchAny, - value, - }, - }) - - assertLogMatches2(resp.logs[1], { - event: 'MedianUpdated', - args: { - token: matchAddress(aToken), - value, - }, - }) - }) - - it('should revert when called by a non-oracle', async () => { - await assertTransactionRevertWithReason( - sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS), - 'sender was not an oracle for token addr' - ) - }) - - describe('when there exists exactly one other report, made by this oracle', () => { - const newValue = toFixed(12) - - beforeEach(async () => { - await sortedOracles.report(aToken, value, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - }) - it('should reset the median rate', async () => { - const [initialNumerator, initialDenominator] = await sortedOracles.medianRate(aToken) - assertEqualBN(initialNumerator, value) - assertEqualBN(initialDenominator, fixed1) - - await sortedOracles.report(aToken, newValue, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - - const [actualNumerator, actualDenominator] = await sortedOracles.medianRate(aToken) - assertEqualBN(actualNumerator, newValue) - assertEqualBN(actualDenominator, fixed1) - }) - it('should not change the number of total reports', async () => { - const initialNumReports = await sortedOracles.numRates(aToken) - await sortedOracles.report(aToken, newValue, NULL_ADDRESS, NULL_ADDRESS, { - from: anOracle, - }) - - assertEqualBN(initialNumReports, await sortedOracles.numRates(aToken)) - }) - }) - - describe('when there are multiple reports, the most recent one done by this oracle', () => { - const anotherOracle = accounts[6] - const anOracleValue1 = toFixed(2) - const anOracleValue2 = toFixed(3) - const anotherOracleValue = toFixed(1) - - beforeEach(async () => { - await sortedOracles.addOracle(aToken, anotherOracle) - await sortedOracles.report(aToken, anotherOracleValue, NULL_ADDRESS, NULL_ADDRESS, { - from: anotherOracle, - }) - await timeTravel(5, web3) - await sortedOracles.report(aToken, anOracleValue1, anotherOracle, NULL_ADDRESS, { - from: anOracle, - }) - await timeTravel(5, web3) - - // confirm the setup worked - const initialRates = await sortedOracles.getRates(aToken) - assertEqualBN(initialRates['1'][0], anOracleValue1) - assertEqualBN(initialRates['1'][1], anotherOracleValue) - }) - - it('updates the list of rates correctly', async () => { - await sortedOracles.report(aToken, anOracleValue2, anotherOracle, NULL_ADDRESS, { - from: anOracle, - }) - const resultRates = await sortedOracles.getRates(aToken) - assertEqualBN(resultRates['1'][0], anOracleValue2) - assertEqualBN(resultRates['1'][1], anotherOracleValue) - }) - - it('updates the latest timestamp', async () => { - const initialTimestamps = await sortedOracles.getTimestamps(aToken) - await sortedOracles.report(aToken, anOracleValue2, anotherOracle, NULL_ADDRESS, { - from: anOracle, - }) - const resultTimestamps = await sortedOracles.getTimestamps(aToken) - - // the second timestamp, belonging to anotherOracle should be unchanged - assertEqualBN(initialTimestamps['1']['1'], resultTimestamps['1']['1']) - - // the most recent timestamp, belonging to anOracle in both cases, should change - assert.isTrue(resultTimestamps['1']['0'].gt(initialTimestamps['1']['0'])) - }) - }) - }) -}) From 7c0921704fda68d24874f271129621023906cbc5 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:00:26 +0100 Subject: [PATCH 03/21] path fixes --- .../protocol/test-sol/{ => stability}/SortedOracles.t.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename packages/protocol/test-sol/{ => stability}/SortedOracles.t.sol (98%) diff --git a/packages/protocol/test-sol/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol similarity index 98% rename from packages/protocol/test-sol/SortedOracles.t.sol rename to packages/protocol/test-sol/stability/SortedOracles.t.sol index 93ea9a83dbe..25b9c230912 100644 --- a/packages/protocol/test-sol/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -3,10 +3,10 @@ pragma solidity ^0.5.13; pragma experimental ABIEncoderV2; import { Test } from "celo-foundry/Test.sol"; -import { SortedOracles } from "../contracts/stability/SortedOracles.sol"; -import "../contracts/common/FixidityLib.sol"; -import "../contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol"; -import "../contracts/common/linkedlists/SortedLinkedListWithMedian.sol"; +import { SortedOracles } from "../../contracts/stability/SortedOracles.sol"; +import "../../contracts/common/FixidityLib.sol"; +import "../../contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol"; +import "../../contracts/common/linkedlists/SortedLinkedListWithMedian.sol"; import "forge-std/console.sol"; contract SortedOraclesTest is Test { From b46efc89dcf83625b60d24c75dd7a582ee7e48a7 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:49:13 +0100 Subject: [PATCH 04/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol Co-authored-by: soloseng <102702451+soloseng@users.noreply.github.com> --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 25b9c230912..650db4069a4 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -210,7 +210,7 @@ contract RemoveExpiredReports is SortedOraclesTest { } } - function test_ShouldDoNothingWhenOldestReportIsNotExpired() public { + function test_ShouldDoNothingWhenOldestReportIsNotExpired_WhenMultipleReportsHaveBeenMade() public { vm.prank(oracleAccount); sortedOracle.report( aToken, From f79b142f6a49186d329640cb151cbfc683bcdddf Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:49:21 +0100 Subject: [PATCH 05/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol Co-authored-by: soloseng <102702451+soloseng@users.noreply.github.com> --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 650db4069a4..71be2fc185d 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -302,7 +302,7 @@ contract IsOldestReportExpired is SortedOraclesTest { assertEq(expired, false); } - function test_ShouldNotExpire_WhenNoTimeHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() + function test_ShouldNotExpire_WhenNoTimeHasPassed_WhenPerTokenExpiryIsSetToHigherThanDefault() public { uint256 newReportExpiry = reportExpiry * 2; From 2e797c06ab3881540b448c88c115661f2c1211ce Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:49:31 +0100 Subject: [PATCH 06/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol Co-authored-by: soloseng <102702451+soloseng@users.noreply.github.com> --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 71be2fc185d..b9d92541567 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -444,7 +444,7 @@ contract RemoveOracle is SortedOraclesTest { sortedOracle.removeOracle(aToken, oracleAccount2, 1); } - function test_MedianUpdatedEvents_WhenTHereIsMOreThanOneReportMade() public { + function test_ShouldEmitMedianUpdatedEvents_WhenTHereIsMOreThanOneReportMade() public { helper_WhenThereIsMoreThanOneReportMade(); vm.expectEmit(true, true, true, true); emit MedianUpdated(aToken, FixidityLib.newFixedFraction(1, 1).unwrap()); From 55b3c8df9aadc12e661c2262507d34770fae0ffe Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:49:38 +0100 Subject: [PATCH 07/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol Co-authored-by: soloseng <102702451+soloseng@users.noreply.github.com> --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index b9d92541567..615462cd109 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -436,7 +436,7 @@ contract RemoveOracle is SortedOraclesTest { sortedOracle.removeOracle(aToken, oracleAccount2, 1); } - function test_OracleReportRemoved_WhenTHereIsMOreThanOneReportMade() public { + function test_ShouldEmitOracleReportRemoved_WhenTHereIsMOreThanOneReportMade() public { helper_WhenThereIsMoreThanOneReportMade(); vm.expectEmit(true, true, true, true); From 9f7d42e7e643a93833e1a1a29777d0dfc4f5020f Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:49:46 +0100 Subject: [PATCH 08/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol Co-authored-by: soloseng <102702451+soloseng@users.noreply.github.com> --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 615462cd109..2304cffa758 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -289,7 +289,7 @@ contract IsOldestReportExpired is SortedOraclesTest { assertEq(expired, true); } - function test_ShouldReturnFalseWhenOldestReportIsNotExpired() public { + function test_ShouldReturnFalseWhenOldestReportIsNotExpired_WhenUsingDefaultExpiry() public { vm.prank(oracleAccount); sortedOracle.report( aToken, From 5bba0292fd1d1d8e949d7202933be1efe3ab644a Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:59:51 +0100 Subject: [PATCH 09/21] PR comments --- .../protocol/test-sol/SortedOracles.t.sol | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/protocol/test-sol/SortedOracles.t.sol b/packages/protocol/test-sol/SortedOracles.t.sol index 93ea9a83dbe..b21ead619c2 100644 --- a/packages/protocol/test-sol/SortedOracles.t.sol +++ b/packages/protocol/test-sol/SortedOracles.t.sol @@ -223,7 +223,9 @@ contract RemoveExpiredReports is SortedOraclesTest { assertEq(sortedOracle.numTimestamps(aToken), 5); } - function test_ShouldRemoveKAndStopWhenKIsLessThanNReportsAreExpired() public { + function test_ShouldRemoveKAndStopWhenKIsLessThanNReportsAreExpired_WhenMultipleReportsHaveBeenMade() + public + { vm.prank(oracleAccount); sortedOracle.report( aToken, @@ -250,7 +252,9 @@ contract RemoveExpiredReports is SortedOraclesTest { sortedOracle.removeExpiredReports(aToken, 5); } - function test_ShouldRemoveNWhenNIsLesserThanNumTimestamps() public { + function test_ShouldRemoveNWhenNIsLesserThanNumTimestamps_WhenMultipleReportsHaveBeenMade() + public + { vm.prank(oracleAccount); sortedOracle.report( aToken, @@ -318,6 +322,23 @@ contract IsOldestReportExpired is SortedOraclesTest { assertEq(expired, false); } + function test_ShouldExpire_WhenTokenExpiryTimeHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() + public + { + uint256 newReportExpiry = reportExpiry * 2; + vm.prank(oracleAccount); + sortedOracle.report( + aToken, + FixidityLib.newFixedFraction(1, 1).unwrap(), + address(0), + address(0) + ); + sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); + vm.warp(YEAR_IN_SECONDS + newReportExpiry + 1); + (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); + assertEq(expired, true); + } + function test_ShouldNotExpire_WhenDefaultExpiryHasPassedAndPerTokenExpiryIsSetToHigherThanDefault() public { From 7dcf3ddf636a7f2652d16086fa2e7fb157906924 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 4 Dec 2023 12:17:12 +0100 Subject: [PATCH 10/21] lint changes --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 342f2651d20..321f569a558 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -210,7 +210,9 @@ contract RemoveExpiredReports is SortedOraclesTest { } } - function test_ShouldDoNothingWhenOldestReportIsNotExpired_WhenMultipleReportsHaveBeenMade() public { + function test_ShouldDoNothingWhenOldestReportIsNotExpired_WhenMultipleReportsHaveBeenMade() + public + { vm.prank(oracleAccount); sortedOracle.report( aToken, From e91c7de6f22e7809280b1ed10908aac3d4ea7106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Volpe?= Date: Mon, 4 Dec 2023 13:19:27 +0100 Subject: [PATCH 11/21] Delete console.log --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 321f569a558..af86ccbc57a 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -7,7 +7,6 @@ import { SortedOracles } from "../../contracts/stability/SortedOracles.sol"; import "../../contracts/common/FixidityLib.sol"; import "../../contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol"; import "../../contracts/common/linkedlists/SortedLinkedListWithMedian.sol"; -import "forge-std/console.sol"; contract SortedOraclesTest is Test { using FixidityLib for FixidityLib.Fraction; From 08e422c1b3e5866f4b8423004f745b837e957baf Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:31:25 +0100 Subject: [PATCH 12/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Volpe --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index af86ccbc57a..5b2dee2b642 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -86,9 +86,6 @@ contract SetReportExpiry is SortedOraclesTest { } contract SetTokenReportExpiry is SortedOraclesTest { - function setUp() public { - super.setUp(); - } function test_ShouldSetTokenReportExpiry() public { uint256 newReportExpiry = 7200; From 2111db627383f9da0a7c12cb7bc5c363f89d6921 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:31:35 +0100 Subject: [PATCH 13/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Volpe --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 5b2dee2b642..7ffc16fecf1 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -61,9 +61,6 @@ contract Initialize is SortedOraclesTest { } contract SetReportExpiry is SortedOraclesTest { - function setUp() public { - super.setUp(); - } function test_ShouldSetReportExpiry() public { uint256 newReportExpiry = 7200; From 470e10a35b8cafc874f07441cc1c58799cd9b92d Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:31:42 +0100 Subject: [PATCH 14/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Volpe --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 7ffc16fecf1..2064672c27a 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -42,9 +42,6 @@ contract SortedOraclesTest is Test { } contract Initialize is SortedOraclesTest { - function setUp() public { - super.setUp(); - } function test_ownerSet() public { assertEq(sortedOracle.owner(), address(this)); From e3d263f7b80e4c1b869e2cf06efb45aa77e38a67 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:31:53 +0100 Subject: [PATCH 15/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Volpe --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 2064672c27a..ed2a794ae89 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -102,9 +102,6 @@ contract SetTokenReportExpiry is SortedOraclesTest { } contract AddOracle is SortedOraclesTest { - function setUp() public { - super.setUp(); - } function test_ShouldAddOracle() public { sortedOracle.addOracle(aToken, oracleAccount); From 7a14978239ceed8d20aa0473eb9af735a6332a1a Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:32:01 +0100 Subject: [PATCH 16/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Volpe --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index ed2a794ae89..325a569039b 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -144,9 +144,6 @@ contract AddOracle is SortedOraclesTest { } contract GetTokenReportExpirySeconds is SortedOraclesTest { - function setUp() public { - super.setUp(); - } function test_ShouldGetTokenReportExpirySeconds_WhenNoTokenLevelExpiryIsSet() public { assertEq(sortedOracle.getTokenReportExpirySeconds(aToken), reportExpiry); From 8d75cb0abe303353657d2f9ec884057ca720e944 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:35:52 +0100 Subject: [PATCH 17/21] Update packages/protocol/test-sol/stability/SortedOracles.t.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Martín Volpe --- packages/protocol/test-sol/stability/SortedOracles.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 325a569039b..1bfe41370c8 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -632,7 +632,7 @@ contract Report is SortedOraclesTest { } - function test_ShouldUpdateTheLIstOfRatesCorrectly_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle() + function test_ShouldUpdateTheListOfRatesCorrectly_WhenThereAreMultipleReportsTheMostRecentOneIsDoneByThisOracle() public { helper_WhenThereAreMultipleReportsTheMostRecentOneDoneByThisOracle(); From 0f59bd99ca021e9dc78989d1d1663115bdd4fafb Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:36:35 +0100 Subject: [PATCH 18/21] introduction of constants --- .../test-sol/stability/SortedOracles.t.sol | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index af86ccbc57a..a04fc01ffc6 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -7,8 +7,9 @@ import { SortedOracles } from "../../contracts/stability/SortedOracles.sol"; import "../../contracts/common/FixidityLib.sol"; import "../../contracts/common/linkedlists/AddressSortedLinkedListWithMedian.sol"; import "../../contracts/common/linkedlists/SortedLinkedListWithMedian.sol"; +import { Constants } from "../constants.sol"; -contract SortedOraclesTest is Test { +contract SortedOraclesTest is Test, Constants { using FixidityLib for FixidityLib.Fraction; using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; @@ -18,8 +19,6 @@ contract SortedOraclesTest is Test { address aToken = 0x00000000000000000000000000000000DeaDBeef; uint256 reportExpiry = 3600; - uint256 constant YEAR_IN_SECONDS = 31536000; - event OracleAdded(address indexed token, address indexed oracleAddress); event OracleRemoved(address indexed token, address indexed oracleAddress); event OracleReported( @@ -34,7 +33,7 @@ contract SortedOraclesTest is Test { event TokenReportExpirySet(address token, uint256 reportExpiry); function setUp() public { - vm.warp(YEAR_IN_SECONDS); + vm.warp(YEAR); sortedOracle = new SortedOracles(true); oracleAccount = actor("oracleAccount"); sortedOracle.initialize(reportExpiry); @@ -42,9 +41,9 @@ contract SortedOraclesTest is Test { } contract Initialize is SortedOraclesTest { - function setUp() public { - super.setUp(); - } + // function setUp() public { + // super.setUp(); + // } function test_ownerSet() public { assertEq(sortedOracle.owner(), address(this)); @@ -195,7 +194,7 @@ contract RemoveExpiredReports is SortedOraclesTest { } function helper_AddMultipleReports(uint256 numReports) public { - vm.warp(YEAR_IN_SECONDS + reportExpiry / 2); + vm.warp(YEAR + reportExpiry / 2); for (uint256 i = 0; i < numReports; i++) { address oracle = actor(string(abi.encode("oracle", i))); sortedOracle.addOracle(aToken, oracle); @@ -235,7 +234,7 @@ contract RemoveExpiredReports is SortedOraclesTest { address(0) ); helper_AddMultipleReports(4); - vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + vm.warp(YEAR + reportExpiry + 1); sortedOracle.removeExpiredReports(aToken, 3); assertEq(sortedOracle.numTimestamps(aToken), 4); } @@ -264,7 +263,7 @@ contract RemoveExpiredReports is SortedOraclesTest { address(0) ); helper_AddMultipleReports(4); - vm.warp(YEAR_IN_SECONDS + 2 * reportExpiry); + vm.warp(YEAR + 2 * reportExpiry); sortedOracle.removeExpiredReports(aToken, 3); assertEq(sortedOracle.numTimestamps(aToken), 2); } @@ -289,7 +288,7 @@ contract IsOldestReportExpired is SortedOraclesTest { address(0), address(0) ); - vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + vm.warp(YEAR + reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -302,7 +301,7 @@ contract IsOldestReportExpired is SortedOraclesTest { address(0), address(0) ); - vm.warp(YEAR_IN_SECONDS + reportExpiry - 1); + vm.warp(YEAR + reportExpiry - 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); } @@ -335,7 +334,7 @@ contract IsOldestReportExpired is SortedOraclesTest { address(0) ); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR_IN_SECONDS + newReportExpiry + 1); + vm.warp(YEAR + newReportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -352,7 +351,7 @@ contract IsOldestReportExpired is SortedOraclesTest { address(0) ); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + vm.warp(YEAR + reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); } @@ -385,7 +384,7 @@ contract IsOldestReportExpired is SortedOraclesTest { address(0) ); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR_IN_SECONDS + reportExpiry + 1); + vm.warp(YEAR + reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -402,7 +401,7 @@ contract IsOldestReportExpired is SortedOraclesTest { address(0) ); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR_IN_SECONDS + newReportExpiry + 1); + vm.warp(YEAR + newReportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -637,10 +636,10 @@ contract Report is SortedOraclesTest { sortedOracle.addOracle(aToken, anotherOracle); vm.prank(anotherOracle); sortedOracle.report(aToken, anotherOracleValue, address(0), address(0)); - vm.warp(YEAR_IN_SECONDS + 5); + vm.warp(YEAR + 5); vm.prank(oracleAccount); sortedOracle.report(aToken, oracleValue1, anotherOracle, address(0)); - vm.warp(YEAR_IN_SECONDS + 10); + vm.warp(YEAR + 10); (, uint256[] memory rateValues, ) = sortedOracle.getRates(aToken); assertEq(rateValues[0], oracleValue1); assertEq(rateValues[1], anotherOracleValue); From 9f6232104f7479b550292b7be0f0b3f8dea229e9 Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:48:28 +0100 Subject: [PATCH 19/21] PR comments --- .../test-sol/stability/SortedOracles.t.sol | 120 ++++-------------- 1 file changed, 25 insertions(+), 95 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 0b690f2c7c6..66b01493a1b 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -17,7 +17,7 @@ contract SortedOraclesTest is Test, Constants { address oracleAccount; address aToken = 0x00000000000000000000000000000000DeaDBeef; - uint256 reportExpiry = 3600; + uint256 reportExpiry = 1 * 60 * 60; // 1 hour event OracleAdded(address indexed token, address indexed oracleAddress); event OracleRemoved(address indexed token, address indexed oracleAddress); @@ -57,13 +57,13 @@ contract Initialize is SortedOraclesTest { contract SetReportExpiry is SortedOraclesTest { function test_ShouldSetReportExpiry() public { - uint256 newReportExpiry = 7200; + uint256 newReportExpiry = reportExpiry * 2; sortedOracle.setReportExpiry(newReportExpiry); assertEq(sortedOracle.reportExpirySeconds(), newReportExpiry); } function test_ShouldEmitReportExpirySetEvent() public { - uint256 newReportExpiry = 7200; + uint256 newReportExpiry = reportExpiry * 2; vm.expectEmit(true, true, true, true); emit ReportExpirySet(newReportExpiry); sortedOracle.setReportExpiry(newReportExpiry); @@ -78,13 +78,13 @@ contract SetReportExpiry is SortedOraclesTest { contract SetTokenReportExpiry is SortedOraclesTest { function test_ShouldSetTokenReportExpiry() public { - uint256 newReportExpiry = 7200; + uint256 newReportExpiry = reportExpiry * 2; sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); assertEq(sortedOracle.tokenReportExpirySeconds(aToken), newReportExpiry); } function test_ShouldEmitTokenReportExpirySetEvent() public { - uint256 newReportExpiry = 7200; + uint256 newReportExpiry = reportExpiry * 2; vm.expectEmit(true, true, true, true); emit TokenReportExpirySet(aToken, newReportExpiry); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); @@ -144,7 +144,7 @@ contract GetTokenReportExpirySeconds is SortedOraclesTest { } function test_ShouldGetTokenReportExpirySeconds_WhenTokenLevelExpiryIsSet() public { - uint256 newReportExpiry = 7200; + uint256 newReportExpiry = reportExpiry * 2; sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); assertEq(sortedOracle.getTokenReportExpirySeconds(aToken), newReportExpiry); } @@ -163,12 +163,7 @@ contract RemoveExpiredReports is SortedOraclesTest { function test_ShouldRevertWhenReportIsNotExpired() public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); vm.expectRevert("token addr null or trying to remove too many reports"); sortedOracle.removeExpiredReports(aToken, 1); } @@ -192,12 +187,7 @@ contract RemoveExpiredReports is SortedOraclesTest { public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); helper_AddMultipleReports(4); sortedOracle.removeExpiredReports(aToken, 3); assertEq(sortedOracle.numTimestamps(aToken), 5); @@ -207,12 +197,7 @@ contract RemoveExpiredReports is SortedOraclesTest { public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); helper_AddMultipleReports(4); vm.warp(YEAR + reportExpiry + 1); sortedOracle.removeExpiredReports(aToken, 3); @@ -221,12 +206,7 @@ contract RemoveExpiredReports is SortedOraclesTest { function test_ShouldRevertWhenNGreaterOrEqualToNumTimestamps() public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); helper_AddMultipleReports(4); vm.expectRevert("token addr null or trying to remove too many reports"); sortedOracle.removeExpiredReports(aToken, 5); @@ -236,12 +216,7 @@ contract RemoveExpiredReports is SortedOraclesTest { public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); helper_AddMultipleReports(4); vm.warp(YEAR + 2 * reportExpiry); sortedOracle.removeExpiredReports(aToken, 3); @@ -262,12 +237,7 @@ contract IsOldestReportExpired is SortedOraclesTest { function test_ShouldReturnTrueWhenOldestReportIsExpired() public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); vm.warp(YEAR + reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); @@ -275,12 +245,7 @@ contract IsOldestReportExpired is SortedOraclesTest { function test_ShouldReturnFalseWhenOldestReportIsNotExpired_WhenUsingDefaultExpiry() public { vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); vm.warp(YEAR + reportExpiry - 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); @@ -291,12 +256,7 @@ contract IsOldestReportExpired is SortedOraclesTest { { uint256 newReportExpiry = reportExpiry * 2; vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); @@ -307,12 +267,7 @@ contract IsOldestReportExpired is SortedOraclesTest { { uint256 newReportExpiry = reportExpiry * 2; vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); vm.warp(YEAR + newReportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); @@ -324,12 +279,7 @@ contract IsOldestReportExpired is SortedOraclesTest { { uint256 newReportExpiry = reportExpiry * 2; vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); vm.warp(YEAR + reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); @@ -341,12 +291,7 @@ contract IsOldestReportExpired is SortedOraclesTest { { uint256 newReportExpiry = reportExpiry / 2; vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); @@ -357,12 +302,7 @@ contract IsOldestReportExpired is SortedOraclesTest { { uint256 newReportExpiry = reportExpiry / 2; vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); vm.warp(YEAR + reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); @@ -374,12 +314,7 @@ contract IsOldestReportExpired is SortedOraclesTest { { uint256 newReportExpiry = reportExpiry / 2; vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); vm.warp(YEAR + newReportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); @@ -403,12 +338,7 @@ contract RemoveOracle is SortedOraclesTest { function helper_WhenThereIsMoreThanOneReportMade() public { sortedOracle.addOracle(aToken, oracleAccount2); vm.prank(oracleAccount); - sortedOracle.report( - aToken, - FixidityLib.newFixedFraction(1, 1).unwrap(), - address(0), - address(0) - ); + sortedOracle.report(aToken, FIXED1, address(0), address(0)); vm.prank(oracleAccount2); sortedOracle.report( aToken, @@ -448,7 +378,7 @@ contract RemoveOracle is SortedOraclesTest { function test_ShouldEmitMedianUpdatedEvents_WhenTHereIsMOreThanOneReportMade() public { helper_WhenThereIsMoreThanOneReportMade(); vm.expectEmit(true, true, true, true); - emit MedianUpdated(aToken, FixidityLib.newFixedFraction(1, 1).unwrap()); + emit MedianUpdated(aToken, FIXED1); sortedOracle.removeOracle(aToken, oracleAccount2, 1); } @@ -543,7 +473,7 @@ contract Report is SortedOraclesTest { address anotherOracle = actor("anotherOracle"); uint256 oracleValue1 = FixidityLib.newFixedFraction(2, 1).unwrap(); uint256 oracleValue2 = FixidityLib.newFixedFraction(3, 1).unwrap(); - uint256 anotherOracleValue = FixidityLib.newFixedFraction(1, 1).unwrap(); + uint256 anotherOracleValue = FIXED1; function setUp() public { super.setUp(); @@ -561,7 +491,7 @@ contract Report is SortedOraclesTest { sortedOracle.report(aToken, value, address(0), address(0)); (uint256 medianRate, uint256 denominator) = sortedOracle.medianRate(aToken); assertEq(medianRate, value); - assertEq(denominator, FixidityLib.newFixedFraction(1, 1).unwrap()); + assertEq(denominator, FIXED1); } function test_ShouldIncreaseTheNumberOfTimestamps() public { @@ -594,12 +524,12 @@ contract Report is SortedOraclesTest { sortedOracle.report(aToken, value, address(0), address(0)); (uint256 medianRateOriginal, uint256 denominatorOriginal) = sortedOracle.medianRate(aToken); assertEq(medianRateOriginal, value); - assertEq(denominatorOriginal, FixidityLib.newFixedFraction(1, 1).unwrap()); + assertEq(denominatorOriginal, FIXED1); vm.prank(oracleAccount); sortedOracle.report(aToken, newValue, address(0), address(0)); (uint256 medianRate, uint256 denominator) = sortedOracle.medianRate(aToken); assertEq(medianRate, newValue); - assertEq(denominator, FixidityLib.newFixedFraction(1, 1).unwrap()); + assertEq(denominator, FIXED1); } function test_ShouldNotChangeTheNumberOfTotalReports_WhenThereIsTwoReportsFromSameOracle() From b6febc91d31c9dc7e095c915265197958567e61f Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:11:56 +0100 Subject: [PATCH 20/21] warp update --- .../test-sol/stability/SortedOracles.t.sol | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index 66b01493a1b..d7ad39ed561 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -33,11 +33,15 @@ contract SortedOraclesTest is Test, Constants { event TokenReportExpirySet(address token, uint256 reportExpiry); function setUp() public { - vm.warp(YEAR); + warp(0); sortedOracle = new SortedOracles(true); oracleAccount = actor("oracleAccount"); sortedOracle.initialize(reportExpiry); } + + function warp(uint256 timeToWarpTo) public { + vm.warp(YEAR + timeToWarpTo); + } } contract Initialize is SortedOraclesTest { @@ -169,7 +173,7 @@ contract RemoveExpiredReports is SortedOraclesTest { } function helper_AddMultipleReports(uint256 numReports) public { - vm.warp(YEAR + reportExpiry / 2); + warp(reportExpiry / 2); for (uint256 i = 0; i < numReports; i++) { address oracle = actor(string(abi.encode("oracle", i))); sortedOracle.addOracle(aToken, oracle); @@ -199,7 +203,7 @@ contract RemoveExpiredReports is SortedOraclesTest { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); helper_AddMultipleReports(4); - vm.warp(YEAR + reportExpiry + 1); + warp(reportExpiry + 1); sortedOracle.removeExpiredReports(aToken, 3); assertEq(sortedOracle.numTimestamps(aToken), 4); } @@ -218,7 +222,7 @@ contract RemoveExpiredReports is SortedOraclesTest { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); helper_AddMultipleReports(4); - vm.warp(YEAR + 2 * reportExpiry); + warp(2 * reportExpiry); sortedOracle.removeExpiredReports(aToken, 3); assertEq(sortedOracle.numTimestamps(aToken), 2); } @@ -238,7 +242,7 @@ contract IsOldestReportExpired is SortedOraclesTest { function test_ShouldReturnTrueWhenOldestReportIsExpired() public { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); - vm.warp(YEAR + reportExpiry + 1); + warp(reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -246,7 +250,7 @@ contract IsOldestReportExpired is SortedOraclesTest { function test_ShouldReturnFalseWhenOldestReportIsNotExpired_WhenUsingDefaultExpiry() public { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); - vm.warp(YEAR + reportExpiry - 1); + warp(reportExpiry - 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); } @@ -269,7 +273,7 @@ contract IsOldestReportExpired is SortedOraclesTest { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR + newReportExpiry + 1); + warp(newReportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -281,7 +285,7 @@ contract IsOldestReportExpired is SortedOraclesTest { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR + reportExpiry + 1); + warp(reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, false); } @@ -304,7 +308,7 @@ contract IsOldestReportExpired is SortedOraclesTest { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR + reportExpiry + 1); + warp(reportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -316,7 +320,7 @@ contract IsOldestReportExpired is SortedOraclesTest { vm.prank(oracleAccount); sortedOracle.report(aToken, FIXED1, address(0), address(0)); sortedOracle.setTokenReportExpiry(aToken, newReportExpiry); - vm.warp(YEAR + newReportExpiry + 1); + warp(newReportExpiry + 1); (bool expired, ) = sortedOracle.isOldestReportExpired(aToken); assertEq(expired, true); } @@ -546,10 +550,10 @@ contract Report is SortedOraclesTest { sortedOracle.addOracle(aToken, anotherOracle); vm.prank(anotherOracle); sortedOracle.report(aToken, anotherOracleValue, address(0), address(0)); - vm.warp(YEAR + 5); + warp(5); vm.prank(oracleAccount); sortedOracle.report(aToken, oracleValue1, anotherOracle, address(0)); - vm.warp(YEAR + 10); + warp(10); (, uint256[] memory rateValues, ) = sortedOracle.getRates(aToken); assertEq(rateValues[0], oracleValue1); assertEq(rateValues[1], anotherOracleValue); From 93e0fbe735db4f541d54e0fc0bcb447609d5215e Mon Sep 17 00:00:00 2001 From: pahor167 <47992132+pahor167@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:23:27 +0100 Subject: [PATCH 21/21] Updated test error messages --- .../protocol/contracts/stability/SortedOracles.sol | 9 ++++----- .../protocol/test-sol/stability/SortedOracles.t.sol | 12 +++--------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/protocol/contracts/stability/SortedOracles.sol b/packages/protocol/contracts/stability/SortedOracles.sol index b5dd428f5d0..813d923127a 100644 --- a/packages/protocol/contracts/stability/SortedOracles.sol +++ b/packages/protocol/contracts/stability/SortedOracles.sol @@ -62,7 +62,7 @@ contract SortedOracles is ISortedOracles, ICeloVersionedContract, Ownable, Initi * @return Patch version of the contract. */ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 2, 2); + return (1, 1, 2, 3); } /** @@ -112,10 +112,9 @@ contract SortedOracles is ISortedOracles, ICeloVersionedContract, Ownable, Initi * @param oracleAddress The address of the oracle. */ function addOracle(address token, address oracleAddress) external onlyOwner { - require( - token != address(0) && oracleAddress != address(0) && !isOracle[token][oracleAddress], - "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" - ); + require(token != address(0), "token addr was null"); + require(oracleAddress != address(0), "oracle addr was null"); + require(!isOracle[token][oracleAddress], "oracle addr is not an oracle for token addr"); isOracle[token][oracleAddress] = true; oracles[token].push(oracleAddress); emit OracleAdded(token, oracleAddress); diff --git a/packages/protocol/test-sol/stability/SortedOracles.t.sol b/packages/protocol/test-sol/stability/SortedOracles.t.sol index d7ad39ed561..54f83a53289 100644 --- a/packages/protocol/test-sol/stability/SortedOracles.t.sol +++ b/packages/protocol/test-sol/stability/SortedOracles.t.sol @@ -121,23 +121,17 @@ contract AddOracle is SortedOraclesTest { function test_ShouldRevertWhenAlreadyOracle() public { sortedOracle.addOracle(aToken, oracleAccount); - vm.expectRevert( - "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" - ); + vm.expectRevert("oracle addr is not an oracle for token addr"); sortedOracle.addOracle(aToken, oracleAccount); } function test_ShouldRevertWhenOracleIsZeroAddress() public { - vm.expectRevert( - "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" - ); + vm.expectRevert("oracle addr was null"); sortedOracle.addOracle(aToken, address(0)); } function test_ShouldRevertWhenTokenIsZeroAddress() public { - vm.expectRevert( - "token addr was null or oracle addr was null or oracle addr is not an oracle for token addr" - ); + vm.expectRevert("token addr was null"); sortedOracle.addOracle(address(0), oracleAccount); } }