Skip to content

Commit

Permalink
feat: checks response and dispute
Browse files Browse the repository at this point in the history
  • Loading branch information
ashitakah committed Jul 31, 2024
1 parent c6f5150 commit 8f6a21e
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 5 deletions.
31 changes: 30 additions & 1 deletion solidity/contracts/Oracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ contract Oracle is IOracle {
Request calldata _request,
Response calldata _response
) external returns (bytes32 _responseId) {
_responseId = _validateResponse(_request, _response);
_responseId = _validateProposeResponse(_request, _response);

// 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 Expand Up @@ -435,6 +435,26 @@ contract Oracle is IOracle {
}

_responseId = keccak256(abi.encode(_response));

if (responseCreatedAt[_responseId] == 0) {
revert Oracle_InvalidResponseBody();
}

if (_response.requestId != _requestId) revert Oracle_InvalidResponseBody();
}

function _validateProposeResponse(
Request calldata _request,
Response calldata _response
) internal view returns (bytes32 _responseId) {
bytes32 _requestId = keccak256(abi.encode(_request));

if (requestCreatedAt[_requestId] == 0) {
revert Oracle_InvalidRequestBody();
}

_responseId = keccak256(abi.encode(_response));

if (_response.requestId != _requestId) revert Oracle_InvalidResponseBody();
}

Expand All @@ -458,8 +478,17 @@ contract Oracle is IOracle {
}

bytes32 _responseId = keccak256(abi.encode(_response));

if (responseCreatedAt[_responseId] == 0) {
revert Oracle_InvalidResponseBody();
}

_disputeId = keccak256(abi.encode(_dispute));

if (disputeCreatedAt[_disputeId] == 0) {
revert Oracle_InvalidDisputeBody();
}

if (_dispute.requestId != _requestId || _dispute.responseId != _responseId) revert Oracle_InvalidDisputeBody();
if (_response.requestId != _requestId) revert Oracle_InvalidResponseBody();
}
Expand Down
156 changes: 152 additions & 4 deletions solidity/test/unit/Oracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ contract MockOracle is Oracle {
requestCreatedAt[_requestId] = _requestCreatedAt;
}

function mock_setResponseCreatedAt(bytes32 _responseId, uint128 _responseCreatedAt) external {
responseCreatedAt[_responseId] = _responseCreatedAt;
}

function mock_setDisputeCreatedAt(bytes32 _disputeId, uint128 _disputeCreatedAt) external {
disputeCreatedAt[_disputeId] = _disputeCreatedAt;
}

function mock_setTotalRequestCount(uint256 _totalRequestCount) external {
totalRequestCount = _totalRequestCount;
}
Expand Down Expand Up @@ -467,6 +475,7 @@ contract Oracle_Unit_ProposeResponse is BaseTest {
vm.assume(_caller != proposer && _caller != address(disputeModule));

oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));

// Check: revert?
vm.expectRevert(IOracle.Oracle_InvalidResponseBody.selector);
Expand Down Expand Up @@ -524,6 +533,8 @@ contract Oracle_Unit_DisputeResponse is BaseTest {
_disputeId = _getId(mockDispute);

oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));
}

/**
Expand Down Expand Up @@ -568,6 +579,21 @@ contract Oracle_Unit_DisputeResponse is BaseTest {
oracle.disputeResponse(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Revert if the response doesn't exist
*/
function test_disputeResponse_revertsIfInvalidResponse() public {
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, 0);

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidResponseBody.selector));

// Test: try to dispute the response
vm.prank(disputer);
oracle.disputeResponse(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Reverts if the dispute proposer and response proposer are not same
*/
Expand Down Expand Up @@ -635,6 +661,8 @@ contract Oracle_Unit_UpdateDisputeStatus is BaseTest {
function test_updateDisputeStatus() public {
bytes32 _requestId = _getId(mockRequest);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_getId(mockDispute), uint128(block.number));

// Try every initial status
for (uint256 _previousStatus; _previousStatus < uint256(type(IOracle.DisputeStatus).max); _previousStatus++) {
Expand Down Expand Up @@ -680,6 +708,22 @@ contract Oracle_Unit_UpdateDisputeStatus is BaseTest {
oracle.updateDisputeStatus(mockRequest, mockResponse, mockDispute, IOracle.DisputeStatus(0));
}

/**
* @notice Revert if the response doesn't exist
*/
function test_updateDisputeStatus_revertsIfInvalidResponse() public {
bytes32 _requestId = _getId(mockRequest);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), 0);

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidResponseBody.selector));

