Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: checks createAt #37

Merged
merged 11 commits into from
Aug 6, 2024
7 changes: 6 additions & 1 deletion solidity/contracts/Oracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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();
0xJabberwock marked this conversation as resolved.
Show resolved Hide resolved
}

// 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)) {
Expand Down
17 changes: 17 additions & 0 deletions solidity/contracts/Validator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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(
0xJabberwock marked this conversation as resolved.
Show resolved Hide resolved
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
*
Expand Down
18 changes: 18 additions & 0 deletions solidity/lib/ValidatorLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
15 changes: 15 additions & 0 deletions solidity/test/lib/ValidatorLib.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 0 additions & 16 deletions solidity/test/mocks/contracts/MockRequestModule.sol
0xJabberwock marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -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) {}
}
9 changes: 9 additions & 0 deletions solidity/test/unit/Oracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
19 changes: 18 additions & 1 deletion solidity/test/unit/Validator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
);
Expand Down
Loading