Skip to content

Commit

Permalink
feat: added events to oracle and unit tests (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmoebius authored Aug 9, 2023
1 parent b461ebb commit 3fe3d5a
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 11 deletions.
50 changes: 41 additions & 9 deletions solidity/contracts/Oracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ contract Oracle is IOracle {
bytes calldata _responseData
) external returns (bytes32 _responseId) {
Request memory _request = _requests[_requestId];
if (msg.sender != address(_request.disputeModule)) revert Oracle_NotDisputeModule(msg.sender);
if (msg.sender != address(_request.disputeModule)) {
revert Oracle_NotDisputeModule(msg.sender);
}
_responseId = _proposeResponse(_proposer, _requestId, _request, _responseData);
}

Expand All @@ -113,29 +115,41 @@ contract Oracle is IOracle {
_responseId = keccak256(abi.encodePacked(_proposer, address(this), _requestId, _responseNonce++));
_responses[_responseId] = _request.responseModule.propose(_requestId, _proposer, _responseData);
_responseIds[_requestId].push(_responseId);

emit Oracle_ResponseProposed(_proposer, _requestId, _responseId);
}

function disputeResponse(bytes32 _requestId, bytes32 _responseId) external returns (bytes32 _disputeId) {
if (disputeOf[_responseId] != bytes32(0)) revert Oracle_ResponseAlreadyDisputed(_responseId);
if (disputeOf[_responseId] != bytes32(0)) {
revert Oracle_ResponseAlreadyDisputed(_responseId);
}
Request memory _request = _requests[_requestId];
Response memory _response = _responses[_responseId];

if (_response.requestId != _requestId || _response.createdAt == 0) revert Oracle_InvalidResponseId(_responseId);
if (_response.requestId != _requestId || _response.createdAt == 0) {
revert Oracle_InvalidResponseId(_responseId);
}

if (_finalizedResponses[_requestId].createdAt != 0) revert Oracle_AlreadyFinalized(_responseId);
if (_finalizedResponses[_requestId].createdAt != 0) {
revert Oracle_AlreadyFinalized(_responseId);
}
// Collision avoided -> this user disputes the _responseId from the _requestId
// -> if trying to redispute, disputeOf isn't empty anymore
_disputeId = keccak256(abi.encodePacked(msg.sender, _requestId, _responseId));
_disputes[_disputeId] =
_request.disputeModule.disputeResponse(_requestId, _responseId, msg.sender, _responses[_responseId].proposer);
disputeOf[_responseId] = _disputeId;

emit Oracle_ResponseDisputed(msg.sender, _responseId, _disputeId);
}

function escalateDispute(bytes32 _disputeId) external {
Dispute memory _dispute = _disputes[_disputeId];

if (_dispute.createdAt == 0) revert Oracle_InvalidDisputeId(_disputeId);
if (_dispute.status != DisputeStatus.Active) revert Oracle_CannotEscalate(_disputeId);
if (_dispute.status != DisputeStatus.Active) {
revert Oracle_CannotEscalate(_disputeId);
}

// Change the dispute status
_dispute.status = DisputeStatus.Escalated;
Expand All @@ -150,6 +164,8 @@ contract Oracle is IOracle {
// Initiate the resolution
_request.resolutionModule.startResolution(_disputeId);
}

emit Oracle_DisputeEscalated(msg.sender, _disputeId);
}

function resolveDispute(bytes32 _disputeId) external {
Expand All @@ -158,21 +174,31 @@ contract Oracle is IOracle {
if (_dispute.createdAt == 0) revert Oracle_InvalidDisputeId(_disputeId);
// Revert if the dispute is not active nor escalated
unchecked {
if (uint256(_dispute.status) - 1 > 1) revert Oracle_CannotResolve(_disputeId);
if (uint256(_dispute.status) - 1 > 1) {
revert Oracle_CannotResolve(_disputeId);
}
}

Request memory _request = _requests[_dispute.requestId];
if (address(_request.resolutionModule) == address(0)) revert Oracle_NoResolutionModule(_disputeId);
if (address(_request.resolutionModule) == address(0)) {
revert Oracle_NoResolutionModule(_disputeId);
}

_request.resolutionModule.resolveDispute(_disputeId);

emit Oracle_DisputeResolved(msg.sender, _disputeId);
}

function updateDisputeStatus(bytes32 _disputeId, DisputeStatus _status) external {
Dispute storage _dispute = _disputes[_disputeId];
Request memory _request = _requests[_dispute.requestId];
if (msg.sender != address(_request.resolutionModule)) revert Oracle_NotResolutionModule(msg.sender);
if (msg.sender != address(_request.resolutionModule)) {
revert Oracle_NotResolutionModule(msg.sender);
}
_dispute.status = _status;
_request.disputeModule.updateDisputeStatus(_disputeId, _dispute);

emit Oracle_DisputeStatusUpdated(_disputeId, _status);
}

function validModule(bytes32 _requestId, address _module) external view returns (bool _validModule) {
Expand All @@ -191,7 +217,9 @@ contract Oracle is IOracle {
}

function finalize(bytes32 _requestId, bytes32 _finalizedResponseId) external {
if (_finalizedResponses[_requestId].createdAt != 0) revert Oracle_AlreadyFinalized(_requestId);
if (_finalizedResponses[_requestId].createdAt != 0) {
revert Oracle_AlreadyFinalized(_requestId);
}

Request memory _request = _requests[_requestId];
Response storage _response = _responses[_finalizedResponseId];
Expand All @@ -218,6 +246,8 @@ contract Oracle is IOracle {
_request.disputeModule.finalizeRequest(_requestId);
_request.responseModule.finalizeRequest(_requestId);
_request.requestModule.finalizeRequest(_requestId);

emit Oracle_RequestFinalized(msg.sender, _requestId);
}

function _createRequest(NewRequest memory _request) internal returns (bytes32 _requestId) {
Expand Down Expand Up @@ -250,6 +280,8 @@ contract Oracle is IOracle {
if (address(_request.finalityModule) != address(0)) {
_request.finalityModule.setupRequest(_requestId, _request.finalityModuleData);
}

emit Oracle_RequestCreated(msg.sender, _requestId);
}

function _getRequest(bytes32 _requestId) internal view returns (FullRequest memory _fullRequest) {
Expand Down
24 changes: 24 additions & 0 deletions solidity/interfaces/IOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ import {IResolutionModule} from './modules/IResolutionModule.sol';
import {IFinalityModule} from './modules/IFinalityModule.sol';

interface IOracle {
event Oracle_RequestCreated(address indexed _requester, bytes32 indexed _requestId);
event Oracle_ResponseProposed(address indexed _proposer, bytes32 indexed _requestId, bytes32 indexed _responseId);
event Oracle_ResponseDisputed(address indexed _disputer, bytes32 indexed _responseId, bytes32 indexed _disputeId);
event Oracle_RequestFinalized(address indexed _caller, bytes32 indexed _requestId);
event Oracle_DisputeEscalated(address indexed _caller, bytes32 indexed _disputeId);
event Oracle_DisputeStatusUpdated(bytes32 indexed _disputeId, DisputeStatus _newStatus);
event Oracle_DisputeResolved(address indexed _caller, bytes32 indexed _disputeId);

error Oracle_NotResolutionModule(address _caller);
error Oracle_NotDisputeModule(address _caller);
error Oracle_NoResolutionModule(bytes32 _disputeId);
Expand Down Expand Up @@ -112,25 +120,41 @@ interface IOracle {
returns (bytes32[] memory _batchRequestsIds);

function validModule(bytes32 _requestId, address _module) external view returns (bool _validModule);

function getDispute(bytes32 _disputeId) external view returns (Dispute memory _dispute);

function getResponse(bytes32 _responseId) external view returns (Response memory _response);

function getRequest(bytes32 _requestId) external view returns (Request memory _request);

function getFullRequest(bytes32 _requestId) external view returns (FullRequest memory _request);

function disputeOf(bytes32 _requestId) external view returns (bytes32 _disputeId);

function proposeResponse(bytes32 _requestId, bytes calldata _responseData) external returns (bytes32 _responseId);

function proposeResponse(
address _proposer,
bytes32 _requestId,
bytes calldata _responseData
) external returns (bytes32 _responseId);

function disputeResponse(bytes32 _requestId, bytes32 _responseId) external returns (bytes32 _disputeId);

function escalateDispute(bytes32 _disputeId) external;

function getFinalizedResponse(bytes32 _requestId) external view returns (Response memory _response);

function getResponseIds(bytes32 _requestId) external view returns (bytes32[] memory _ids);

function resolveDispute(bytes32 _disputeId) external;

function updateDisputeStatus(bytes32 _disputeId, DisputeStatus _status) external;

function listRequests(uint256 _startFrom, uint256 _amount) external view returns (FullRequest[] memory _list);

function listRequestIds(uint256 _startFrom, uint256 _batchSize) external view returns (bytes32[] memory _list);

function finalize(bytes32 _requestId, bytes32 _finalizedResponseId) external;
function totalRequestCount() external view returns (uint256 _count);
}
58 changes: 56 additions & 2 deletions solidity/test/unit/Oracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ contract Oracle_UnitTest is Test {
// 100% random sequence of bytes representing request, response, or dispute id
bytes32 public mockId = bytes32('69');

event Oracle_RequestCreated(address indexed _requester, bytes32 indexed _requestId);
event Oracle_ResponseProposed(address indexed _proposer, bytes32 indexed _requestId, bytes32 indexed _responseId);
event Oracle_ResponseDisputed(address indexed _disputer, bytes32 indexed _responseId, bytes32 indexed _disputeId);
event Oracle_RequestFinalized(address indexed _caller, bytes32 indexed _requestId);
event Oracle_DisputeEscalated(address indexed _caller, bytes32 indexed _disputeId);
event Oracle_DisputeStatusUpdated(bytes32 indexed _disputeId, IOracle.DisputeStatus _newStatus);
event Oracle_DisputeResolved(address indexed _caller, bytes32 indexed _disputeId);

/**
* @notice Deploy the target and mock oracle+modules
*/
Expand Down Expand Up @@ -173,7 +181,11 @@ contract Oracle_UnitTest is Test {
address(responseModule), abi.encodeCall(IModule.setupRequest, (_theoricRequestId, _request.responseModuleData))
);

// Test: crete the request
// Check: emits RequestCreated event?
vm.expectEmit(true, true, true, true);
emit Oracle_RequestCreated(sender, _theoricRequestId);

// Test: create the request
vm.prank(sender);
bytes32 _requestId = oracle.createRequest(_request);

Expand Down Expand Up @@ -212,7 +224,9 @@ contract Oracle_UnitTest is Test {

uint256 _requestsAmount = 5;

IOracle.NewRequest[] memory _requests = new IOracle.NewRequest[](_requestsAmount);
IOracle.NewRequest[] memory _requests = new IOracle.NewRequest[](
_requestsAmount
);

bytes32[] memory _precalculatedIds = new bytes32[](_requestsAmount);

Expand Down Expand Up @@ -293,6 +307,10 @@ contract Oracle_UnitTest is Test {
vm.expectCall(
address(responseModule), abi.encodeCall(IModule.setupRequest, (_theoricRequestId, _request.responseModuleData))
);

// Check: emits RequestCreated event?
vm.expectEmit(true, true, true, true);
emit Oracle_RequestCreated(sender, _theoricRequestId);
}

vm.prank(sender);
Expand Down Expand Up @@ -429,10 +447,20 @@ contract Oracle_UnitTest is Test {
);
vm.expectCall(address(responseModule), abi.encodeCall(IResponseModule.propose, (_requestId, sender, _responseData)));

// Check: emits ResponseProposed event?
vm.expectEmit(true, true, true, true);
emit Oracle_ResponseProposed(sender, _requestId, _responseId);

// Test: propose the response
vm.prank(sender);
bytes32 _actualResponseId = oracle.proposeResponse(_requestId, _responseData);

// Check: emits ResponseProposed event?
vm.expectEmit(true, true, true, true);
emit Oracle_ResponseProposed(
sender, _requestId, keccak256(abi.encodePacked(sender, address(oracle), _requestId, _responseNonce + 1))
);

vm.prank(sender);
bytes32 _secondResponseId = oracle.proposeResponse(_requestId, _responseData);

Expand Down Expand Up @@ -499,10 +527,20 @@ contract Oracle_UnitTest is Test {
address(responseModule), abi.encodeCall(IResponseModule.propose, (_requestId, _proposer, _responseData))
);

// Check: emits ResponseProposed event?
vm.expectEmit(true, true, true, true);
emit Oracle_ResponseProposed(_proposer, _requestId, _responseId);

// Test: propose the response
vm.prank(address(disputeModule));
bytes32 _actualResponseId = oracle.proposeResponse(_proposer, _requestId, _responseData);

// Check: emits ResponseProposed event?
vm.expectEmit(true, true, true, true);
emit Oracle_ResponseProposed(
_proposer, _requestId, keccak256(abi.encodePacked(_proposer, address(oracle), _requestId, _responseNonce + 1))
);

vm.prank(address(disputeModule));
bytes32 _secondResponseId = oracle.proposeResponse(_proposer, _requestId, _responseData);

Expand Down Expand Up @@ -564,6 +602,10 @@ contract Oracle_UnitTest is Test {
abi.encodeCall(IDisputeModule.disputeResponse, (_requestId, _responseId, sender, _proposer))
);

// Check: emits ResponseDisputed event?
vm.expectEmit(true, true, true, true);
emit Oracle_ResponseDisputed(sender, _responseId, _disputeId);

// Test: dispute the response
vm.prank(sender);
bytes32 _actualDisputeId = oracle.disputeResponse(_requestId, _responseId);
Expand Down Expand Up @@ -636,6 +678,10 @@ contract Oracle_UnitTest is Test {
address(disputeModule), abi.encodeCall(IDisputeModule.updateDisputeStatus, (_disputeId, mockDispute))
);

// Check: emits DisputeStatusUpdated event?
vm.expectEmit(true, true, true, true);
emit Oracle_DisputeStatusUpdated(_disputeId, IOracle.DisputeStatus(_newStatus));

// Test: change the status
vm.prank(address(resolutionModule));
oracle.updateDisputeStatus(_disputeId, IOracle.DisputeStatus(_newStatus));
Expand Down Expand Up @@ -664,6 +710,10 @@ contract Oracle_UnitTest is Test {
vm.mockCall(address(resolutionModule), abi.encodeCall(IResolutionModule.resolveDispute, (_disputeId)), abi.encode());
vm.expectCall(address(resolutionModule), abi.encodeCall(IResolutionModule.resolveDispute, (_disputeId)));

// Check: emits DisputeResolved event?
vm.expectEmit(true, true, true, true);
emit Oracle_DisputeResolved(address(this), _disputeId);

// Test: resolve the dispute
oracle.resolveDispute(_disputeId);
}
Expand Down Expand Up @@ -821,6 +871,10 @@ contract Oracle_UnitTest is Test {
vm.expectCall(address(finalityModule), abi.encodeCall(IModule.finalizeRequest, (_requestId)));
}

// Check: emits RequestFinalized event?
vm.expectEmit(true, true, true, true);
emit Oracle_RequestFinalized(_caller, _requestId);

// Test: finalize the request
vm.prank(_caller);
oracle.finalize(_requestId, _responseId);
Expand Down

0 comments on commit 3fe3d5a

Please sign in to comment.