Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: access control #74

Merged
merged 52 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
522cb38
feat: use access control in all the necessary functions
xorsal Oct 23, 2024
3dc123e
feat: update interfaces
xorsal Oct 23, 2024
ed39f02
test: update integration tests
xorsal Oct 23, 2024
88eaddf
test: update unit tests
xorsal Oct 23, 2024
495fde5
feat: add typehash constants
xorsal Oct 23, 2024
42cb077
feat: run linter
xorsal Oct 24, 2024
73688ac
feat: add AccessControllerModule
xorsal Oct 24, 2024
f8e7113
feat: pass params to hasAccess modifier
xorsal Oct 24, 2024
b3731d3
feat: update typehashes
xorsal Oct 24, 2024
5796f29
feat: releaseUnutilizedResponse does not require access control
xorsal Oct 24, 2024
1ebcfc9
feat: update releaseUnutilizedResponse calls
xorsal Oct 24, 2024
5398e63
feat: add _defaultAccessControl to AccessControllerModule
xorsal Oct 25, 2024
f0b55fc
feat: remove accessControl param from unnecesary functions
xorsal Oct 25, 2024
463bfd6
test: use access control in corresponding functions
xorsal Oct 25, 2024
08fe1ca
docs: add access control param to natspec
xorsal Oct 25, 2024
2b28b57
docs: add natspec for _defaultAccessControl
xorsal Oct 25, 2024
a37968c
docs: add missing natspec for onlyAuthorizedCaller modifier
xorsal Oct 25, 2024
7606748
test: replace mockAC for actual access control
xorsal Oct 30, 2024
384e297
test: use pranked caller in _createAccessControl
xorsal Oct 30, 2024
7c76a8c
feat: use access control in finalize and escalate
xorsal Oct 30, 2024
cb76d9a
chore: remove unused import
xorsal Oct 30, 2024
21cd67e
feat: revealVote is now external
xorsal Oct 30, 2024
137d27e
test: add access control unit test for BondEscalationModule
xorsal Oct 30, 2024
124764a
feat: add unit for access controlled function
xorsal Oct 30, 2024
dbadc59
chore: remove comment
xorsal Oct 30, 2024
eae4ea1
feat: replace usage of msg.sender, instead use accessControl.user
xorsal Oct 31, 2024
618cc36
refactor: rework local variables to avoid stack to deep error
xorsal Oct 31, 2024
28f44e9
chore: lint
xorsal Oct 31, 2024
5f875e4
chore: run linter
xorsal Oct 31, 2024
ea1d17f
feat: declare local variable instead of using access control
xorsal Nov 1, 2024
d526ff9
feat: update circuit resolve module
xorsal Nov 2, 2024
b99f8c1
feat: add another defaultAccessControl fn
xorsal Nov 4, 2024
5fa2a04
docs: review the _isModule check
xorsal Nov 4, 2024
f65effd
test: add vm.skip(false) in a few tests to revisit them later
xorsal Nov 4, 2024
cb2a558
feat: update calldata for memory
xorsal Nov 4, 2024
ff81b35
test: resolveDispute now uses access control
xorsal Nov 4, 2024
f0b77fb
feat: resolveDispute in MockAtomicArbitrator
xorsal Nov 4, 2024
cf061e2
chore: fix conflict
xorsal Nov 4, 2024
a0d185e
Merge branch 'dev' into feat/access-control
xorsal Nov 4, 2024
879dc9d
chore: update prophet-core to canary release
xorsal Nov 4, 2024
0f5367f
chore: update yarn.lock
xorsal Nov 4, 2024
71c6b11
chore: remove commented line, uncomment snippet
xorsal Nov 5, 2024
0541655
feat: access module (#77)
xorsal Nov 10, 2024
381a9c5
Merge branch 'dev' into feat/access-control
gas1cent Nov 12, 2024
15061db
fix: an extra space
gas1cent Nov 12, 2024
78dd38d
refactor: unnecessary `AccessControl` in `IArbitrator`
gas1cent Nov 12, 2024
4507e3e
test: access control in bond escalation module tests
gas1cent Nov 12, 2024
a57e89d
fix: stack too deep
gas1cent Nov 12, 2024
b863c5e
chore: remove addressed todos
xorsal Nov 12, 2024
ebc91e8
feat: update prophet-core
gas1cent Nov 12, 2024
0977b85
feat: avoid external calls if access control user is the sender
gas1cent Nov 12, 2024
d5e88d5
feat: remove Aderyn report
gas1cent Nov 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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-3afab791",
"@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
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {AccessController} from '@defi-wonderland/prophet-core/solidity/contracts/AccessController.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 AccessControllerModule is AccessController, Module {
constructor(IOracle _oracle) Module(_oracle) {}
0xJabberwock marked this conversation as resolved.
Show resolved Hide resolved

/**
* @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});
}

/**
* // todo: update name to _selfAccessControl
* @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) {
ashitakah marked this conversation as resolved.
Show resolved Hide resolved
_accessControl = _defaultAccessControl(bytes(''));
}
}
57 changes: 43 additions & 14 deletions solidity/contracts/modules/dispute/BondEscalationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import {FixedPointMathLib} from 'solmate/src/utils/FixedPointMathLib.sol';

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

contract BondEscalationModule is Module, IBondEscalationModule {
import {_PLEDGE_AGAINST_DISPUTE_TYPEHASH, _PLEDGE_FOR_DISPUTE_TYPEHASH} from '../../utils/Typehash.sol';
import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol';

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

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

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

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
Expand Down Expand Up @@ -61,7 +64,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());
0xJabberwock marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -208,39 +211,62 @@ 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.accessControlModule, _PLEDGE_FOR_DISPUTE_TYPEHASH, abi.encode(_request, _dispute), _accessControl)
{
0xJabberwock marked this conversation as resolved.
Show resolved Hide resolved
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.accessControlModule,
_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 +300,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 {AccessControllerModule} from '../accessControl/AccessControllerModule.sol';

contract CircuitResolverModule is AccessControllerModule, 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) AccessControllerModule(_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 {AccessControllerModule} from '../accessControl/AccessControllerModule.sol';

contract RootVerificationModule is Module, IRootVerificationModule {
contract RootVerificationModule is AccessControllerModule, 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) AccessControllerModule(_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
10 changes: 6 additions & 4 deletions solidity/contracts/modules/resolution/ArbitratorModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,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';

contract ArbitratorModule is Module, IArbitratorModule {
import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol';

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

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

/// @inheritdoc IModule
function moduleName() external pure returns (string memory _moduleName) {
Expand Down Expand Up @@ -41,7 +43,7 @@ contract ArbitratorModule is Module, IArbitratorModule {
if (_params.arbitrator == address(0)) revert ArbitratorModule_InvalidArbitrator();

_disputeData[_disputeId] = ArbitrationStatus.Active;
IArbitrator(_params.arbitrator).resolve(_request, _response, _dispute);
IArbitrator(_params.arbitrator).resolve(_request, _response, _dispute, _defaultAccessControl());

emit ResolutionStarted(_dispute.requestId, _disputeId);
}
Expand All @@ -61,7 +63,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
Loading