diff --git a/contracts/gas-snapshots/feeds.gas-snapshot b/contracts/gas-snapshots/feeds.gas-snapshot index b5701e3df09..3aaf609831d 100644 --- a/contracts/gas-snapshots/feeds.gas-snapshot +++ b/contracts/gas-snapshots/feeds.gas-snapshot @@ -1,58 +1,58 @@ -AcceptPayeeship:test_EmitsPayeeshipTransferred() (gas: 27046) -AcceptPayeeship:test_RevertIf_SenderIsNotProposed() (gas: 15265) -Constructor:test_constructor() (gas: 11815) +AcceptPayeeship:test_EmitsPayeeshipTransferred() (gas: 27068) +AcceptPayeeship:test_RevertIf_SenderIsNotProposed() (gas: 15287) +Constructor:test_constructor() (gas: 30920) Description:test_ReturnsCorrectDescription() (gas: 12439) -GetAnswer:test_ReturnsPrimaryGetAnswer() (gas: 206955) -GetAnswer:test_ReturnsPrimaryGetAnswerAfterBlock() (gas: 210110) -GetAnswer:test_ReturnsPrimaryGetAnswerNotAllowed() (gas: 209689) -GetAnswer:test_ReturnsSecondaryGetAnswer() (gas: 209729) -GetAnswer:test_ReturnsSecondaryGetAnswerNotAllowed() (gas: 212227) -GetAnswer:test_ReturnsSecondaryGetAnswerSynced() (gas: 216996) -GetBilling:test_ReturnsBillingData() (gas: 16726) -GetBillingAccessController:test_ReturnsBillingAccessController() (gas: 11011) -GetLinkToken:test_ReturnsLinkToken() (gas: 13081) -GetRequesterAccessController:test_ReturnsRequesterAccessController() (gas: 13063) -GetRoundData:test_ReturnsPrimaryGetRoundData() (gas: 209178) -GetRoundData:test_ReturnsPrimaryGetRoundDataAfterBlock() (gas: 212350) -GetRoundData:test_ReturnsPrimaryGetRoundDataNotAllowed() (gas: 211813) -GetRoundData:test_ReturnsSecondaryGetRoundData() (gas: 211979) -GetRoundData:test_ReturnsSecondaryGetRoundDataNotAllowed() (gas: 214364) -GetRoundData:test_ReturnsSecondaryGetRoundDataSynced() (gas: 219222) -GetSyncPrimaryRound:test_returnSecondaryRoundId() (gas: 213744) -GetSyncPrimaryRound:test_returnSyncFourthRoundId() (gas: 212219) -GetSyncPrimaryRound:test_returnSyncLatestRoundId() (gas: 210430) -GetSyncPrimaryRound:test_zeroTransmissions() (gas: 12884) -GetTimestamp:test_ReturnsPrimaryGetTimestamp() (gas: 207023) -GetTimestamp:test_ReturnsPrimaryGetTimestampAfterBlock() (gas: 210136) -GetTimestamp:test_ReturnsPrimaryGetTimestampNotAllowed() (gas: 209712) -GetTimestamp:test_ReturnsSecondaryGetTimestamp() (gas: 209740) -GetTimestamp:test_ReturnsSecondaryGetTimestampNotAllowed() (gas: 212248) -GetTimestamp:test_ReturnsSecondaryGetTimestampSynced() (gas: 217029) -GetTransmitters:test_ReturnsTransmittersList() (gas: 161077) -GetValidatorConfig:test_ReturnsValidatorConfig() (gas: 14244) -LatestAnswer:test_ReturnsLatestPrimaryAnswer() (gas: 209678) -LatestAnswer:test_ReturnsLatestPrimaryAnswerAfterBlock() (gas: 210031) -LatestAnswer:test_ReturnsLatestSecondaryAnswer() (gas: 210031) -LatestAnswer:test_ReturnsPreviousPrimaryAnswer() (gas: 209798) -LatestAnswer:test_ReturnsSyncedAnswer() (gas: 215813) -LatestConfigDetails:test_ReturnsConfigDetails() (gas: 191094) -LatestConfigDigestAndEpoch:test_ReturnsLatestConfigDigestAndEpoch() (gas: 191064) -LatestRound:test_ReturnsLatestPrimaryRoundId() (gas: 209506) -LatestRound:test_ReturnsLatestPrimaryRoundIdAfterBlock() (gas: 209905) -LatestRound:test_ReturnsLatestSecondaryRoundId() (gas: 209902) -LatestRound:test_ReturnsPreviousPrimaryRoundId() (gas: 209649) -LatestRound:test_ReturnsSyncedRoundId() (gas: 215642) -LatestRoundData:test_ReturnsLatestPrimaryRoundData() (gas: 211852) -LatestRoundData:test_ReturnsLatestPrimaryRoundDataAfterBlock() (gas: 212192) -LatestRoundData:test_ReturnsLatestSecondaryRoundData() (gas: 212256) -LatestRoundData:test_ReturnsPreviousPrimaryRoundData() (gas: 211974) -LatestRoundData:test_ReturnsSyncedRoundData() (gas: 218027) -LatestTimestamp:test_ReturnsLatestPrimaryTimestamp() (gas: 209687) -LatestTimestamp:test_ReturnsLatestPrimaryTimestampAfterBlock() (gas: 210063) -LatestTimestamp:test_ReturnsLatestSecondaryTimestamp() (gas: 210106) -LatestTimestamp:test_ReturnsPreviousPrimaryTimestamp() (gas: 209809) -LatestTimestamp:test_ReturnsSyncedTimestamp() (gas: 215887) -LatestTransmissionDetails:test_ReturnsLatestTransmissionDetails() (gas: 17646) +GetAnswer:test_ReturnsPrimaryGetAnswer() (gas: 163009) +GetAnswer:test_ReturnsPrimaryGetAnswerAfterBlock() (gas: 166164) +GetAnswer:test_ReturnsPrimaryGetAnswerNotAllowed() (gas: 165743) +GetAnswer:test_ReturnsSecondaryGetAnswer() (gas: 165519) +GetAnswer:test_ReturnsSecondaryGetAnswerNotAllowed() (gas: 168281) +GetAnswer:test_ReturnsSecondaryGetAnswerSynced() (gas: 172477) +GetBilling:test_ReturnsBillingData() (gas: 16704) +GetBillingAccessController:test_ReturnsBillingAccessController() (gas: 11033) +GetLinkToken:test_ReturnsLinkToken() (gas: 13131) +GetRequesterAccessController:test_ReturnsRequesterAccessController() (gas: 18435) +GetRoundData:test_ReturnsPrimaryGetRoundData() (gas: 165177) +GetRoundData:test_ReturnsPrimaryGetRoundDataAfterBlock() (gas: 168371) +GetRoundData:test_ReturnsPrimaryGetRoundDataNotAllowed() (gas: 167812) +GetRoundData:test_ReturnsSecondaryGetRoundData() (gas: 167714) +GetRoundData:test_ReturnsSecondaryGetRoundDataNotAllowed() (gas: 170341) +GetRoundData:test_ReturnsSecondaryGetRoundDataSynced() (gas: 174671) +GetSyncPrimaryRound:test_returnSecondaryRoundId() (gas: 169199) +GetSyncPrimaryRound:test_returnSyncFourthRoundId() (gas: 167846) +GetSyncPrimaryRound:test_returnSyncLatestRoundId() (gas: 166309) +GetSyncPrimaryRound:test_zeroTransmissions() (gas: 12898) +GetTimestamp:test_ReturnsPrimaryGetTimestamp() (gas: 162966) +GetTimestamp:test_ReturnsPrimaryGetTimestampAfterBlock() (gas: 166100) +GetTimestamp:test_ReturnsPrimaryGetTimestampNotAllowed() (gas: 165699) +GetTimestamp:test_ReturnsSecondaryGetTimestamp() (gas: 165463) +GetTimestamp:test_ReturnsSecondaryGetTimestampNotAllowed() (gas: 168235) +GetTimestamp:test_ReturnsSecondaryGetTimestampSynced() (gas: 172466) +GetTransmitters:test_ReturnsTransmittersList() (gas: 161033) +GetValidatorConfig:test_ReturnsValidatorConfig() (gas: 37637) +LatestAnswer:test_ReturnsLatestPrimaryAnswer() (gas: 165707) +LatestAnswer:test_ReturnsLatestPrimaryAnswerAfterBlock() (gas: 166093) +LatestAnswer:test_ReturnsLatestSecondaryAnswer() (gas: 166093) +LatestAnswer:test_ReturnsPreviousPrimaryAnswer() (gas: 165872) +LatestAnswer:test_ReturnsSyncedAnswer() (gas: 171457) +LatestConfigDetails:test_ReturnsConfigDetails() (gas: 16815) +LatestConfigDigestAndEpoch:test_ReturnsLatestConfigDigestAndEpoch() (gas: 186558) +LatestRound:test_ReturnsLatestPrimaryRoundId() (gas: 165493) +LatestRound:test_ReturnsLatestPrimaryRoundIdAfterBlock() (gas: 165880) +LatestRound:test_ReturnsLatestSecondaryRoundId() (gas: 165877) +LatestRound:test_ReturnsPreviousPrimaryRoundId() (gas: 165636) +LatestRound:test_ReturnsSyncedRoundId() (gas: 171199) +LatestRoundData:test_ReturnsLatestPrimaryRoundData() (gas: 167873) +LatestRoundData:test_ReturnsLatestPrimaryRoundDataAfterBlock() (gas: 168213) +LatestRoundData:test_ReturnsLatestSecondaryRoundData() (gas: 168277) +LatestRoundData:test_ReturnsPreviousPrimaryRoundData() (gas: 168038) +LatestRoundData:test_ReturnsSyncedRoundData() (gas: 173641) +LatestTimestamp:test_ReturnsLatestPrimaryTimestamp() (gas: 165674) +LatestTimestamp:test_ReturnsLatestPrimaryTimestampAfterBlock() (gas: 166038) +LatestTimestamp:test_ReturnsLatestSecondaryTimestamp() (gas: 166081) +LatestTimestamp:test_ReturnsPreviousPrimaryTimestamp() (gas: 165796) +LatestTimestamp:test_ReturnsSyncedTimestamp() (gas: 171444) +LatestTransmissionDetails:test_ReturnsLatestTransmissionDetails() (gas: 19740) LatestTransmissionDetails:test_RevertIf_NotEOA() (gas: 8558) LinkAvailableForPayment:test_ReturnsBalanceWhenNothingDue() (gas: 40404) LinkAvailableForPayment:test_ReturnsRemainingBalanceWhenHasDues() (gas: 164) @@ -60,50 +60,61 @@ OracleObservationCount:test_ReturnsCorrectObservationCount() (gas: 164) OracleObservationCount:test_ReturnsZeroWhenNoObservations() (gas: 20040) OwedPayment:test_ReturnOwedAmount() (gas: 20440) OwedPayment:test_ReturnZeroIfTransmitterNotActive() (gas: 20441) -SetBilling:test_EmitsBillingSet() (gas: 56804) -SetBilling:test_RevertIf_NotOwner() (gas: 15214) -SetBillingAccessController:test_EmitsBillingAccessControllerSet() (gas: 22756) -SetConfig:test_HappyPath() (gas: 3048461) +RequestNewRound:test_RevertIf_NotRequester() (gas: 15094) +RequestNewRound:test_ShouldRequestNewRound() (gas: 34290) +SetBilling:test_EmitsBillingSet() (gas: 56836) +SetBilling:test_RevertIf_NotOwner() (gas: 15279) +SetBillingAccessController:test_EmitsBillingAccessControllerSet() (gas: 22778) SetConfig:test_RevertIf_OracleLengthMismatch() (gas: 27450) SetConfig:test_RevertIf_RepeatedSigner() (gas: 120296) SetConfig:test_RevertIf_RepeatedTransmitter() (gas: 143058) -SetConfig:test_RevertIf_SignersTooLong() (gas: 27852) +SetConfig:test_RevertIf_SignersTooLong() (gas: 27874) SetConfig:test_RevertIf_fNotPositive() (gas: 14430) SetConfig:test_RevertIf_fTooHigh() (gas: 14265) SetConfig:test_RevertIf_onchainConfigInvalid() (gas: 27927) -SetLinkToken:test_EmitsLinkTokenSet() (gas: 227728) -SetPayees:test_EmitsPayeeshipTransferred() (gas: 328494) -SetRequesterAccessController:test_EmitsRequesterAccessControllerSet() (gas: 22675) -SetValidatorConfig:test_EmitsValidatorConfigSet() (gas: 41602) +SetConfig:test_SetsTheConfigAndEmitsEvent() (gas: 3103066) +SetConfig:test_ShouldBeAbleToRemoveSigners() (gas: 3641924) +SetLinkToken:test_EmitsLinkTokenSet() (gas: 227769) +SetPayees:test_EmitsPayeeshipTransferred() (gas: 1005423) +SetRequesterAccessController:test_EmitsRequesterAccessControllerSet() (gas: 18362) +SetValidatorConfig:test_EmitsValidatorConfigSet() (gas: 37293) TransferPayeeship:test_EmitsPayeeshipTransferredRequested() (gas: 46313) TransferPayeeship:test_RevertIf_SenderIsProposed() (gas: 19978) TransferPayeeship:test_RevertIf_SenderNotCurrentPayee() (gas: 10713) -Transmit:test_BothFeedsStalledIncomingPrimaryReportIsFromBeforeCutoffTime() (gas: 421798) -Transmit:test_BothFeedsStalledIncomingReportIsFromAfterCutoffTime() (gas: 421290) -Transmit:test_BothFeedsStalledIncomingSecondaryReportIsFromBeforeCutoffTime() (gas: 465809) -Transmit:test_IncomingSecondaryReportHasNotBeenRecordedOlderThanLatestReportNewerThanCutoffTime() (gas: 514430) -Transmit:test_IncomingSecondaryReportHasNotBeenRecordedOlderThanLatestReportOlderThanCutoffTime() (gas: 524754) -Transmit:test_IncomingSecondaryReportRevertsDueToMaxIterations() (gas: 811371) -Transmit:test_OutOfSyncFeedsPrimaryIsSourcedFromSecondaryWithLockDelay() (gas: 420967) -Transmit:test_OutOfSyncFeedsSecondaryFeedFallbackToStandardFeed() (gas: 813559) -Transmit:test_ReadExpectedInitialState() (gas: 146843) -Transmit:test_RevertIf_CalldataLengthMismatch() (gas: 23346) -Transmit:test_RevertIf_ConfigDigestMismatch() (gas: 20943) -Transmit:test_RevertIf_DuplicateSigner() (gas: 83078) -Transmit:test_RevertIf_SendTheSameReportAlternateFirstPrimaryFeed() (gas: 370986) -Transmit:test_RevertIf_SendTheSameReportAlternateFirstSecondaryFeed() (gas: 368526) -Transmit:test_RevertIf_SendTheSameReportTwiceToThePrimaryFeed() (gas: 278088) -Transmit:test_RevertIf_SendTheSameReportTwiceToTheSecondaryFeed() (gas: 281419) -Transmit:test_RevertIf_SignatureError() (gas: 79780) -Transmit:test_RevertIf_SignaturesOutOfRegistration() (gas: 25147) -Transmit:test_RevertIf_UnauthorizedTransmitter() (gas: 14158) -Transmit:test_RevertIf_WrongNumberOfSignatures() (gas: 25004) -Transmit:test_SyncFeedsTransmitSecondaryFirstAlwaysSameBlock() (gas: 488893) -Transmit:test_SyncFeedsTransmitSecondaryFirstNeverSameBlock() (gas: 489861) -Transmit:test_SyncFeedsTransmitStandardFirstAlwaysSameBlock() (gas: 489823) -Transmit:test_SyncFeedsTransmitStandardFirstNeverSameBlock() (gas: 532533) -TypeAndVersion:test_IsCorrect() (gas: 10108) -WithdrawFunds:test_RevertIf_InsufficientFunds() (gas: 191227) -WithdrawFunds:test_RevertIf_NotOwner() (gas: 14829) +Transmit:test_BothFeedsStalledIncomingPrimaryReportIsFromBeforeCutoffTime() (gas: 420630) +Transmit:test_BothFeedsStalledIncomingReportIsFromAfterCutoffTime() (gas: 420166) +Transmit:test_BothFeedsStalledIncomingSecondaryReportIsFromBeforeCutoffTime() (gas: 465131) +Transmit:test_IncomingSecondaryReportHasNotBeenRecordedOlderThanLatestReportNewerThanCutoffTime() (gas: 511883) +Transmit:test_IncomingSecondaryReportHasNotBeenRecordedOlderThanLatestReportOlderThanCutoffTime() (gas: 520986) +Transmit:test_IncomingSecondaryReportRevertsDueToMaxIterations() (gas: 806380) +Transmit:test_OutOfSyncFeedsPrimaryIsSourcedFromSecondaryWithLockDelay() (gas: 420722) +Transmit:test_OutOfSyncFeedsSecondaryFeedFallbackToStandardFeed() (gas: 810613) +Transmit:test_ReadExpectedInitialState() (gas: 146990) +Transmit:test_RevertIf_CalldataLengthMismatch() (gas: 23391) +Transmit:test_RevertIf_ConfigDigestMismatch() (gas: 20932) +Transmit:test_RevertIf_DuplicateSigner() (gas: 83230) +Transmit:test_RevertIf_MedianIsOutOfMinMaxRange() (gas: 159659) +Transmit:test_RevertIf_NumObservationsOutOfBounds() (gas: 97900) +Transmit:test_RevertIf_ReportLengthMismatch() (gas: 90900) +Transmit:test_RevertIf_SendTheSameReportAlternateFirstPrimaryFeed() (gas: 365939) +Transmit:test_RevertIf_SendTheSameReportAlternateFirstSecondaryFeed() (gas: 363743) +Transmit:test_RevertIf_SendTheSameReportTwiceToThePrimaryFeed() (gas: 275529) +Transmit:test_RevertIf_SendTheSameReportTwiceToTheSecondaryFeed() (gas: 279080) +Transmit:test_RevertIf_SignatureError() (gas: 79943) +Transmit:test_RevertIf_SignaturesOutOfRegistration() (gas: 25163) +Transmit:test_RevertIf_TooFewValuesToTrustMedian() (gas: 72143) +Transmit:test_RevertIf_UnauthorizedTransmitter() (gas: 14180) +Transmit:test_RevertIf_WrongNumberOfSignatures() (gas: 25024) +Transmit:test_SyncFeedsTransmitSecondaryFirstAlwaysSameBlock() (gas: 488281) +Transmit:test_SyncFeedsTransmitSecondaryFirstNeverSameBlock() (gas: 489249) +Transmit:test_SyncFeedsTransmitStandardFirstAlwaysSameBlock() (gas: 489123) +Transmit:test_SyncFeedsTransmitStandardFirstNeverSameBlock() (gas: 531537) +TypeAndVersion:test_IsCorrect() (gas: 10130) +ValidateAnswer:test_RevertIf_InsufficientGas() (gas: 332116) +ValidateAnswer:test_ValidateWithContractAddress() (gas: 376760) +ValidateAnswer:test_ValidateWithZeroAddressContract() (gas: 247172) +WithdrawFunds:test_RevertIf_InsufficientBalance() (gas: 340375) +WithdrawFunds:test_RevertIf_InsufficientFunds() (gas: 191296) +WithdrawFunds:test_RevertIf_NotOwner() (gas: 14903) WithdrawPayment:test_PaysOracles() (gas: 165) -WithdrawPayment:test_RevertIf_NotPayee() (gas: 10572) \ No newline at end of file +WithdrawPayment:test_RevertIf_NotPayee() (gas: 10571) \ No newline at end of file diff --git a/contracts/src/v0.8/feeds/DualAggregator.sol b/contracts/src/v0.8/feeds/DualAggregator.sol index 6a3a200cb68..c1eba4bf20a 100644 --- a/contracts/src/v0.8/feeds/DualAggregator.sol +++ b/contracts/src/v0.8/feeds/DualAggregator.sol @@ -382,9 +382,8 @@ contract DualAggregator is OCR2Abstract, Ownable2StepMsgSender, AggregatorV2V3In /// @return the aggregatorRoundId of the next round. Note: The report for this round may have been /// transmitted (but not yet mined) *before* requestNewRound() was even called. There is *no* /// guarantee of causality between the request and the report at aggregatorRoundId. - // TODO: i think we can remove this function entirely function requestNewRound() external returns (uint80) { - if (!(msg.sender == owner() || s_requesterAccessController.hasAccess(msg.sender, msg.data))) { + if (msg.sender != owner() && !s_requesterAccessController.hasAccess(msg.sender, msg.data)) { revert OnlyOwnerAndRequesterCanCall(); } @@ -875,7 +874,7 @@ contract DualAggregator is OCR2Abstract, Ownable2StepMsgSender, AggregatorV2V3In // get median, validate its range, store it in new aggregator round int192 median = report.observations[report.observations.length / 2]; - if (i_minAnswer > median && median > i_maxAnswer) revert MedianIsOutOfMinMaxRange(); + if (i_minAnswer > median || median > i_maxAnswer) revert MedianIsOutOfMinMaxRange(); hotVars.latestAggregatorRoundId++; s_transmissions[hotVars.latestAggregatorRoundId] = Transmission({ @@ -1154,7 +1153,7 @@ contract DualAggregator is OCR2Abstract, Ownable2StepMsgSender, AggregatorV2V3In uint24 accountingGas ) external { AccessControllerInterface access = s_billingAccessController; - if (!(msg.sender == owner() || access.hasAccess(msg.sender, msg.data))) { + if (msg.sender != owner() && !access.hasAccess(msg.sender, msg.data)) { revert OnlyOwnerAndBillingAdminCanCall(); } _payOracles(); @@ -1208,7 +1207,7 @@ contract DualAggregator is OCR2Abstract, Ownable2StepMsgSender, AggregatorV2V3In function withdrawPayment( address transmitter ) external { - if (!(msg.sender == s_payees[transmitter])) revert OnlyPayeeCanWithdraw(); + if (msg.sender != s_payees[transmitter]) revert OnlyPayeeCanWithdraw(); _payOracle(transmitter); } @@ -1303,7 +1302,7 @@ contract DualAggregator is OCR2Abstract, Ownable2StepMsgSender, AggregatorV2V3In /// @param amount maximum amount to withdraw, denominated in LINK-wei. /// @dev access control provided by billingAccessController function withdrawFunds(address recipient, uint256 amount) external { - if (!(msg.sender == owner() || s_billingAccessController.hasAccess(msg.sender, msg.data))) { + if (msg.sender != owner() && !s_billingAccessController.hasAccess(msg.sender, msg.data)) { revert OnlyOwnerAndBillingAdminCanCall(); } uint256 linkDue = _totalLinkDue(); @@ -1497,7 +1496,7 @@ contract DualAggregator is OCR2Abstract, Ownable2StepMsgSender, AggregatorV2V3In address payee = payees[i]; address currentPayee = s_payees[transmitter]; bool zeroedOut = currentPayee == address(0); - if (!(zeroedOut || currentPayee == payee)) revert PayeeAlreadySent(); + if (!zeroedOut && currentPayee != payee) revert PayeeAlreadySent(); s_payees[transmitter] = payee; if (currentPayee != payee) { diff --git a/contracts/src/v0.8/feeds/test/DualAggregator.t.sol b/contracts/src/v0.8/feeds/test/DualAggregator.t.sol index 12e47284b30..58629355f42 100644 --- a/contracts/src/v0.8/feeds/test/DualAggregator.t.sol +++ b/contracts/src/v0.8/feeds/test/DualAggregator.t.sol @@ -556,8 +556,43 @@ contract GetRequesterAccessController is DualAggregatorBaseTest { } } -// TODO: determine if we need this method still -contract RequestNewRound is ConfiguredDualAggregatorBaseTest {} +contract RequestNewRound is ConfiguredDualAggregatorBaseTest { + event RoundRequested(address indexed requester, bytes32 configDigest, uint32 epoch, uint8 round); + + address internal constant USER = address(777); + + function test_RevertIf_NotRequester() public { + _changePrank(USER); + + vm.mockCall( + REQUESTER_ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(false) + ); + + vm.expectRevert(DualAggregator.OnlyOwnerAndRequesterCanCall.selector); + s_aggregator.requestNewRound(); + } + + function test_ShouldRequestNewRound() public { + uint256 currentRoundId = s_aggregator.getHotVars().latestAggregatorRoundId; + uint40 currentEpochAndRound = s_aggregator.getHotVars().latestEpochAndRound; + + vm.mockCall( + REQUESTER_ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(true) + ); + + _changePrank(USER); + + vm.expectEmit(); + emit RoundRequested(USER, s_configDigest, uint32(currentEpochAndRound >> 8), uint8(currentEpochAndRound)); + uint256 newRoundId = s_aggregator.requestNewRound(); + + assertEq(newRoundId, currentRoundId + 1, "round id not incremented"); + } +} contract Transmit is ConfiguredDualAggregatorBaseTest { uint32 constant CUTOFF_TIME = 40; @@ -682,6 +717,61 @@ contract Transmit is ConfiguredDualAggregatorBaseTest { ); } + function test_RevertIf_ReportLengthMismatch() public { + ReportGenerator.SignedReport memory signedReport = + s_reportGenerator.generateSignedReportWithLengthMismatch(0, uint32(block.timestamp)); + + _changePrank(s_transmitters[0]); + + vm.expectRevert(DualAggregator.ReportLengthMismatch.selector); + s_aggregator.transmit( + signedReport.reportContext, signedReport.report, signedReport.rs, signedReport.ss, signedReport.rawVs + ); + } + + function test_RevertIf_NumObservationsOutOfBounds() public { + ReportGenerator.SignedReport memory signedReport = + s_reportGenerator.generateSignedReportWithTooManyOracles(0, uint32(block.timestamp)); + + _changePrank(s_transmitters[0]); + + vm.expectRevert(DualAggregator.NumObservationsOutOfBounds.selector); + s_aggregator.transmit( + signedReport.reportContext, signedReport.report, signedReport.rs, signedReport.ss, signedReport.rawVs + ); + } + + function test_RevertIf_TooFewValuesToTrustMedian() public { + ReportGenerator.SignedReport memory signedReport = + s_reportGenerator.generateSignedReportWithFOracles(0, uint32(block.timestamp), s_f); + + _changePrank(s_transmitters[0]); + + vm.expectRevert(DualAggregator.TooFewValuesToTrustMedian.selector); + s_aggregator.transmit( + signedReport.reportContext, signedReport.report, signedReport.rs, signedReport.ss, signedReport.rawVs + ); + } + + function test_RevertIf_MedianIsOutOfMinMaxRange() public { + ReportGenerator.SignedReport memory signedReport = + s_reportGenerator.generateSignedReport(MAX_ANSWER + 1, uint32(block.timestamp)); + + _changePrank(s_transmitters[0]); + + vm.expectRevert(DualAggregator.MedianIsOutOfMinMaxRange.selector); + s_aggregator.transmit( + signedReport.reportContext, signedReport.report, signedReport.rs, signedReport.ss, signedReport.rawVs + ); + + signedReport = s_reportGenerator.generateSignedReport(MIN_ANSWER - 1, uint32(block.timestamp)); + + vm.expectRevert(DualAggregator.MedianIsOutOfMinMaxRange.selector); + s_aggregator.transmit( + signedReport.reportContext, signedReport.report, signedReport.rs, signedReport.ss, signedReport.rawVs + ); + } + function test_RevertIf_SendTheSameReportTwiceToThePrimaryFeed() public { Report memory report1 = Report({price: 1, timestamp: uint32(block.timestamp)}); ReportGenerator.SignedReport memory signedReport1 = diff --git a/contracts/src/v0.8/feeds/test/testhelpers/DualAggregatorHelper.sol b/contracts/src/v0.8/feeds/test/testhelpers/DualAggregatorHelper.sol index b5a2bfdc21f..cf4d0641a50 100644 --- a/contracts/src/v0.8/feeds/test/testhelpers/DualAggregatorHelper.sol +++ b/contracts/src/v0.8/feeds/test/testhelpers/DualAggregatorHelper.sol @@ -64,4 +64,8 @@ contract DualAggregatorHelper is DualAggregator { function totalLinkDue() public view returns (uint256 linkDue) { return _totalLinkDue(); } + + function getHotVars() public view returns (HotVars memory) { + return s_hotVars; + } } diff --git a/contracts/src/v0.8/feeds/test/testhelpers/ReportGenerator.t.sol b/contracts/src/v0.8/feeds/test/testhelpers/ReportGenerator.t.sol index bf7d2170dce..cfeb1e1acf5 100644 --- a/contracts/src/v0.8/feeds/test/testhelpers/ReportGenerator.t.sol +++ b/contracts/src/v0.8/feeds/test/testhelpers/ReportGenerator.t.sol @@ -48,6 +48,81 @@ contract ReportGenerator is Test { return SignedReport({reportContext: reportContext, report: report, rs: rs, ss: ss, rawVs: rawVs}); } + function generateSignedReportWithLengthMismatch( + int192 price, + uint32 observationTimestamp + ) public returns (SignedReport memory) { + // build report + bytes memory report = _buildReport(price, observationTimestamp); + + // add extra faulty bytes to the report + report = abi.encode(report, uint8(7)); + + // build report context + bytes32[3] memory reportContext = _buildReportContext(); + + // sign report + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _signReport(report, reportContext); + + ++s_currentEpoch; + + return SignedReport({reportContext: reportContext, report: report, rs: rs, ss: ss, rawVs: rawVs}); + } + + function generateSignedReportWithTooManyOracles( + int192 price, + uint32 observationTimestamp + ) public returns (SignedReport memory) { + // add new oracle + uint256 newOraclePrivateKey = 123456789; + s_oraclePrivateKeys.push(newOraclePrivateKey); + + // build report + bytes memory report = _buildReport(price, observationTimestamp); + + // build report context + bytes32[3] memory reportContext = _buildReportContext(); + + // sign report + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _signReport(report, reportContext); + + ++s_currentEpoch; + + // remove new oracle + s_oraclePrivateKeys.pop(); + + return SignedReport({reportContext: reportContext, report: report, rs: rs, ss: ss, rawVs: rawVs}); + } + + function generateSignedReportWithFOracles( + int192 price, + uint32 observationTimestamp, + uint8 f + ) public returns (SignedReport memory) { + // build the observers bytes (string of uint8 id numbers for each observer) and observations array + bytes memory rawObservers = new bytes(f); + int192[] memory observations = new int192[](f); + for (uint256 i; i < f; ++i) { + rawObservers[i] = bytes1(uint8(i)); + observations[i] = price; + } + // We can convert because we know the length of the array is less than 32 + bytes32 observers = bytes32(rawObservers); + + // build report + bytes memory report = abi.encode(observationTimestamp, observers, observations, JUELS_PER_FEECOIN); + + // build report context + bytes32[3] memory reportContext = _buildReportContext(); + + // sign report + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _signReport(report, reportContext); + + ++s_currentEpoch; + + return SignedReport({reportContext: reportContext, report: report, rs: rs, ss: ss, rawVs: rawVs}); + } + function _buildReport(int192 price, uint32 observationTimestamp) internal view returns (bytes memory) { // build the observers bytes (string of uint8 id numbers for each observer) and observations array bytes memory rawObservers = new bytes(s_oraclePrivateKeys.length);