From 65d89225568ac3bfdfca49b177940da11a59f3a9 Mon Sep 17 00:00:00 2001 From: David Przybilla Date: Thu, 25 Jul 2024 12:24:33 +0900 Subject: [PATCH 1/4] llo-feeds: Tests setConfigWithActivationTime --- .../test/verifier/VerifierSetConfigTest.t.sol | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierSetConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierSetConfigTest.t.sol index 9d1cb7b1149..69f17043b98 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierSetConfigTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierSetConfigTest.t.sol @@ -112,4 +112,48 @@ contract VerifierSetConfigTest is BaseTest { vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DONConfigDoesNotExist.selector)); s_verifier.setConfigActive(3, true); } + + function test_setConfigWithActivationTime() public { + // simple case setting a config with specific activation time + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + uint32 activationTime = 10; + s_verifier.setConfigWithActivationTime( + signerAddrs, + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + activationTime + ); + } + + function test_setConfigWithActivationTimeNoFutureTimeShouldFail() public { + // calling setConfigWithActivationTime with a future timestamp should fail + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + uint32 activationTime = uint32(block.timestamp) + 100; + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); + s_verifier.setConfigWithActivationTime( + signerAddrs, + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + activationTime + ); + } + + function test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() public { + // setting a config older than the latest current config should fail + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + uint32 oldActivationTime = uint32(block.timestamp) - 1; + // sets a config with timestamp = block.timestamp + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + // setting a config with ealier timestamp retuls in failure + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); + s_verifier.setConfigWithActivationTime( + signerAddrs, + FAULT_TOLERANCE - 1, + new Common.AddressAndWeight[](0), + oldActivationTime + ); + } } From 294350a2e64db2195dcddb14d22638a7e4d40df0 Mon Sep 17 00:00:00 2001 From: David Przybilla Date: Thu, 25 Jul 2024 12:54:43 +0900 Subject: [PATCH 2/4] llo-feeds: Tests setConfigWithActivationTime --- .../test/verifier/VerifierVerifyTest.t.sol | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierVerifyTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierVerifyTest.t.sol index 9d09dd6b5b6..0725478a2e6 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierVerifyTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierVerifyTest.t.sol @@ -571,4 +571,142 @@ contract VerifierVerifyTest is BaseTest { vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); s_verifierProxy.verify(signedReport, abi.encode(native)); } + + function test_scenarioRollingNewChainWithHistoricConfigs() public { + /* + This test is checking that we can roll out in a new network and set historic configurations : + - Stars with a chain at blocktimestamp 1000 + - SetConfigA with teimstamp 100 + - SetConfigB with timesmtap 200 + - SetConfigC with timestamp current + - tries verifying reports for all the configs + */ + + vm.warp(block.timestamp + 1000); + + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersA = new BaseTest.Signer[](7); + signersA[0] = signers[0]; + signersA[1] = signers[1]; + signersA[2] = signers[2]; + signersA[3] = signers[3]; + signersA[4] = signers[4]; + signersA[5] = signers[5]; + signersA[6] = signers[6]; + + // ConfigA (historical config) + uint32 configATimestmap = 100; + address[] memory signersAddrA = _getSignerAddresses(signersA); + s_verifier.setConfigWithActivationTime( + signersAddrA, + MINIMAL_FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + configATimestmap + ); + + // ConfigB (historical config) + uint32 configBTimestmap = 200; + // Config B + BaseTest.Signer[] memory signersB = new BaseTest.Signer[](7); + // signers in ConfigA + signersB[0] = signers[8]; + signersB[1] = signers[9]; + signersB[2] = signers[10]; + signersB[3] = signers[11]; + signersB[4] = signers[12]; + signersB[5] = signers[13]; + signersB[6] = signers[14]; + address[] memory signersAddrsB = _getSignerAddresses(signersB); + s_verifier.setConfigWithActivationTime( + signersAddrsB, + MINIMAL_FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + configBTimestmap + ); + + // ConfigC (config at current timestamp) + // BaseTest.Signer[] memory signersC = new BaseTest.Signer[](7); + // signers in ConfigA + signersB[6] = signers[15]; + address[] memory signersAddrsC = _getSignerAddresses(signersB); + s_verifier.setConfig(signersAddrsC, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + vm.warp(block.timestamp + 10); + + // historical report + V3Report memory s_testReportA = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(101), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp + 1000), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + // historical report + V3Report memory s_testReportB = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(201), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp + 1000), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + // report at recent timestamp + V3Report memory s_testReportC = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp + 1000), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSignersA = new BaseTest.Signer[](3); + reportSignersA[0] = signers[0]; + reportSignersA[1] = signers[1]; + reportSignersA[2] = signers[2]; + + BaseTest.Signer[] memory reportSignersB = new BaseTest.Signer[](3); + reportSignersB[0] = signers[8]; + reportSignersB[1] = signers[9]; + reportSignersB[2] = signers[14]; + + BaseTest.Signer[] memory reportSignersC = new BaseTest.Signer[](3); + reportSignersC[0] = signers[15]; + reportSignersC[1] = signers[13]; + reportSignersC[2] = signers[12]; + + bytes memory signedReportA = _generateV3EncodedBlob(s_testReportA, s_reportContext, reportSignersA); + bytes memory signedReportB = _generateV3EncodedBlob(s_testReportB, s_reportContext, reportSignersB); + bytes memory signedReportC = _generateV3EncodedBlob(s_testReportC, s_reportContext, reportSignersC); + + // verifying historical reports + s_verifierProxy.verify(signedReportA, abi.encode(native)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + // verifiying a current report + s_verifierProxy.verify(signedReportC, abi.encode(native)); + + // current report verified by historical report fails + bytes memory signedNewReportWithOldSignatures = _generateV3EncodedBlob( + s_testReportC, + s_reportContext, + reportSignersA + ); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedNewReportWithOldSignatures, abi.encode(native)); + } } From de3893d3d77e3f6689e5cba84cf6abc2a3f9dc12 Mon Sep 17 00:00:00 2001 From: David Przybilla Date: Thu, 25 Jul 2024 12:54:57 +0900 Subject: [PATCH 3/4] llo-feeds: Tests VerifierRemoveLatestConfigTest --- .../VerifierRemoveLatestConfigTest.t.sol | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierRemoveLatestConfigTest.t.sol diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierRemoveLatestConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierRemoveLatestConfigTest.t.sol new file mode 100644 index 00000000000..52adc7c905c --- /dev/null +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/VerifierRemoveLatestConfigTest.t.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierSetConfigTest is BaseTest { + bytes32[3] internal s_reportContext; + V3Report internal s_testReport; + + function setUp() public virtual override { + BaseTest.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + } + + function test_removeLatestConfigWhenNoConfigShouldFail() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DONConfigDoesNotExist.selector)); + s_verifier.removeLatestConfig(); + } + + function test_removeLatestConfig() public { + /* + This test sets two Configs: Config A and Config B. + - it removes and readds config B multiple times while trying Config A verifications + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersA = new BaseTest.Signer[](7); + signersA[0] = signers[0]; + signersA[1] = signers[1]; + signersA[2] = signers[2]; + signersA[3] = signers[3]; + signersA[4] = signers[4]; + signersA[5] = signers[5]; + signersA[6] = signers[6]; + + // ConfigA + address[] memory signersAddrA = _getSignerAddresses(signersA); + s_verifier.setConfig(signersAddrA, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 10); + V3Report memory s_testReportA = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + vm.warp(block.timestamp + 100); + // Config B + BaseTest.Signer[] memory signersB = new BaseTest.Signer[](7); + // signers in ConfigA + signersB[0] = signers[8]; + signersB[1] = signers[9]; + signersB[2] = signers[10]; + signersB[3] = signers[11]; + signersB[4] = signers[12]; + signersB[5] = signers[13]; + signersB[6] = signers[14]; + address[] memory signersAddrsB = _getSignerAddresses(signersB); + s_verifier.setConfig(signersAddrsB, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory s_testReportB = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSignersA = new BaseTest.Signer[](3); + reportSignersA[0] = signers[0]; + reportSignersA[1] = signers[1]; + reportSignersA[2] = signers[2]; + + BaseTest.Signer[] memory reportSignersB = new BaseTest.Signer[](3); + reportSignersB[0] = signers[8]; + reportSignersB[1] = signers[9]; + reportSignersB[2] = signers[10]; + + bytes memory signedReportA = _generateV3EncodedBlob(s_testReportA, s_reportContext, reportSignersA); + bytes memory signedReportB = _generateV3EncodedBlob(s_testReportB, s_reportContext, reportSignersB); + + // verifying should work + s_verifierProxy.verify(signedReportA, abi.encode(native)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + + s_verifier.removeLatestConfig(); + + // this should remove the latest config, so ConfigA should be able to verify reports still + s_verifierProxy.verify(signedReportA, abi.encode(native)); + // this report cannot be verified any longer because ConfigB is not there + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + + // since ConfigB is removed we should be able to set it again with no errors + s_verifier.setConfig(signersAddrsB, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + // we should be able to remove ConfigB + s_verifier.removeLatestConfig(); + // removing configA + s_verifier.removeLatestConfig(); + + // verifigny should fail + // verifying should work + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReportA, abi.encode(native)); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + + // removing again should fail. no other configs exist + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DONConfigDoesNotExist.selector)); + s_verifier.removeLatestConfig(); + } +} From 1d1dc8de0b54eca2f2ce65bbd85c6b408db110c5 Mon Sep 17 00:00:00 2001 From: David Przybilla Date: Thu, 25 Jul 2024 13:08:54 +0900 Subject: [PATCH 4/4] llo-feeds: fixing linter errors (unused imports) --- .../src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol | 2 -- .../llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol | 3 --- 2 files changed, 5 deletions(-) diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol index 85324972c94..42372f13ca5 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol @@ -3,9 +3,7 @@ pragma solidity 0.8.19; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../libraries/Common.sol"; import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; import {IDestinationVerifier} from "./interfaces/IDestinationVerifier.sol"; diff --git a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol index 7790caf9a62..15b8022b053 100644 --- a/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol +++ b/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol @@ -1,9 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {Common} from "../../libraries/Common.sol"; -import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; - interface IDestinationVerifierProxy { /** * @notice Verifies that the data encoded has been signed