Skip to content

Commit

Permalink
feat: CircuitResolverModule (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
turtlemoji authored Aug 15, 2023
1 parent bd1328d commit de1d10b
Show file tree
Hide file tree
Showing 7 changed files with 727 additions and 3 deletions.
106 changes: 106 additions & 0 deletions solidity/contracts/modules/CircuitResolverModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import {ICircuitResolverModule} from '../../interfaces/modules/ICircuitResolverModule.sol';
import {IOracle} from '../../interfaces/IOracle.sol';
import {IAccountingExtension} from '../../interfaces/extensions/IAccountingExtension.sol';

import {Module} from '../Module.sol';

contract CircuitResolverModule is Module, ICircuitResolverModule {
constructor(IOracle _oracle) Module(_oracle) {}

function moduleName() external pure returns (string memory _moduleName) {
return 'CircuitResolverModule';
}

function decodeRequestData(bytes32 _requestId)
public
view
returns (
bytes memory _callData,
address _verifier,
IAccountingExtension _accountingExtension,
IERC20 _bondToken,
uint256 _bondSize
)
{
(_callData, _verifier, _accountingExtension, _bondToken, _bondSize) =
abi.decode(requestData[_requestId], (bytes, address, IAccountingExtension, IERC20, uint256));
}

function disputeEscalated(bytes32 _disputeId) external onlyOracle {}
function updateDisputeStatus(bytes32, /* _disputeId */ IOracle.Dispute memory _dispute) external onlyOracle {}

function disputeResponse(
bytes32 _requestId,
bytes32 _responseId,
address _disputer,
address _proposer
) external onlyOracle returns (IOracle.Dispute memory _dispute) {
IOracle.Response memory _response = ORACLE.getResponse(_responseId);

(
bytes memory _proposedResponse,
bytes memory _correctResponse,
IAccountingExtension _accountingExtension,
IERC20 _bondToken,
uint256 _bondSize
) = _getDisputeData(_requestId, _response);

// We test length first to short circuit and don't do keccack256
// if lengths are different, just to optimize gas usage
bool _won =
_proposedResponse.length != _correctResponse.length || keccak256(_proposedResponse) != keccak256(_correctResponse);

_dispute = IOracle.Dispute({
disputer: _disputer,
responseId: _responseId,
proposer: _proposer,
requestId: _requestId,
status: _won ? IOracle.DisputeStatus.Won : IOracle.DisputeStatus.Lost,
createdAt: block.timestamp
});

if (_won) {
_accountingExtension.pay(_dispute.requestId, _dispute.proposer, _dispute.disputer, _bondToken, _bondSize);
_accountingExtension.release(_dispute.disputer, _dispute.requestId, _bondToken, _bondSize);
bytes32 _correctResponseId = ORACLE.proposeResponse(_disputer, _requestId, abi.encode(_correctResponse));
ORACLE.finalize(_requestId, _correctResponseId);
} else {
_accountingExtension.release(_dispute.proposer, _dispute.requestId, _bondToken, _bondSize);
ORACLE.finalize(_requestId, _responseId);
}
}

function _getDisputeData(
bytes32 _requestId,
IOracle.Response memory _response
)
internal
returns (
bytes memory _proposedResponse,
bytes memory _correctResponse,
IAccountingExtension _accountingExtension,
IERC20 _bondToken,
uint256 _bondSize
)
{
(
bytes memory _callData,
address _verifier,
IAccountingExtension __accountingExtension,
IERC20 __bondToken,
uint256 __bondSize
) = decodeRequestData(_requestId);

_proposedResponse = _response.response;
(, _correctResponse) = _verifier.call(_callData);

_accountingExtension = __accountingExtension;
_bondToken = __bondToken;
_bondSize = __bondSize;
}
}
51 changes: 51 additions & 0 deletions solidity/contracts/modules/CircuitResolverRequestModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import {ICircuitResolverRequestModule} from '../../interfaces/modules/ICircuitResolverRequestModule.sol';
import {IAccountingExtension} from '../../interfaces/extensions/IAccountingExtension.sol';
import {IOracle} from '../../interfaces/IOracle.sol';
import {IModule, Module} from '../Module.sol';

contract CircuitResolverRequestModule is Module, ICircuitResolverRequestModule {
constructor(IOracle _oracle) Module(_oracle) {}

function decodeRequestData(bytes32 _requestId)
public
view
returns (
bytes memory _callData,
address _verifier,
IAccountingExtension _accountingExtension,
IERC20 _paymentToken,
uint256 _paymentAmount
)
{
(_callData, _verifier, _accountingExtension, _paymentToken, _paymentAmount) =
abi.decode(requestData[_requestId], (bytes, address, IAccountingExtension, IERC20, uint256));
}

function _afterSetupRequest(bytes32 _requestId, bytes calldata _data) internal override {
(,, IAccountingExtension _accountingExtension, IERC20 _paymentToken, uint256 _paymentAmount) =
decodeRequestData(_requestId);
IOracle.Request memory _request = ORACLE.getRequest(_requestId);
_accountingExtension.bond(_request.requester, _requestId, _paymentToken, _paymentAmount);
}

function finalizeRequest(bytes32 _requestId, address) external override(IModule, Module) onlyOracle {
IOracle.Request memory _request = ORACLE.getRequest(_requestId);
IOracle.Response memory _response = ORACLE.getFinalizedResponse(_requestId);
(,, IAccountingExtension _accountingExtension, IERC20 _paymentToken, uint256 _paymentAmount) =
decodeRequestData(_requestId);
if (_response.createdAt != 0) {
_accountingExtension.pay(_requestId, _request.requester, _response.proposer, _paymentToken, _paymentAmount);
} else {
_accountingExtension.release(_request.requester, _requestId, _paymentToken, _paymentAmount);
}
}

function moduleName() public pure returns (string memory _moduleName) {
_moduleName = 'CircuitResolverRequestModule';
}
}
22 changes: 22 additions & 0 deletions solidity/interfaces/modules/ICircuitResolverModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import {IDisputeModule} from './IDisputeModule.sol';
import {IAccountingExtension} from '../extensions/IAccountingExtension.sol';

interface ICircuitResolverModule is IDisputeModule {
error CircuitResolverModule_DisputingCorrectHash(bytes32 _proposedHash);

function decodeRequestData(bytes32 _requestId)
external
view
returns (
bytes memory _callData,
address _verifier,
IAccountingExtension _accountingExtension,
IERC20 _bondToken,
uint256 _bondSize
);
}
20 changes: 20 additions & 0 deletions solidity/interfaces/modules/ICircuitResolverRequestModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import {IRequestModule} from '../../interfaces/modules/IRequestModule.sol';
import {IAccountingExtension} from '../../interfaces/extensions/IAccountingExtension.sol';

interface ICircuitResolverRequestModule is IRequestModule {
function decodeRequestData(bytes32 _requestId)
external
view
returns (
bytes memory _callData,
address _verifier,
IAccountingExtension _accountingExtension,
IERC20 _paymentToken,
uint256 _paymentAmount
);
}
Loading

0 comments on commit de1d10b

Please sign in to comment.