diff --git a/contracts/package.json b/contracts/package.json index cb0229eb4..2320a988b 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -32,7 +32,7 @@ "prettier-solidity-check": "yarn --cwd='../' contracts-v01 prettier-solidity-check", "solhint": "yarn --cwd='../' contracts-v01 solhint", "lint": "yarn --cwd='../' contracts-v01 lint && yarn --cwd='../' contracts-v02 lint", - "test-non-vrf": "yarn --cwd='../' contracts-v01 test-non-vrf" + "test-non-vrf": "yarn --cwd='../' contracts-v01 test-non-vrf && yarn --cwd='../' contracts-v02 test" }, "engines": { "node": ">=20.0.0" diff --git a/contracts/v0.2/src/SubmissionProxy.sol b/contracts/v0.2/src/SubmissionProxy.sol index 9dd74aa79..3cf56b674 100644 --- a/contracts/v0.2/src/SubmissionProxy.sol +++ b/contracts/v0.2/src/SubmissionProxy.sol @@ -37,7 +37,7 @@ contract SubmissionProxy is Ownable { mapping(address => OracleInfo) public whitelist; mapping(bytes32 feedHash => uint8 threshold) thresholds; mapping(bytes32 feedHash => IFeed feedAddress) feeds; - IFeed[] public feedAddresses; + address[] public feedAddresses; event OracleAdded(address oracle, uint256 expirationTime); event OracleRemoved(address oracle); @@ -47,7 +47,7 @@ contract SubmissionProxy is Ownable { event ThresholdSet(bytes32 feedHash, uint8 threshold); event DataFreshnessSet(uint256 dataFreshness); event FeedAddressUpdated(bytes32 feedHash, address indexed feed); - event FeedAddressBulkUpdated(bytes32[] feedHashs, address[] feeds); + event FeedAddressBulkUpdated(bytes32[] feedHashes, address[] feeds); event FeedAddressRemoved(bytes32 feedHash, address feed); error OnlyOracle(); @@ -79,11 +79,7 @@ contract SubmissionProxy is Ownable { * @return The list of feed addresses */ function getFeeds() external view returns (address[] memory) { - address[] memory feedAddressesArray = new address[](feedAddresses.length); - for (uint256 i = 0; i < feedAddresses.length; i++) { - feedAddressesArray[i] = address(feedAddresses[i]); - } - return feedAddressesArray; + return feedAddresses; } /** @@ -97,8 +93,10 @@ contract SubmissionProxy is Ownable { } delete feeds[_feedHash]; - for (uint256 i = 0; i < feedAddresses.length; i++) { - if (address(feedAddresses[i]) == address(feed)) { + + uint256 feedAddressesLength = feedAddresses.length; + for (uint256 i = 0; i < feedAddressesLength; i++) { + if (feedAddresses[i] == address(feed)) { feedAddresses[i] = feedAddresses[feedAddresses.length - 1]; feedAddresses.pop(); break; @@ -114,12 +112,19 @@ contract SubmissionProxy is Ownable { * @param _feed The address of the feed */ function updateFeed(bytes32 _feedHash, address _feed) public onlyOwner { - IFeed feed = IFeed(_feed); if (address(feeds[_feedHash]) == address(0)) { - feedAddresses.push(feed); + feedAddresses.push(_feed); + } else { + uint256 feedAddressesLength = feedAddresses.length; + for (uint256 i = 0; i < feedAddressesLength; i++) { + if (feedAddresses[i] == address(feeds[_feedHash])) { + feedAddresses[i] = _feed; + break; + } + } } - feeds[_feedHash] = feed; + feeds[_feedHash] = IFeed(_feed); emit FeedAddressUpdated(_feedHash, _feed); } @@ -227,7 +232,9 @@ contract SubmissionProxy is Ownable { for (uint8 i = 0; i < oraclesLength_; i++) { if (!isWhitelisted(oracles[i])) { // reuse existing oracle slot if it is expired + whitelist[oracles[i]].index = 0; oracles[i] = _oracle; + found = true; index_ = i; break; @@ -357,7 +364,7 @@ contract SubmissionProxy is Ownable { continue; } - if (keccak256(abi.encode(feeds[_feedHashes[i]].description())) != _feedHashes[i]) { + if (keccak256(abi.encodePacked(feeds[_feedHashes[i]].description())) != _feedHashes[i]) { // feedHash not matching with registered feed -> do not submit! continue; } @@ -440,6 +447,10 @@ contract SubmissionProxy is Ownable { */ function recoverSigner(bytes32 message, bytes memory sig) private pure returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); + if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { + // return address(0) if s is larger than half of the order, to skip signature malleability + return address(0); + } return ecrecover(message, v, r, s); } @@ -483,12 +494,12 @@ contract SubmissionProxy is Ownable { * @dev The order of the proofs must be in ascending order of the * oracle index. The function will revert with `IndexesNotAscending` * error if the order is not ascending. - * @param _feed The address of the feed + * @param _feedHash The hash of the feed * @param _message The hash of the message * @param _proofs The proofs * @return `true` if the proof is valid, `false` otherwise */ - function validateProof(bytes32 _feed, bytes32 _message, bytes[] memory _proofs) private view returns (bool) { + function validateProof(bytes32 _feedHash, bytes32 _message, bytes[] memory _proofs) private view returns (bool) { if (oracles.length == 0) { return false; } @@ -496,7 +507,7 @@ contract SubmissionProxy is Ownable { uint8 verifiedSignatures_ = 0; uint8 lastIndex_ = 0; - uint8 threshold_ = thresholds[_feed]; + uint8 threshold_ = thresholds[_feedHash]; if (threshold_ == 0) { threshold_ = defaultThreshold; } diff --git a/contracts/v0.2/test/SubmissionProxy.t.sol b/contracts/v0.2/test/SubmissionProxy.t.sol index ffd554b2e..29e97c0bb 100644 --- a/contracts/v0.2/test/SubmissionProxy.t.sol +++ b/contracts/v0.2/test/SubmissionProxy.t.sol @@ -331,7 +331,7 @@ contract SubmissionProxyTest is Test { 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])); @@ -386,14 +386,14 @@ contract SubmissionProxyTest is Test { ) = createSubmitParameters(_numOracles); address[] memory feeds_ = new address[](_numOracles); for (uint256 i = 0; i < _numOracles; i++) { - Feed feed_ = new Feed(DECIMALS, DESCRIPTION, address(submissionProxy)); + Feed feed_ = new Feed(DECIMALS, SAMPLE_NAMES[i], address(submissionProxy)); feeds_[i] = address(feed_); feedHashes_[i] = keccak256(abi.encodePacked(SAMPLE_NAMES[i])); submissions_[i] = _submissionValue; timestamps_[i] = block.timestamp; proofs_[i] = createProof(_oracleSk, keccak256(abi.encodePacked(timestamps_[i], submissions_[i], feedHashes_[i]))); - submissionProxy.updateFeed(feedHashes_[i], address(feed_)); + submissionProxy.updateFeed(feedHashes_[i], address(feeds_[i])); } return (feedHashes_, submissions_, proofs_, timestamps_, feeds_);