Skip to content

Commit

Permalink
fix: restrict duplicate calls to resolveDispute
Browse files Browse the repository at this point in the history
  • Loading branch information
xorsal committed Dec 10, 2024
1 parent 3e1078a commit df5b7b9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
8 changes: 8 additions & 0 deletions solidity/contracts/Oracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ contract Oracle is IOracle, OracleAccessController {
/// @inheritdoc IOracle
mapping(bytes32 _disputeId => DisputeStatus _status) public disputeStatus;

/// @inheritdoc IOracle
mapping(bytes32 _disputeId => bool _resolved) public disputeResolved;

/// @inheritdoc IOracle
mapping(uint256 _requestNumber => bytes32 _id) public nonceToRequestId;

Expand Down Expand Up @@ -278,6 +281,10 @@ contract Oracle is IOracle, OracleAccessController {
revert Oracle_InvalidDisputeId(_disputeId);
}

if (disputeResolved[_disputeId]) {
revert Oracle_DisputeAlreadyResolved();
}

// Revert if the dispute is not active nor escalated
DisputeStatus _currentStatus = disputeStatus[_disputeId];
if (_currentStatus != DisputeStatus.Active && _currentStatus != DisputeStatus.Escalated) {
Expand All @@ -288,6 +295,7 @@ contract Oracle is IOracle, OracleAccessController {
revert Oracle_NoResolutionModule(_disputeId);
}

disputeResolved[_disputeId] = true;
IResolutionModule(_request.resolutionModule).resolveDispute(_disputeId, _request, _response, _dispute);

emit DisputeResolved(_disputeId, _dispute);
Expand Down
13 changes: 13 additions & 0 deletions solidity/interfaces/IOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ interface IOracle is IOracleAccessController {
*/
error Oracle_InvalidDisputer();

/**
* @notice Thrown when the dispute is already resolved
*/
error Oracle_DisputeAlreadyResolved();

/*///////////////////////////////////////////////////////////////
ENUMS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -299,6 +304,14 @@ interface IOracle is IOracleAccessController {
*/
function disputeStatus(bytes32 _disputeId) external view returns (DisputeStatus _status);

/**
* @notice Returns whether the dispute has been resolved
*
* @param _disputeId The id of the dispute
* @return _resolved True if the dispute has been resolved, false otherwise
*/
function disputeResolved(bytes32 _disputeId) external view returns (bool _resolved);

/**
* @notice The id of each request in chronological order
*
Expand Down
21 changes: 21 additions & 0 deletions solidity/test/unit/Oracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ contract MockOracle is Oracle {
disputeStatus[_disputeId] = _status;
}

function mock_setDisputeResolved(bytes32 _disputeId, bool _resolved) external {
disputeResolved[_disputeId] = _resolved;
}

function mock_setRequestId(uint256 _nonce, bytes32 _requestId) external {
nonceToRequestId[_nonce] = _requestId;
}
Expand Down Expand Up @@ -877,6 +881,23 @@ contract Oracle_Unit_ResolveDispute is BaseTest {
oracle.resolveDispute(mockRequest, mockResponse, mockDispute, mockAccessControl);
}

function test_resolveDispute_revertsWhenAlreadyResolved() public happyPath {
// Mock the dispute
bytes32 _disputeId = _getId(mockDispute);
oracle.mock_setRequestCreatedAt(_getId(mockRequest), block.timestamp);
oracle.mock_setResponseCreatedAt(_getId(mockResponse), block.timestamp);
oracle.mock_setDisputeCreatedAt(_disputeId, block.timestamp);

oracle.mock_setDisputeOf(_getId(mockResponse), _disputeId);
oracle.mock_setDisputeResolved(_disputeId, true);

// Check: reverts?
vm.expectRevert(IOracle.Oracle_DisputeAlreadyResolved.selector);

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

/**
* @notice Test the revert when the function is called with an non-existent dispute id
*/
Expand Down

0 comments on commit df5b7b9

Please sign in to comment.