// Test: change the status
vm.prank(address(resolutionModule));
oracle.updateDisputeStatus(mockRequest, mockResponse, mockDispute, IOracle.DisputeStatus(0));
}

/**
* @notice Providing a dispute that does not match the response should revert
*/
Expand All @@ -692,6 +736,8 @@ contract Oracle_Unit_UpdateDisputeStatus is BaseTest {
// Setting a random dispute id, not matching the mockDispute
oracle.mock_setDisputeOf(_getId(mockResponse), _randomId);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidDisputeId.selector, _disputeId));
Expand All @@ -708,9 +754,14 @@ contract Oracle_Unit_UpdateDisputeStatus is BaseTest {
// 0 to 3 status, fuzzed
_newStatus = bound(_newStatus, 0, 3);

bytes32 _disputeId = _getId(mockDispute);
bytes32 _responseId = _getId(mockResponse);

// Mock the dispute
oracle.mock_setDisputeOf(_getId(mockResponse), _getId(mockDispute));
oracle.mock_setDisputeOf(_responseId, _disputeId);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_NotDisputeOrResolutionModule.selector, proposer));
Expand All @@ -729,6 +780,9 @@ contract Oracle_Unit_ResolveDispute is BaseTest {
// Mock the dispute
bytes32 _disputeId = _getId(mockDispute);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));

oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);
oracle.mock_setDisputeStatus(_disputeId, IOracle.DisputeStatus.Active);

Expand All @@ -750,8 +804,11 @@ contract Oracle_Unit_ResolveDispute is BaseTest {
/**
* @notice Test the revert when the function is called with an non-existent dispute id
*/
function test_resolveDispute_revertsIfInvalidDispute() public {
function test_resolveDispute_revertsIfInvalidDisputeId() public {
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_getId(mockDispute), uint128(block.number));

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidDisputeId.selector, _getId(mockDispute)));

Expand All @@ -770,6 +827,37 @@ contract Oracle_Unit_ResolveDispute is BaseTest {
oracle.resolveDispute(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Revert if the response doesn't exist
*/
function test_resolveDispute_revertsIfInvalidResponse() public {
bytes32 _requestId = _getId(mockRequest);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), 0);

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidResponseBody.selector));

// Test: try to resolve the dispute
oracle.resolveDispute(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Revert if the dispute doesn't exist
*/
function test_resolveDispute_revertsIfInvalidDispute() public {
bytes32 _requestId = _getId(mockRequest);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_getId(mockDispute), 0);

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidDisputeBody.selector));

// Test: try to resolve the dispute
oracle.resolveDispute(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Test the revert when the function is called with a dispute in unresolvable status
*/
Expand All @@ -781,9 +869,13 @@ contract Oracle_Unit_ResolveDispute is BaseTest {
continue;
}

bytes32 _responseId = _getId(mockResponse);

// Mock the dispute
oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);
oracle.mock_setDisputeOf(_responseId, _disputeId);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));
oracle.mock_setDisputeStatus(_disputeId, IOracle.DisputeStatus(_status));

// Check: revert?
Expand Down Expand Up @@ -813,6 +905,8 @@ contract Oracle_Unit_ResolveDispute is BaseTest {
oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);
oracle.mock_setDisputeStatus(_disputeId, IOracle.DisputeStatus.Escalated);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));

// Check: revert?
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_NoResolutionModule.selector, _disputeId));
Expand Down Expand Up @@ -895,6 +989,7 @@ contract Oracle_Unit_Finalize is BaseTest {

oracle.mock_addResponseId(_requestId, _responseId);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));

// Mock the finalize call on all modules
bytes memory _calldata = abi.encodeCall(IModule.finalizeRequest, (mockRequest, mockResponse, _caller));
Expand Down Expand Up @@ -930,16 +1025,34 @@ contract Oracle_Unit_Finalize is BaseTest {
oracle.finalize(mockRequest, mockResponse);
}

/**
* @notice Revert if the response doesn't exist
*/
function test_finalize_revertsIfInvalidResponse() public {
bytes32 _requestId = _getId(mockRequest);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), 0);

