-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf: optimize
CircuitResolverModule
(#6)
- Loading branch information
Showing
5 changed files
with
494 additions
and
631 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
184 changes: 93 additions & 91 deletions
184
solidity/contracts/modules/dispute/CircuitResolverModule.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,91 +1,93 @@ | ||
// // SPDX-License-Identifier: MIT | ||
// pragma solidity ^0.8.19; | ||
|
||
// // solhint-disable-next-line no-unused-import | ||
// import {Module, IModule} from '@defi-wonderland/prophet-core-contracts/solidity/contracts/Module.sol'; | ||
// import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; | ||
|
||
// import {ICircuitResolverModule} from '../../../interfaces/modules/dispute/ICircuitResolverModule.sol'; | ||
|
||
// contract CircuitResolverModule is Module, ICircuitResolverModule { | ||
// constructor(IOracle _oracle) Module(_oracle) {} | ||
|
||
// mapping(bytes32 _requestId => bytes _correctResponse) internal _correctResponses; | ||
|
||
// /// @inheritdoc IModule | ||
// function moduleName() external pure returns (string memory _moduleName) { | ||
// return 'CircuitResolverModule'; | ||
// } | ||
|
||
// /// @inheritdoc ICircuitResolverModule | ||
// function decodeRequestData(bytes32 _requestId) public view returns (RequestParameters memory _params) { | ||
// _params = abi.decode(requestData[_requestId], (RequestParameters)); | ||
// } | ||
|
||
// /// @inheritdoc ICircuitResolverModule | ||
// function disputeEscalated(bytes32 _disputeId) external onlyOracle {} | ||
|
||
// /// @inheritdoc ICircuitResolverModule | ||
// function onDisputeStatusChange(bytes32, /* _disputeId */ IOracle.Dispute memory _dispute) external onlyOracle { | ||
// RequestParameters memory _params = decodeRequestData(_dispute.requestId); | ||
|
||
// IOracle.Response memory _response = ORACLE.getResponse(_dispute.responseId); | ||
|
||
// bytes memory _correctResponse = _correctResponses[_dispute.requestId]; | ||
// bool _won = _response.response.length != _correctResponse.length | ||
// || keccak256(_response.response) != keccak256(_correctResponse); | ||
|
||
// if (_won) { | ||
// _params.accountingExtension.pay({ | ||
// _requestId: _dispute.requestId, | ||
// _payer: _dispute.proposer, | ||
// _receiver: _dispute.disputer, | ||
// _token: _params.bondToken, | ||
// _amount: _params.bondSize | ||
// }); | ||
// bytes32 _correctResponseId = | ||
// ORACLE.proposeResponse(_dispute.disputer, _dispute.requestId, abi.encode(_correctResponses[_dispute.requestId])); | ||
// ORACLE.finalize(_dispute.requestId, _correctResponseId); | ||
// } else { | ||
// ORACLE.finalize(_dispute.requestId, _dispute.responseId); | ||
// } | ||
|
||
// delete _correctResponses[_dispute.requestId]; | ||
|
||
// emit DisputeStatusChanged({ | ||
// _requestId: _dispute.requestId, | ||
// _responseId: _dispute.responseId, | ||
// _disputer: _dispute.disputer, | ||
// _proposer: _dispute.proposer, | ||
// _status: _dispute.status | ||
// }); | ||
// } | ||
|
||
// /// @inheritdoc ICircuitResolverModule | ||
// function disputeResponse( | ||
// bytes32 _requestId, | ||
// bytes32 _responseId, | ||
// address _disputer, | ||
// address _proposer | ||
// ) external onlyOracle returns (IOracle.Dispute memory _dispute) { | ||
// IOracle.Response memory _response = ORACLE.getResponse(_responseId); | ||
// RequestParameters memory _params = decodeRequestData(_requestId); | ||
|
||
// (, bytes memory _correctResponse) = _params.verifier.call(_params.callData); | ||
// _correctResponses[_requestId] = _correctResponse; | ||
|
||
// bool _won = _response.response.length != _correctResponse.length | ||
// || keccak256(_response.response) != keccak256(_correctResponse); | ||
|
||
// _dispute = IOracle.Dispute({ | ||
// disputer: _disputer, | ||
// responseId: _responseId, | ||
// proposer: _proposer, | ||
// requestId: _requestId, | ||
// status: _won ? IOracle.DisputeStatus.Won : IOracle.DisputeStatus.Lost, | ||
// createdAt: block.timestamp | ||
// }); | ||
|
||
// emit ResponseDisputed(_requestId, _responseId, _disputer, _proposer); | ||
// } | ||
// } | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
// solhint-disable-next-line no-unused-import | ||
import {Module, IModule} from '@defi-wonderland/prophet-core-contracts/solidity/contracts/Module.sol'; | ||
import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; | ||
|
||
import {ICircuitResolverModule} from '../../../interfaces/modules/dispute/ICircuitResolverModule.sol'; | ||
|
||
contract CircuitResolverModule is Module, ICircuitResolverModule { | ||
constructor(IOracle _oracle) Module(_oracle) {} | ||
|
||
mapping(bytes32 _requestId => bytes _correctResponse) internal _correctResponses; | ||
|
||
/// @inheritdoc IModule | ||
function moduleName() external pure returns (string memory _moduleName) { | ||
return 'CircuitResolverModule'; | ||
} | ||
|
||
/// @inheritdoc ICircuitResolverModule | ||
function decodeRequestData(bytes calldata _data) public pure returns (RequestParameters memory _params) { | ||
_params = abi.decode(_data, (RequestParameters)); | ||
} | ||
|
||
/// @inheritdoc ICircuitResolverModule | ||
function onDisputeStatusChange( | ||
bytes32 _disputeId, | ||
IOracle.Request calldata _request, | ||
IOracle.Response calldata _response, | ||
IOracle.Dispute calldata _dispute | ||
) external onlyOracle { | ||
// TODO: Call `disputeStatus` to check the current status instead of reading from `_correctResponses` | ||
RequestParameters memory _params = decodeRequestData(_request.disputeModuleData); | ||
|
||
bytes memory _correctResponse = _correctResponses[_dispute.requestId]; | ||
bool _won = _response.response.length != _correctResponse.length | ||
|| keccak256(_response.response) != keccak256(_correctResponse); | ||
|
||
if (_won) { | ||
_params.accountingExtension.pay({ | ||
_requestId: _dispute.requestId, | ||
_payer: _dispute.proposer, | ||
_receiver: _dispute.disputer, | ||
_token: _params.bondToken, | ||
_amount: _params.bondSize | ||
}); | ||
|
||
IOracle.Response memory _newResponse = | ||
IOracle.Response({requestId: _dispute.requestId, proposer: _dispute.disputer, response: _correctResponse}); | ||
|
||
emit DisputeStatusChanged({_disputeId: _disputeId, _dispute: _dispute, _status: IOracle.DisputeStatus.Won}); | ||
|
||
ORACLE.proposeResponse(_request, _newResponse); | ||
ORACLE.finalize(_request, _newResponse); | ||
} else { | ||
emit DisputeStatusChanged({_disputeId: _disputeId, _dispute: _dispute, _status: IOracle.DisputeStatus.Lost}); | ||
|
||
ORACLE.finalize(_request, _response); | ||
} | ||
|
||
delete _correctResponses[_dispute.requestId]; | ||
} | ||
|
||
/// @inheritdoc ICircuitResolverModule | ||
function disputeResponse( | ||
IOracle.Request calldata _request, | ||
IOracle.Response calldata _response, | ||
IOracle.Dispute calldata _dispute | ||
) external onlyOracle { | ||
RequestParameters memory _params = decodeRequestData(_request.disputeModuleData); | ||
|
||
(bool _success, bytes memory _correctResponse) = _params.verifier.call(_params.callData); | ||
|
||
if (!_success) revert CircuitResolverModule_VerificationFailed(); | ||
|
||
_correctResponses[_response.requestId] = _correctResponse; | ||
|
||
IOracle.DisputeStatus _status = _response.response.length != _correctResponse.length | ||
|| keccak256(_response.response) != keccak256(_correctResponse) | ||
? IOracle.DisputeStatus.Won | ||
: IOracle.DisputeStatus.Lost; | ||
|
||
emit ResponseDisputed({ | ||
_requestId: _response.requestId, | ||
_responseId: _dispute.responseId, | ||
_disputeId: _getId(_dispute), | ||
_dispute: _dispute, | ||
_blockNumber: block.number | ||
}); | ||
|
||
ORACLE.updateDisputeStatus(_request, _response, _dispute, _status); | ||
} | ||
} |
144 changes: 85 additions & 59 deletions
144
solidity/interfaces/modules/dispute/ICircuitResolverModule.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,94 @@ | ||
// // SPDX-License-Identifier: MIT | ||
// pragma solidity ^0.8.19; | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
// import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; | ||
// import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; | ||
// import {IDisputeModule} from | ||
// '@defi-wonderland/prophet-core-contracts/solidity/interfaces/modules/dispute/IDisputeModule.sol'; | ||
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; | ||
import {IOracle} from '@defi-wonderland/prophet-core-contracts/solidity/interfaces/IOracle.sol'; | ||
import {IDisputeModule} from | ||
'@defi-wonderland/prophet-core-contracts/solidity/interfaces/modules/dispute/IDisputeModule.sol'; | ||
|
||
// import {IAccountingExtension} from '../../extensions/IAccountingExtension.sol'; | ||
import {IAccountingExtension} from '../../extensions/IAccountingExtension.sol'; | ||
|
||
// /** | ||
// * @title CircuitResolverModule | ||
// * @notice Module allowing users to dispute a proposed response | ||
// * by bonding tokens. | ||
// * The module will invoke the circuit verifier supplied to calculate | ||
// * the proposed response and compare it to the correct response. | ||
// * - If the dispute is valid, the disputer wins and their bond is returned along with a reward. | ||
// * - If the dispute is invalid, the bond is forfeited and returned to the proposer. | ||
// * | ||
// * After the dispute is settled, the correct response is automatically proposed to the oracle | ||
// * and the request is finalized. | ||
// */ | ||
// interface ICircuitResolverModule is IDisputeModule { | ||
// /*/////////////////////////////////////////////////////////////// | ||
// STRUCTS | ||
// //////////////////////////////////////////////////////////////*/ | ||
/** | ||
* @title CircuitResolverModule | ||
* @notice Module allowing users to dispute a proposed response by bonding tokens. | ||
* The module will invoke the circuit verifier supplied to calculate | ||
* the proposed response and compare it to the correct response. | ||
* - If the dispute is valid, the disputer wins and their bond is returned along with a reward. | ||
* - If the dispute is invalid, the bond is forfeited and returned to the proposer. | ||
* | ||
* After the dispute is settled, the correct response is automatically proposed to the oracle | ||
* and the request is finalized. | ||
*/ | ||
interface ICircuitResolverModule is IDisputeModule { | ||
/*/////////////////////////////////////////////////////////////// | ||
STRUCTS | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
// /** | ||
// * @notice Parameters of the request as stored in the module | ||
// * @return callData The encoded data forwarded to the verifier | ||
// * @return verifier The address of the verifier contract | ||
// * @return accountingExtension The address of the accounting extension | ||
// * @return bondToken The address of the bond token | ||
// * @return bondSize The size of the bond | ||
// */ | ||
// struct RequestParameters { | ||
// bytes callData; | ||
// address verifier; | ||
// IAccountingExtension accountingExtension; | ||
// IERC20 bondToken; | ||
// uint256 bondSize; | ||
// } | ||
/** | ||
* @notice Parameters of the request as stored in the module | ||
* | ||
* @return callData The encoded data forwarded to the verifier | ||
* @return verifier The address of the verifier contract | ||
* @return accountingExtension The address of the accounting extension | ||
* @return bondToken The address of the bond token | ||
* @return bondSize The size of the bond | ||
*/ | ||
struct RequestParameters { | ||
bytes callData; | ||
address verifier; | ||
IAccountingExtension accountingExtension; | ||
IERC20 bondToken; | ||
uint256 bondSize; | ||
} | ||
|
||
// /*/////////////////////////////////////////////////////////////// | ||
// LOGIC | ||
// //////////////////////////////////////////////////////////////*/ | ||
/*/////////////////////////////////////////////////////////////// | ||
ERRORS | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
// /** | ||
// * @notice Returns the decoded data for a request | ||
// * @param _requestId The ID of the request | ||
// * @return _params The decoded parameters of the request | ||
// */ | ||
// function decodeRequestData(bytes32 _requestId) external view returns (RequestParameters memory _params); | ||
/** | ||
* @notice Thrown when the verification of a response fails | ||
*/ | ||
error CircuitResolverModule_VerificationFailed(); | ||
|
||
// /// @inheritdoc IDisputeModule | ||
// function disputeResponse( | ||
// bytes32 _requestId, | ||
// bytes32 _responseId, | ||
// address _disputer, | ||
// address _proposer | ||
// ) external returns (IOracle.Dispute memory _dispute); | ||
/*/////////////////////////////////////////////////////////////// | ||
LOGIC | ||
//////////////////////////////////////////////////////////////*/ | ||
|
||
// /// @inheritdoc IDisputeModule | ||
// function onDisputeStatusChange(bytes32 _disputeId, IOracle.Dispute memory _dispute) external; | ||
/** | ||
* @notice Returns the decoded data for a request | ||
* | ||
* @param _data The encoded request parameters | ||
* @return _params The decoded parameters of the request | ||
*/ | ||
function decodeRequestData(bytes calldata _data) external view returns (RequestParameters memory _params); | ||
|
||
// /// @inheritdoc IDisputeModule | ||
// function disputeEscalated(bytes32 _disputeId) external; | ||
// } | ||
/** | ||
* @notice Initiates and resolves the dispute by comparing the proposed response with the one returned by the verifier | ||
* | ||
* @dev This function will notify the oracle about the outcome of the dispute | ||
* @param _request The request that the response was proposed to | ||
* @param _response The response that is being disputed | ||
* @param _dispute The dispute created by the oracle | ||
*/ | ||
function disputeResponse( | ||
IOracle.Request calldata _request, | ||
IOracle.Response calldata _response, | ||
IOracle.Dispute calldata _dispute | ||
) external; | ||
|
||
/** | ||
* @notice Depending on the status of the dispute, either pays the disputer and submits the correct response, | ||
* or pays the proposer. Finalizes the request in any case. | ||
* | ||
* @param _disputeId The id of the dispute | ||
* @param _request The request | ||
* @param _response The response that was disputed | ||
* @param _dispute The dispute | ||
*/ | ||
function onDisputeStatusChange( | ||
bytes32 _disputeId, | ||
IOracle.Request calldata _request, | ||
IOracle.Response calldata _response, | ||
IOracle.Dispute calldata _dispute | ||
) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import {ITreeVerifier} from '../../interfaces/ITreeVerifier.sol'; | ||
|
||
contract MockVerifier is ITreeVerifier { | ||
constructor() {} | ||
|
||
function calculateRoot( | ||
bytes memory, /* _treeData */ | ||
bytes32[] memory /* _leavesToInsert */ | ||
) external view returns (bytes32 _calculatedRoot) { | ||
_calculatedRoot = keccak256(abi.encode(block.timestamp)); | ||
} | ||
} |
Oops, something went wrong.