diff --git a/solidity/contracts/Oracle.sol b/solidity/contracts/Oracle.sol index 9283cb9..67f64cd 100644 --- a/solidity/contracts/Oracle.sol +++ b/solidity/contracts/Oracle.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; + import {IOracle} from '../interfaces/IOracle.sol'; import {IAccessModule} from '../interfaces/modules/access/IAccessModule.sol'; @@ -15,6 +17,7 @@ import {OracleTypehash} from './utils/OracleTypehash.sol'; contract Oracle is IOracle, OracleAccessController { using ValidatorLib for *; + using EnumerableSet for EnumerableSet.Bytes32Set; /// @inheritdoc IOracle mapping(bytes32 _requestId => uint256 _finalizedAt) public finalizedAt; @@ -50,24 +53,13 @@ contract Oracle is IOracle, OracleAccessController { uint256 public totalRequestCount; /** - * @notice The list of the response ids for each request + * @notice An enumerable set of the response ids for each request */ - mapping(bytes32 _requestId => bytes _responseIds) internal _responseIds; + mapping(bytes32 _requestId => EnumerableSet.Bytes32Set _responseIds) internal _responseIds; /// @inheritdoc IOracle function getResponseIds(bytes32 _requestId) public view returns (bytes32[] memory _ids) { - bytes memory _responses = _responseIds[_requestId]; - uint256 _length = _responses.length / 32; - - assembly { - for { let _i := 0 } lt(_i, _length) { _i := add(_i, 1) } { - // Increase the size of the array - mstore(_ids, add(mload(_ids), 1)) - - // Store the response id in the array - mstore(add(_ids, add(32, mul(_i, 32))), mload(add(_responses, add(32, mul(_i, 32))))) - } - } + _ids = _responseIds[_requestId].values(); } /// @inheritdoc IOracle @@ -154,7 +146,7 @@ contract Oracle is IOracle, OracleAccessController { } isParticipant[_requestId][_response.proposer] = true; IResponseModule(_request.responseModule).propose(_request, _response, _accessControl.user); - _responseIds[_requestId] = abi.encodePacked(_responseIds[_requestId], _responseId); + _responseIds[_requestId].add(_responseId); responseCreatedAt[_responseId] = block.timestamp; emit ResponseProposed(_requestId, _responseId, _response); diff --git a/solidity/test/unit/Oracle.t.sol b/solidity/test/unit/Oracle.t.sol index 6034398..e6c8fe0 100644 --- a/solidity/test/unit/Oracle.t.sol +++ b/solidity/test/unit/Oracle.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; import 'forge-std/Test.sol'; import {IModule} from '../../interfaces/IModule.sol'; @@ -71,7 +72,7 @@ contract MockOracle is Oracle { } function mock_addResponseId(bytes32 _requestId, bytes32 _responseId) external { - _responseIds[_requestId] = abi.encodePacked(_responseIds[_requestId], _responseId); + EnumerableSet.add(_responseIds[_requestId], _responseId); } function mock_setAccessModuleApproved(address _user, address _accessModule, bool _approved) external {