From 97b844e3dfc76660afd5633164c8f324e3d6a222 Mon Sep 17 00:00:00 2001 From: Ashitaka Date: Tue, 6 Aug 2024 14:22:28 -0300 Subject: [PATCH] feat: request response --- solidity/contracts/Oracle.sol | 7 ++++++- solidity/contracts/Validator.sol | 17 +++++++++++++++++ solidity/lib/ValidatorLib.sol | 18 ++++++++++++++++++ solidity/test/lib/ValidatorLib.t.sol | 15 +++++++++++++++ .../mocks/contracts/MockRequestModule.sol | 16 ---------------- solidity/test/unit/Oracle.t.sol | 9 +++++++++ solidity/test/unit/Validator.t.sol | 19 ++++++++++++++++++- 7 files changed, 83 insertions(+), 18 deletions(-) diff --git a/solidity/contracts/Oracle.sol b/solidity/contracts/Oracle.sol index 2643b14..704a397 100644 --- a/solidity/contracts/Oracle.sol +++ b/solidity/contracts/Oracle.sol @@ -105,7 +105,12 @@ contract Oracle is IOracle { Request calldata _request, Response calldata _response ) external returns (bytes32 _responseId) { - _responseId = ValidatorLib._validateResponse(_request, _response); + bytes32 _requestId; + (_requestId, _responseId) = ValidatorLib._validateRequestAndResponse(_request, _response); + + if (requestCreatedAt[_requestId] == 0) { + revert Oracle_InvalidRequestBody(); + } // The caller must be the proposer, unless the response is coming from a dispute module if (msg.sender != _response.proposer && msg.sender != address(_request.disputeModule)) { diff --git a/solidity/contracts/Validator.sol b/solidity/contracts/Validator.sol index 00b0d55..fde475f 100644 --- a/solidity/contracts/Validator.sol +++ b/solidity/contracts/Validator.sol @@ -43,6 +43,23 @@ abstract contract Validator is IValidator { _id = ValidatorLib._getId(_dispute); } + /** + * @notice Validates the correctness and existance of a request-response pair + * + * @param _request The request to compute the id for + * @param _response The response to compute the id for + * @return _requestId The id the request + * @return _responseId The id the response + */ + function _validateRequestAndResponse( + IOracle.Request calldata _request, + IOracle.Response calldata _response + ) internal view returns (bytes32 _requestId, bytes32 _responseId) { + (_requestId, _responseId) = ValidatorLib._validateRequestAndResponse(_request, _response); + + if (ORACLE.responseCreatedAt(_responseId) == 0) revert Validator_InvalidResponse(); + } + /** * @notice Validates the correctness and existance of a request-response pair * diff --git a/solidity/lib/ValidatorLib.sol b/solidity/lib/ValidatorLib.sol index 8c694ca..c194247 100644 --- a/solidity/lib/ValidatorLib.sol +++ b/solidity/lib/ValidatorLib.sol @@ -44,6 +44,24 @@ library ValidatorLib { _id = keccak256(abi.encode(_dispute)); } + /** + * @notice Validates the correctness and existance of a request-response pair + * + * @param _request The request to compute the id for + * @param _response The response to compute the id for + * @return _requestId The id the request + * @return _responseId The id the response + */ + function _validateRequestAndResponse( + IOracle.Request calldata _request, + IOracle.Response calldata _response + ) public pure returns (bytes32 _requestId, bytes32 _responseId) { + _requestId = _getId(_request); + _responseId = _getId(_response); + + if (_response.requestId != _requestId) revert ValidatorLib_InvalidResponseBody(); + } + /** * @notice Validates the correctness and existance of a request-response pair * diff --git a/solidity/test/lib/ValidatorLib.t.sol b/solidity/test/lib/ValidatorLib.t.sol index b40f246..02b65aa 100644 --- a/solidity/test/lib/ValidatorLib.t.sol +++ b/solidity/test/lib/ValidatorLib.t.sol @@ -68,6 +68,21 @@ contract ValidatorLibGetIds is BaseTest { } } +contract ValidatorLibValidateRequestAndResponse is BaseTest { + function test_validateRequestAndResponse() public { + (bytes32 _requestId, bytes32 _responseId) = ValidatorLib._validateRequestAndResponse(mockRequest, mockResponse); + assertEq(_requestId, keccak256(abi.encode(mockRequest))); + assertEq(_responseId, keccak256(abi.encode(mockResponse))); + } + + function test_validateRequestAndResponse_InvalidResponseBody() public { + IOracle.Response memory _response = mockResponse; + _response.requestId = bytes32('invalid'); + vm.expectRevert(ValidatorLib.ValidatorLib_InvalidResponseBody.selector); + ValidatorLib._validateRequestAndResponse(mockRequest, _response); + } +} + contract ValidatorLibValidateResponse is BaseTest { function test_validateResponse() public { bytes32 _responseId = ValidatorLib._validateResponse(mockRequest, mockResponse); diff --git a/solidity/test/mocks/contracts/MockRequestModule.sol b/solidity/test/mocks/contracts/MockRequestModule.sol index 627bf94..8b13789 100644 --- a/solidity/test/mocks/contracts/MockRequestModule.sol +++ b/solidity/test/mocks/contracts/MockRequestModule.sol @@ -1,17 +1 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; -import {Module} from '../../../contracts/Module.sol'; -import {IOracle} from '../../../interfaces/IOracle.sol'; -import {IMockRequestModule} from '../interfaces/IMockRequestModule.sol'; - -contract MockRequestModule is Module, IMockRequestModule { - constructor(IOracle _oracle) Module(_oracle) {} - - function decodeRequestData(bytes calldata _data) public pure returns (RequestParameters memory _requestData) { - _requestData = abi.decode(_data, (RequestParameters)); - } - - function createRequest(bytes32 _requestId, bytes calldata _data, address _requester) external onlyOracle {} - function moduleName() external view returns (string memory _moduleName) {} -} diff --git a/solidity/test/unit/Oracle.t.sol b/solidity/test/unit/Oracle.t.sol index 4ff711b..429cb44 100644 --- a/solidity/test/unit/Oracle.t.sol +++ b/solidity/test/unit/Oracle.t.sol @@ -459,6 +459,15 @@ contract Oracle_Unit_ProposeResponse is BaseTest { assertEq(_responseIds[1], _secondResponseId); } + function test_proposeResponse_revertsIfInvalidRequest() public { + // Check: revert? + vm.expectRevert(IOracle.Oracle_InvalidRequestBody.selector); + + // Test: try to propose a response with an invalid request + vm.prank(proposer); + oracle.proposeResponse(mockRequest, mockResponse); + } + /** * @notice Revert if the caller is not the proposer nor the dispute module */ diff --git a/solidity/test/unit/Validator.t.sol b/solidity/test/unit/Validator.t.sol index 30a5c64..5a2d963 100644 --- a/solidity/test/unit/Validator.t.sol +++ b/solidity/test/unit/Validator.t.sol @@ -22,6 +22,13 @@ import {Helpers} from '../utils/Helpers.sol'; contract MockValidator is Validator { constructor(IOracle _oracle) Validator(_oracle) {} + function validateRequestAndResponse( + IOracle.Request calldata _request, + IOracle.Response calldata _response + ) external view returns (bytes32 _requestId, bytes32 _responseId) { + return _validateRequestAndResponse(_request, _response); + } + function validateResponse( IOracle.Request calldata _request, IOracle.Response calldata _response @@ -84,8 +91,18 @@ contract BaseTest is Test, Helpers { } } +contract ValidatorValidateRequestAndResponse is BaseTest { + function test_validateRequestAndResponse_InvalidResponse() public { + vm.mockCall( + address(oracle), abi.encodeWithSelector(IOracle.responseCreatedAt.selector, _getId(mockResponse)), abi.encode(0) + ); + vm.expectRevert(IValidator.Validator_InvalidResponse.selector); + validator.validateRequestAndResponse(mockRequest, mockResponse); + } +} + contract ValidatorValidateResponse is BaseTest { - function test__validateResponse_InvalidResponse() public { + function test_validateResponse_InvalidResponse() public { vm.mockCall( address(oracle), abi.encodeWithSelector(IOracle.responseCreatedAt.selector, _getId(mockResponse)), abi.encode(0) );