Skip to content

Commit

Permalink
feat: access control (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: Ashitaka <[email protected]>
Co-authored-by: Gas One Cent <[email protected]>
  • Loading branch information
3 people authored Nov 12, 2024
1 parent 7d7a76d commit 822962a
Show file tree
Hide file tree
Showing 44 changed files with 943 additions and 382 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"package.json": "sort-package-json"
},
"dependencies": {
"@defi-wonderland/prophet-core": "0.0.0-4d28a0ec",
"@defi-wonderland/prophet-core": "0.0.0-0e46031c",
"@openzeppelin/contracts": "4.9.5",
"solmate": "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c"
},
Expand Down
1 change: 1 addition & 0 deletions solidity/contracts/extensions/BondEscalationAccounting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ contract BondEscalationAccounting is AccountingExtension, IBondEscalationAccount
}
}

/// @notice Checks if the caller is an authorized caller
modifier onlyAuthorizedCaller() {
if (!authorizedCallers[msg.sender]) revert BondEscalationAccounting_UnauthorizedCaller();
_;
Expand Down
51 changes: 51 additions & 0 deletions solidity/contracts/modules/access/ModuleAccessController.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 {CommonAccessController} from '@defi-wonderland/prophet-core/solidity/contracts/CommonAccessController.sol';

import {IModuleAccessController} from '../../../interfaces/modules/access/IModuleAccessController.sol';
import {Module} from '@defi-wonderland/prophet-core/solidity/contracts/Module.sol';
import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol';

abstract contract ModuleAccessController is IModuleAccessController, CommonAccessController, Module {
constructor(IOracle _oracle) Module(_oracle) {}

/**
* @notice Returns an access control object using the contract address as user and the given data
* @dev should only be used by modules as the self-access-control object
* @param _data Arbitrary data
* @return _accessControl The self access control for this contract.
*/
function _defaultAccessControl(bytes memory _data) internal view returns (AccessControl memory _accessControl) {
_accessControl = AccessControl({user: address(this), data: _data});
}

/**
* @notice Returns an access control object using the contract address as user, and empty data
*
* @dev should only be used by modules as the self-access-control object
* @return _accessControl The self access control for this contract.
*/
function _defaultAccessControl() internal view returns (AccessControl memory _accessControl) {
_accessControl = _defaultAccessControl(bytes(''));
}

modifier hasAccess(
address _accessModule,
bytes32 _typehash,
bytes memory _params,
AccessControl memory _accessControl
) {
if (_accessControl.user != msg.sender) {
if (_accessModule == address(0)) {
revert AccessController_NoAccess();
} else {
if (!ORACLE.isAccessModuleApproved(_accessControl.user, _accessModule)) {
revert ModuleAccessController_AccessModuleNotApproved();
}
_hasAccess(_accessModule, _typehash, _params, _accessControl);
}
}
_;
}
}
63 changes: 49 additions & 14 deletions solidity/contracts/modules/dispute/BondEscalationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {FixedPointMathLib} from 'solmate/src/utils/FixedPointMathLib.sol';

import {IBondEscalationModule} from '../../../interfaces/modules/dispute/IBondEscalationModule.sol';

contract BondEscalationModule is Module, IBondEscalationModule {
import {ModuleAccessController} from '../access/ModuleAccessController.sol';

import {ModuleTypehash} from '../../utils/ModuleTypehash.sol';

contract BondEscalationModule is ModuleAccessController, IBondEscalationModule {
/// @inheritdoc IBondEscalationModule
mapping(bytes32 _requestId => mapping(address _pledger => uint256 pledges)) public pledgesForDispute;

Expand All @@ -19,7 +23,7 @@ contract BondEscalationModule is Module, IBondEscalationModule {
*/
mapping(bytes32 _requestId => BondEscalation) internal _escalations;

constructor(IOracle _oracle) Module(_oracle) {}
constructor(IOracle _oracle) ModuleAccessController(_oracle) {}

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
Expand Down Expand Up @@ -61,7 +65,7 @@ contract BondEscalationModule is Module, IBondEscalationModule {
_escalation.disputeId = _disputeId;
emit BondEscalationStatusUpdated(_dispute.requestId, _disputeId, BondEscalationStatus.Active);
} else if (_disputeId != _escalation.disputeId) {
ORACLE.escalateDispute(_request, _response, _dispute);
ORACLE.escalateDispute(_request, _response, _dispute, _defaultAccessControl());
}
}

Expand Down Expand Up @@ -208,39 +212,67 @@ contract BondEscalationModule is Module, IBondEscalationModule {
////////////////////////////////////////////////////////////////////

/// @inheritdoc IBondEscalationModule
function pledgeForDispute(IOracle.Request calldata _request, IOracle.Dispute calldata _dispute) external {
function pledgeForDispute(
IOracle.Request calldata _request,
IOracle.Dispute calldata _dispute,
AccessControl calldata _accessControl
)
external
hasAccess(
_request.accessModule,
ModuleTypehash._PLEDGE_FOR_DISPUTE_TYPEHASH,
abi.encode(_request, _dispute),
_accessControl
)
{
bytes32 _disputeId = _getId(_dispute);
RequestParameters memory _params = _pledgeChecks(_request, _dispute, true);

address _pledger = _accessControl.user;

_escalations[_dispute.requestId].amountOfPledgesForDispute += 1;
pledgesForDispute[_dispute.requestId][msg.sender] += 1;
pledgesForDispute[_dispute.requestId][_pledger] += 1;
_params.accountingExtension.pledge({
_pledger: msg.sender,
_pledger: _pledger,
_request: _request,
_dispute: _dispute,
_token: _params.bondToken,
_amount: _params.bondSize
});

emit PledgedForDispute(_disputeId, msg.sender, _params.bondSize);
emit PledgedForDispute(_disputeId, _pledger, _params.bondSize);
}

/// @inheritdoc IBondEscalationModule
function pledgeAgainstDispute(IOracle.Request calldata _request, IOracle.Dispute calldata _dispute) external {
function pledgeAgainstDispute(
IOracle.Request calldata _request,
IOracle.Dispute calldata _dispute,
AccessControl calldata _accessControl
)
external
hasAccess(
_request.accessModule,
ModuleTypehash._PLEDGE_AGAINST_DISPUTE_TYPEHASH,
abi.encode(_request, _dispute),
_accessControl
)
{
bytes32 _disputeId = _getId(_dispute);
RequestParameters memory _params = _pledgeChecks(_request, _dispute, false);

address _pledger = _accessControl.user;

_escalations[_dispute.requestId].amountOfPledgesAgainstDispute += 1;
pledgesAgainstDispute[_dispute.requestId][msg.sender] += 1;
pledgesAgainstDispute[_dispute.requestId][_pledger] += 1;
_params.accountingExtension.pledge({
_pledger: msg.sender,
_pledger: _pledger,
_request: _request,
_dispute: _dispute,
_token: _params.bondToken,
_amount: _params.bondSize
});

emit PledgedAgainstDispute(_disputeId, msg.sender, _params.bondSize);
emit PledgedAgainstDispute(_disputeId, _pledger, _params.bondSize);
}

/// @inheritdoc IBondEscalationModule
Expand Down Expand Up @@ -274,9 +306,12 @@ contract BondEscalationModule is Module, IBondEscalationModule {

emit BondEscalationStatusUpdated(_dispute.requestId, _disputeId, _escalation.status);

ORACLE.updateDisputeStatus(
_request, _response, _dispute, _disputersWon ? IOracle.DisputeStatus.Won : IOracle.DisputeStatus.Lost
);
ORACLE.updateDisputeStatus({
_request: _request,
_response: _response,
_dispute: _dispute,
_status: _disputersWon ? IOracle.DisputeStatus.Won : IOracle.DisputeStatus.Lost
});
}

/**
Expand Down
15 changes: 9 additions & 6 deletions solidity/contracts/modules/dispute/CircuitResolverModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle
import {IProphetVerifier} from '../../../interfaces/IProphetVerifier.sol';
import {ICircuitResolverModule} from '../../../interfaces/modules/dispute/ICircuitResolverModule.sol';

contract CircuitResolverModule is Module, ICircuitResolverModule {
import {ModuleAccessController} from '../access/ModuleAccessController.sol';

contract CircuitResolverModule is ModuleAccessController, ICircuitResolverModule {
/// @notice Keeps track of the correct responses to requests
mapping(bytes32 _requestId => bytes _correctResponse) internal _correctResponses;

constructor(IOracle _oracle) Module(_oracle) {}
constructor(IOracle _oracle) ModuleAccessController(_oracle) {}

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
Expand All @@ -32,6 +34,7 @@ contract CircuitResolverModule is Module, ICircuitResolverModule {
) external onlyOracle {
RequestParameters memory _params = decodeRequestData(_request.disputeModuleData);
IOracle.DisputeStatus _status = ORACLE.disputeStatus(_disputeId);
AccessControl memory _accessControl = _defaultAccessControl();

if (_status == IOracle.DisputeStatus.Won) {
_params.accountingExtension.pay({
Expand All @@ -50,12 +53,12 @@ contract CircuitResolverModule is Module, ICircuitResolverModule {

emit DisputeStatusChanged({_disputeId: _disputeId, _dispute: _dispute, _status: IOracle.DisputeStatus.Won});

ORACLE.proposeResponse(_request, _newResponse);
ORACLE.finalize(_request, _newResponse);
ORACLE.proposeResponse(_request, _newResponse, _accessControl);
ORACLE.finalize(_request, _newResponse, _accessControl);
} else {
emit DisputeStatusChanged({_disputeId: _disputeId, _dispute: _dispute, _status: IOracle.DisputeStatus.Lost});

ORACLE.finalize(_request, _response);
ORACLE.finalize(_request, _response, _accessControl);
}

delete _correctResponses[_dispute.requestId];
Expand Down Expand Up @@ -88,7 +91,7 @@ contract CircuitResolverModule is Module, ICircuitResolverModule {
_dispute: _dispute
});

ORACLE.updateDisputeStatus(_request, _response, _dispute, _status);
ORACLE.updateDisputeStatus({_request: _request, _response: _response, _dispute: _dispute, _status: _status});
}

/// @inheritdoc IModule
Expand Down
14 changes: 8 additions & 6 deletions solidity/contracts/modules/dispute/RootVerificationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle

import {IRootVerificationModule} from '../../../interfaces/modules/dispute/IRootVerificationModule.sol';
import {MerkleLib} from '../../libraries/MerkleLib.sol';
import {ModuleAccessController} from '../access/ModuleAccessController.sol';

contract RootVerificationModule is Module, IRootVerificationModule {
contract RootVerificationModule is ModuleAccessController, IRootVerificationModule {
using MerkleLib for MerkleLib.Tree;

/**
* @notice The calculated correct root for a given request
*/
mapping(bytes32 _requestId => bytes32 _correctRoot) internal _correctRoots;

constructor(IOracle _oracle) Module(_oracle) {}
constructor(IOracle _oracle) ModuleAccessController(_oracle) {}

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
Expand All @@ -36,6 +37,7 @@ contract RootVerificationModule is Module, IRootVerificationModule {
) external onlyOracle {
RequestParameters memory _params = decodeRequestData(_request.disputeModuleData);
IOracle.DisputeStatus _status = ORACLE.disputeStatus(_disputeId);
AccessControl memory _accessControl = _defaultAccessControl();

if (_status == IOracle.DisputeStatus.Won) {
_params.accountingExtension.pay({
Expand All @@ -54,11 +56,11 @@ contract RootVerificationModule is Module, IRootVerificationModule {

emit DisputeStatusChanged({_disputeId: _disputeId, _dispute: _dispute, _status: IOracle.DisputeStatus.Won});

ORACLE.proposeResponse(_request, _newResponse);
ORACLE.finalize(_request, _newResponse);
ORACLE.proposeResponse(_request, _newResponse, _accessControl);
ORACLE.finalize(_request, _newResponse, _accessControl);
} else {
emit DisputeStatusChanged({_disputeId: _disputeId, _dispute: _dispute, _status: IOracle.DisputeStatus.Lost});
ORACLE.finalize(_request, _response);
ORACLE.finalize(_request, _response, _accessControl);
}

delete _correctRoots[_dispute.requestId];
Expand Down Expand Up @@ -86,7 +88,7 @@ contract RootVerificationModule is Module, IRootVerificationModule {
_dispute: _dispute
});

ORACLE.updateDisputeStatus(_request, _response, _dispute, _status);
ORACLE.updateDisputeStatus({_request: _request, _response: _response, _dispute: _dispute, _status: _status});
}

/// @inheritdoc IModule
Expand Down
7 changes: 4 additions & 3 deletions solidity/contracts/modules/resolution/ArbitratorModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle

import {IArbitrator} from '../../../interfaces/IArbitrator.sol';
import {IArbitratorModule} from '../../../interfaces/modules/resolution/IArbitratorModule.sol';
import {ModuleAccessController} from '../access/ModuleAccessController.sol';

contract ArbitratorModule is Module, IArbitratorModule {
contract ArbitratorModule is ModuleAccessController, IArbitratorModule {
/**
* @notice The status of all disputes
*/
mapping(bytes32 _disputeId => ArbitrationStatus _status) internal _disputeData;

constructor(IOracle _oracle) Module(_oracle) {}
constructor(IOracle _oracle) ModuleAccessController(_oracle) {}

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
Expand Down Expand Up @@ -61,7 +62,7 @@ contract ArbitratorModule is Module, IArbitratorModule {
if (_status <= IOracle.DisputeStatus.Escalated) revert ArbitratorModule_InvalidResolutionStatus();
_disputeData[_disputeId] = ArbitrationStatus.Resolved;

ORACLE.updateDisputeStatus(_request, _response, _dispute, _status);
ORACLE.updateDisputeStatus({_request: _request, _response: _response, _dispute: _dispute, _status: _status});

emit DisputeResolved(_dispute.requestId, _disputeId, _status);
}
Expand Down
Loading

0 comments on commit 822962a

Please sign in to comment.