// Check: revert?
vm.expectRevert(IOracle.Oracle_InvalidResponseBody.selector);

// Test: finalize the request
vm.prank(requester);
oracle.finalize(mockRequest, mockResponse);
}

/**
* @notice Finalizing an already finalized request
*/
function test_finalize_withResponse_revertsWhenAlreadyFinalized() public {
bytes32 _requestId = _getId(mockRequest);
bytes32 _responseId = _getId(mockResponse);

// Test: finalize a finalized request
oracle.mock_setFinalizedAt(_requestId, uint128(block.number));
oracle.mock_addResponseId(_requestId, _getId(mockResponse));
oracle.mock_addResponseId(_requestId, _responseId);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));

vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_AlreadyFinalized.selector, _requestId));
vm.prank(requester);
Expand All @@ -958,6 +1071,7 @@ contract Oracle_Unit_Finalize is BaseTest {
// Store the response
oracle.mock_addResponseId(_requestId, _responseId);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_requestId, uint128(block.number));

// Test: finalize the request
vm.expectRevert(IOracle.Oracle_InvalidResponseBody.selector);
Expand All @@ -970,6 +1084,7 @@ contract Oracle_Unit_Finalize is BaseTest {
*/
function test_finalize_withResponse_revertsIfInvalidResponse() public {
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));

// Test: finalize the request
vm.expectRevert(IOracle.Oracle_InvalidFinalizedResponse.selector);
Expand All @@ -992,6 +1107,7 @@ contract Oracle_Unit_Finalize is BaseTest {
// Submit a response to the request
oracle.mock_addResponseId(_requestId, _responseId);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));
oracle.mock_setDisputeOf(_responseId, _disputeId);
oracle.mock_setDisputeStatus(_disputeId, IOracle.DisputeStatus.Won);

Expand Down Expand Up @@ -1133,6 +1249,8 @@ contract Oracle_Unit_EscalateDispute is BaseTest {
oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);
oracle.mock_setDisputeStatus(_disputeId, IOracle.DisputeStatus.Active);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));

// Mock and expect the dispute module call
_mockAndExpect(
Expand Down Expand Up @@ -1177,6 +1295,8 @@ contract Oracle_Unit_EscalateDispute is BaseTest {
oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);
oracle.mock_setDisputeStatus(_disputeId, IOracle.DisputeStatus.Active);
oracle.mock_setRequestCreatedAt(_requestId, uint128(block.number));
oracle.mock_setResponseCreatedAt(_responseId, uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));

// Mock and expect the dispute module call
_mockAndExpect(
Expand Down Expand Up @@ -1206,12 +1326,38 @@ contract Oracle_Unit_EscalateDispute is BaseTest {
oracle.escalateDispute(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Revert if the response doesn't exist
*/
function test_escalateDispute_revertsIfInvalidResponse() public {
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), 0);
vm.expectRevert(IOracle.Oracle_InvalidResponseBody.selector);

oracle.escalateDispute(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Revert if the dispute doesn't exist
*/
function test_escalateDispute_revertsIfInvalidDispute() public {
bytes32 _disputeId = _getId(mockDispute);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, 0);
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidDisputeBody.selector));

oracle.escalateDispute(mockRequest, mockResponse, mockDispute);
}

/**
* @notice Revert if the provided dispute does not match the request or the response
*/
function test_escalateDispute_revertsIfDisputeNotValid() public {
bytes32 _disputeId = _getId(mockDispute);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));
vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_InvalidDisputeId.selector, _disputeId));

// Test: escalate the dispute
Expand All @@ -1221,6 +1367,8 @@ contract Oracle_Unit_EscalateDispute is BaseTest {
function test_escalateDispute_revertsIfDisputeNotActive() public {
bytes32 _disputeId = _getId(mockDispute);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), uint128(block.number));
oracle.mock_setResponseCreatedAt(_getId(mockResponse), uint128(block.number));
oracle.mock_setDisputeCreatedAt(_disputeId, uint128(block.number));
oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);

vm.expectRevert(abi.encodeWithSelector(IOracle.Oracle_CannotEscalate.selector, _disputeId));
Expand Down

0 comments on commit 8f6a21e

Please sign in to comment.