diff --git a/contracts/v0.2/src/SubmissionProxy.sol b/contracts/v0.2/src/SubmissionProxy.sol index 0c5709b2e..b4a66a60c 100644 --- a/contracts/v0.2/src/SubmissionProxy.sol +++ b/contracts/v0.2/src/SubmissionProxy.sol @@ -406,7 +406,7 @@ contract SubmissionProxy is Ownable { * @param _timestamps The unixmilli timestamps of the proofs * @param _proofs The proofs */ - function submitStrictBatch( + function submitStrict( bytes32[] calldata _feedHashes, int256[] calldata _answers, uint256[] calldata _timestamps, @@ -471,14 +471,14 @@ contract SubmissionProxy is Ownable { /** * @notice Submit a batch of answers to multiple feeds. The answers are - * ignored if they have been superseeded. If any of the answers do not + * ignored if they have been superseded. If any of the answers do not * meet the rest of required conditions the whole batch is reverted. * @param _feedHashes The hashes of the feeds * @param _answers The submissions * @param _timestamps The unixmilli timestamps of the proofs * @param _proofs The proofs */ - function updatePrices( + function submitWithoutSupersedValidation( bytes32[] calldata _feedHashes, int256[] calldata _answers, uint256[] calldata _timestamps, @@ -493,7 +493,7 @@ contract SubmissionProxy is Ownable { uint256 feedsLength_ = _feedHashes.length; for (uint256 i = 0; i < feedsLength_; i++) { - updatePrice(_feedHashes[i], _answers[i], _timestamps[i], _proofs[i]); + submitSingleWithoutSupersedValidation(_feedHashes[i], _answers[i], _timestamps[i], _proofs[i]); } } @@ -506,7 +506,12 @@ contract SubmissionProxy is Ownable { * @param _timestamp The unixmilli timestamp of the proof * @param _proof The proof */ - function updatePrice(bytes32 _feedHash, int256 _answer, uint256 _timestamp, bytes calldata _proof) public { + function submitSingleWithoutSupersedValidation( + bytes32 _feedHash, + int256 _answer, + uint256 _timestamp, + bytes calldata _proof + ) public { if (lastSubmissionTimes[_feedHash] >= _timestamp) { // answer is superseeded -> skip submission return; diff --git a/contracts/v0.2/test/SubmissionProxy.t.sol b/contracts/v0.2/test/SubmissionProxy.t.sol index 88662874b..f20a14788 100644 --- a/contracts/v0.2/test/SubmissionProxy.t.sol +++ b/contracts/v0.2/test/SubmissionProxy.t.sol @@ -433,6 +433,106 @@ contract SubmissionProxyTest is Test { IFeed(feeds_[0]).latestRoundData(); } + function test_SubmitStrict() public { + (address alice_, uint256 aliceSk_) = makeAddrAndKey("alice"); + (address bob_, uint256 bobSk_) = makeAddrAndKey("bob"); + (address celine_, uint256 celineSk_) = makeAddrAndKey("celine"); + (, uint256 dummySk_) = makeAddrAndKey("dummy"); + + submissionProxy.addOracle(alice_); + submissionProxy.addOracle(bob_); + submissionProxy.addOracle(celine_); + + uint256 numOracles_ = 1; + int256 submissionValue_ = 10; + ( + bytes32[] memory feedHashes_, + int256[] memory submissions_, + bytes[] memory proofs_, + uint256[] memory timestamps_, + address[] memory feeds_ + ) = prepareFeedsSubmissions(numOracles_, submissionValue_, dummySk_); + bytes32 hash_ = keccak256(abi.encodePacked(submissions_[0], timestamps_[0], feedHashes_[0])); + proofs_[0] = + abi.encodePacked(createProof(aliceSk_, hash_), createProof(bobSk_, hash_), createProof(celineSk_, hash_)); + + submissionProxy.setProofThreshold(feedHashes_[0], 100); // 100 % of the oracles must submit a valid proof + submissionProxy.submitStrict(feedHashes_, submissions_, timestamps_, proofs_); + + // don't raise `NoDataPresent` + IFeed(feeds_[0]).latestRoundData(); + } + + function test_submitWithoutSupersededValidation() public { + (address alice_, uint256 aliceSk_) = makeAddrAndKey("alice"); + (address bob_, uint256 bobSk_) = makeAddrAndKey("bob"); + (address celine_, uint256 celineSk_) = makeAddrAndKey("celine"); + (, uint256 dummySk_) = makeAddrAndKey("dummy"); + + submissionProxy.addOracle(alice_); + submissionProxy.addOracle(bob_); + submissionProxy.addOracle(celine_); + + uint256 numOracles_ = 1; + int256 submissionValue_ = 10; + ( + bytes32[] memory feedHashes_, + int256[] memory submissions_, + bytes[] memory proofs_, + uint256[] memory timestamps_, + address[] memory feeds_ + ) = prepareFeedsSubmissions(numOracles_, submissionValue_, dummySk_); + bytes32 hash_ = keccak256(abi.encodePacked(submissions_[0], timestamps_[0], feedHashes_[0])); + proofs_[0] = + abi.encodePacked(createProof(aliceSk_, hash_), createProof(bobSk_, hash_), createProof(celineSk_, hash_)); + + submissionProxy.setProofThreshold(feedHashes_[0], 100); // 100 % of the oracles must submit a valid proof + submissionProxy.submitWithoutSupersedValidation(feedHashes_, submissions_, timestamps_, proofs_); + + // don't raise `NoDataPresent` + IFeed(feeds_[0]).latestRoundData(); + } + + function test_submitWithoutSupersededValidationIgnoreLateSubmission() public { + + + (address alice_, uint256 aliceSk_) = makeAddrAndKey("alice"); + (address bob_, uint256 bobSk_) = makeAddrAndKey("bob"); + (address celine_, uint256 celineSk_) = makeAddrAndKey("celine"); + (, uint256 dummySk_) = makeAddrAndKey("dummy"); + + submissionProxy.addOracle(alice_); + submissionProxy.addOracle(bob_); + submissionProxy.addOracle(celine_); + + uint256 numOracles_ = 1; + int256 submissionValue_ = 10; + + ( + bytes32[] memory feedHashes_, + int256[] memory submissions_, + bytes[] memory proofs_, + uint256[] memory timestamps_, + address[] memory feeds_ + ) = prepareFeedsSubmissions(numOracles_, submissionValue_, dummySk_); + bytes32 hash_ = keccak256(abi.encodePacked(submissions_[0], timestamps_[0], feedHashes_[0])); + proofs_[0] = + abi.encodePacked(createProof(aliceSk_, hash_), createProof(bobSk_, hash_), createProof(celineSk_, hash_)); + + submissionProxy.setProofThreshold(feedHashes_[0], 100); // 100 % of the oracles must submit a valid proof + submissionProxy.submitWithoutSupersedValidation(feedHashes_, submissions_, timestamps_, proofs_); + + uint256[] memory oldTimestamps = new uint256[](timestamps_.length); + for (uint256 i = 0; i < timestamps_.length; i++) { + oldTimestamps[i] = timestamps_[i] -1; + } + // should not revert + submissionProxy.submitWithoutSupersedValidation(feedHashes_, submissions_, oldTimestamps, proofs_); + + // don't raise `NoDataPresent` + IFeed(feeds_[0]).latestRoundData(); + } + function prepareFeedsSubmissions(uint256 _numOracles, int256 _submissionValue, uint256 _oracleSk) private returns (bytes32[] memory, int256[] memory, bytes[] memory, uint256[] memory, address[] memory) diff --git a/contracts/v0.2/test/SubmitStrict.t.sol b/contracts/v0.2/test/SubmitStrict.t.sol index 54ad41146..21d189f18 100644 --- a/contracts/v0.2/test/SubmitStrict.t.sol +++ b/contracts/v0.2/test/SubmitStrict.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import "forge-std/Vm.sol"; import {Test, console} from "forge-std/Test.sol"; -import { stdJson } from "forge-std/StdJson.sol"; +import {stdJson} from "forge-std/StdJson.sol"; import {SubmissionProxy} from "../src/SubmissionProxy.sol"; import {FeedRouter} from "../src/FeedRouter.sol"; import "forge-std/console.sol"; @@ -12,73 +12,68 @@ contract SubmitStrictTest is Test { using stdJson for string; function run() public { - string memory json = vm.readFile("submission.json"); + string memory json = vm.readFile("submission.json"); - string[] memory symbols = getsymbols(json); - bytes32[] memory feedHashes = gethashes(json); - int256[] memory valuesInt = getvalues(json); - uint256[] memory timestampsInt = gettimestamps(json); - bytes[] memory proofs = getproofs(json); + string[] memory symbols = getsymbols(json); + bytes32[] memory feedHashes = gethashes(json); + int256[] memory valuesInt = getvalues(json); + uint256[] memory timestampsInt = gettimestamps(json); + bytes[] memory proofs = getproofs(json); - console.log("submission"); - console.logBytes32(feedHashes[0]); - console.logInt(valuesInt[0]); - console.logUint(timestampsInt[0]); - console.logBytes(proofs[0]); + console.log("submission"); + console.logBytes32(feedHashes[0]); + console.logInt(valuesInt[0]); + console.logUint(timestampsInt[0]); + console.logBytes(proofs[0]); - SubmissionProxy sp = SubmissionProxy(0x3a251c738e19806A546815eb6065e139A8D65B4b); - sp.submitStrictBatch( - feedHashes, - valuesInt, - timestampsInt, - proofs - ); + SubmissionProxy sp = SubmissionProxy(0x3a251c738e19806A546815eb6065e139A8D65B4b); + sp.submitStrict(feedHashes, valuesInt, timestampsInt, proofs); - console.log(block.timestamp); + console.log(block.timestamp); - FeedRouter fr = FeedRouter(0x653078F0D3a230416A59aA6486466470Db0190A2); - (uint64 roundId, int256 answer, uint256 blockTimestamp) = fr.latestRoundData(symbols[0]); + FeedRouter fr = FeedRouter(0x653078F0D3a230416A59aA6486466470Db0190A2); + (uint64 roundId, int256 answer, uint256 blockTimestamp) = fr.latestRoundData(symbols[0]); - console.log("latestRoundData"); - console.logUint(roundId); - console.logInt(answer); - console.logUint(blockTimestamp); + console.log("latestRoundData"); + console.logUint(roundId); + console.logInt(answer); + console.logUint(blockTimestamp); - require(block.timestamp == blockTimestamp, "Timestamps do not match"); + require(block.timestamp == blockTimestamp, "Timestamps do not match"); } function getsymbols(string memory json) public pure returns (string[] memory) { - bytes memory rawSymbols = json.parseRaw(".symbols"); - return abi.decode(rawSymbols, (string[])); + bytes memory rawSymbols = json.parseRaw(".symbols"); + return abi.decode(rawSymbols, (string[])); } function gethashes(string memory json) public pure returns (bytes32[] memory) { - bytes memory rawFeedHashes = json.parseRaw(".feedHashes"); + bytes memory rawFeedHashes = json.parseRaw(".feedHashes"); return abi.decode(rawFeedHashes, (bytes32[])); } function getvalues(string memory json) public pure returns (int256[] memory) { - bytes memory rawValues = json.parseRaw(".values"); - string[] memory values = abi.decode(rawValues, (string[])); - int256[] memory valuesInt = new int256[](values.length); - for (uint i = 0; i < values.length; i++) { - valuesInt[i] = vm.parseInt(values[i]); - } - return valuesInt; + bytes memory rawValues = json.parseRaw(".values"); + string[] memory values = abi.decode(rawValues, (string[])); + int256[] memory valuesInt = new int256[](values.length); + for (uint256 i = 0; i < values.length; i++) { + valuesInt[i] = vm.parseInt(values[i]); + } + return valuesInt; } function gettimestamps(string memory json) public pure returns (uint256[] memory) { - bytes memory rawTimestamps = json.parseRaw(".aggregateTimes"); - string[] memory timestamps = abi.decode(rawTimestamps, (string[])); - uint256[] memory timestampsInt = new uint256[](timestamps.length); - for (uint i = 0; i < timestamps.length; i++) { - timestampsInt[i] = vm.parseUint(timestamps[i]); - } - return timestampsInt; + bytes memory rawTimestamps = json.parseRaw(".aggregateTimes"); + string[] memory timestamps = abi.decode(rawTimestamps, (string[])); + uint256[] memory timestampsInt = new uint256[](timestamps.length); + for (uint256 i = 0; i < timestamps.length; i++) { + timestampsInt[i] = vm.parseUint(timestamps[i]); + } + return timestampsInt; } function getproofs(string memory json) public pure returns (bytes[] memory) { - bytes memory rawProofs = json.parseRaw(".proofs"); - return abi.decode(rawProofs, (bytes[])); + bytes memory rawProofs = json.parseRaw(".proofs"); + return abi.decode(rawProofs, (bytes[])); } }