diff --git a/package.json b/package.json index 3b374eeb..0a893bbe 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "package.json": "sort-package-json" }, "dependencies": { - "@defi-wonderland/prophet-core": "0.0.0-3afab791", + "@defi-wonderland/prophet-core": "0.0.0-823459fc", "@openzeppelin/contracts": "4.9.5", "solmate": "https://github.com/transmissions11/solmate.git#bfc9c25865a274a7827fea5abf6e4fb64fc64e6c" }, diff --git a/solidity/contracts/modules/accessControl/AccessControllerModule.sol b/solidity/contracts/modules/access/ModuleAccessController.sol similarity index 57% rename from solidity/contracts/modules/accessControl/AccessControllerModule.sol rename to solidity/contracts/modules/access/ModuleAccessController.sol index ad2a7fde..e2cd9c21 100644 --- a/solidity/contracts/modules/accessControl/AccessControllerModule.sol +++ b/solidity/contracts/modules/access/ModuleAccessController.sol @@ -1,11 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {AccessController} from '@defi-wonderland/prophet-core/solidity/contracts/AccessController.sol'; +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 AccessControllerModule is AccessController, Module { +abstract contract ModuleAccessController is IModuleAccessController, CommonAccessController, Module { constructor(IOracle _oracle) Module(_oracle) {} /** @@ -19,7 +21,6 @@ abstract contract AccessControllerModule is AccessController, Module { } /** - * // 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 @@ -28,4 +29,19 @@ abstract contract AccessControllerModule is AccessController, Module { function _defaultAccessControl() internal view returns (AccessControl memory _accessControl) { _accessControl = _defaultAccessControl(bytes('')); } + + modifier hasAccess( + address _accessModule, + bytes32 _typehash, + bytes memory _params, + AccessControl memory _accessControl + ) { + // Revert if sender is acting for a user without module approval + if (msg.sender != _accessControl.user && !ORACLE.isAccessModuleApproved(_accessControl.user, _accessModule)) { + revert ModuleAccessController_AccessModuleNotApproved(); + } + // todo: probably a change name is required here, something like `_ensureAccess`? + _hasAccess(_accessModule, _typehash, _params, _accessControl); + _; + } } diff --git a/solidity/contracts/modules/dispute/BondEscalationModule.sol b/solidity/contracts/modules/dispute/BondEscalationModule.sol index 090a07d6..08906b5f 100644 --- a/solidity/contracts/modules/dispute/BondEscalationModule.sol +++ b/solidity/contracts/modules/dispute/BondEscalationModule.sol @@ -7,10 +7,11 @@ import {FixedPointMathLib} from 'solmate/src/utils/FixedPointMathLib.sol'; import {IBondEscalationModule} from '../../../interfaces/modules/dispute/IBondEscalationModule.sol'; -import {_PLEDGE_AGAINST_DISPUTE_TYPEHASH, _PLEDGE_FOR_DISPUTE_TYPEHASH} from '../../utils/Typehash.sol'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; +import {ModuleAccessController} from '../access/ModuleAccessController.sol'; -contract BondEscalationModule is AccessControllerModule, IBondEscalationModule { +import {ModuleTypehash} from '../../utils/ModuleTypehash.sol'; + +contract BondEscalationModule is ModuleAccessController, IBondEscalationModule { /// @inheritdoc IBondEscalationModule mapping(bytes32 _requestId => mapping(address _pledger => uint256 pledges)) public pledgesForDispute; @@ -22,7 +23,7 @@ contract BondEscalationModule is AccessControllerModule, IBondEscalationModule { */ mapping(bytes32 _requestId => BondEscalation) internal _escalations; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { @@ -217,7 +218,12 @@ contract BondEscalationModule is AccessControllerModule, IBondEscalationModule { AccessControl calldata _accessControl ) external - hasAccess(_request.accessControlModule, _PLEDGE_FOR_DISPUTE_TYPEHASH, abi.encode(_request, _dispute), _accessControl) + hasAccess( + _request.accessModule, + ModuleTypehash._PLEDGE_FOR_DISPUTE_TYPEHASH, + abi.encode(_request, _dispute), + _accessControl + ) { bytes32 _disputeId = _getId(_dispute); RequestParameters memory _params = _pledgeChecks(_request, _dispute, true); @@ -245,8 +251,8 @@ contract BondEscalationModule is AccessControllerModule, IBondEscalationModule { ) external hasAccess( - _request.accessControlModule, - _PLEDGE_AGAINST_DISPUTE_TYPEHASH, + _request.accessModule, + ModuleTypehash._PLEDGE_AGAINST_DISPUTE_TYPEHASH, abi.encode(_request, _dispute), _accessControl ) diff --git a/solidity/contracts/modules/dispute/CircuitResolverModule.sol b/solidity/contracts/modules/dispute/CircuitResolverModule.sol index 80b6894a..c7d06d7b 100644 --- a/solidity/contracts/modules/dispute/CircuitResolverModule.sol +++ b/solidity/contracts/modules/dispute/CircuitResolverModule.sol @@ -7,13 +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'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; +import {ModuleAccessController} from '../access/ModuleAccessController.sol'; -contract CircuitResolverModule is AccessControllerModule, ICircuitResolverModule { +contract CircuitResolverModule is ModuleAccessController, ICircuitResolverModule { /// @notice Keeps track of the correct responses to requests mapping(bytes32 _requestId => bytes _correctResponse) internal _correctResponses; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { diff --git a/solidity/contracts/modules/dispute/RootVerificationModule.sol b/solidity/contracts/modules/dispute/RootVerificationModule.sol index e79874d9..24e164a6 100644 --- a/solidity/contracts/modules/dispute/RootVerificationModule.sol +++ b/solidity/contracts/modules/dispute/RootVerificationModule.sol @@ -6,9 +6,9 @@ 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'; +import {ModuleAccessController} from '../access/ModuleAccessController.sol'; -contract RootVerificationModule is AccessControllerModule, IRootVerificationModule { +contract RootVerificationModule is ModuleAccessController, IRootVerificationModule { using MerkleLib for MerkleLib.Tree; /** @@ -16,7 +16,7 @@ contract RootVerificationModule is AccessControllerModule, IRootVerificationModu */ mapping(bytes32 _requestId => bytes32 _correctRoot) internal _correctRoots; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { diff --git a/solidity/contracts/modules/resolution/ArbitratorModule.sol b/solidity/contracts/modules/resolution/ArbitratorModule.sol index 9ace482c..f970df6b 100644 --- a/solidity/contracts/modules/resolution/ArbitratorModule.sol +++ b/solidity/contracts/modules/resolution/ArbitratorModule.sol @@ -6,16 +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'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; - -contract ArbitratorModule is AccessControllerModule, IArbitratorModule { +contract ArbitratorModule is ModuleAccessController, IArbitratorModule { /** * @notice The status of all disputes */ mapping(bytes32 _disputeId => ArbitrationStatus _status) internal _disputeData; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { diff --git a/solidity/contracts/modules/resolution/BondEscalationResolutionModule.sol b/solidity/contracts/modules/resolution/BondEscalationResolutionModule.sol index 661a0c6c..63002a90 100644 --- a/solidity/contracts/modules/resolution/BondEscalationResolutionModule.sol +++ b/solidity/contracts/modules/resolution/BondEscalationResolutionModule.sol @@ -16,15 +16,11 @@ import {IResolutionModule} from import {IBondEscalationResolutionModule} from '../../../interfaces/modules/resolution/IBondEscalationResolutionModule.sol'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; +import {ModuleAccessController} from '../access/ModuleAccessController.sol'; -import { - _CLAIM_PLEDGE_TYPEHASH, - _PLEDGE_AGAINST_DISPUTE_TYPEHASH, - _PLEDGE_FOR_DISPUTE_TYPEHASH -} from '../../utils/Typehash.sol'; +import {ModuleTypehash} from '../../utils/ModuleTypehash.sol'; -contract BondEscalationResolutionModule is AccessControllerModule, IBondEscalationResolutionModule { +contract BondEscalationResolutionModule is ModuleAccessController, IBondEscalationResolutionModule { using SafeERC20 for IERC20; /// @inheritdoc IBondEscalationResolutionModule @@ -42,7 +38,7 @@ contract BondEscalationResolutionModule is AccessControllerModule, IBondEscalati /// @inheritdoc IBondEscalationResolutionModule mapping(bytes32 _disputeId => mapping(address _pledger => uint256 pledges)) public pledgesAgainstDispute; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { @@ -74,8 +70,8 @@ contract BondEscalationResolutionModule is AccessControllerModule, IBondEscalati ) external hasAccess( - _request.accessControlModule, - _PLEDGE_FOR_DISPUTE_TYPEHASH, + _request.accessModule, + ModuleTypehash._PLEDGE_FOR_DISPUTE_TYPEHASH, abi.encode(_request, _dispute, _pledgeAmount), _accessControl ) @@ -98,8 +94,8 @@ contract BondEscalationResolutionModule is AccessControllerModule, IBondEscalati ) external hasAccess( - _request.accessControlModule, - _PLEDGE_AGAINST_DISPUTE_TYPEHASH, + _request.accessModule, + ModuleTypehash._PLEDGE_AGAINST_DISPUTE_TYPEHASH, abi.encode(_request, _dispute, _pledgeAmount), _accessControl ) @@ -164,7 +160,12 @@ contract BondEscalationResolutionModule is AccessControllerModule, IBondEscalati AccessControl calldata _accessControl ) external - hasAccess(_request.accessControlModule, _CLAIM_PLEDGE_TYPEHASH, abi.encode(_request, _dispute), _accessControl) + hasAccess( + _request.accessModule, + ModuleTypehash._CLAIM_PLEDGE_TYPEHASH, + abi.encode(_request, _dispute), + _accessControl + ) { bytes32 _disputeId = _validateDispute(_request, _dispute); Escalation storage _escalation = escalations[_disputeId]; diff --git a/solidity/contracts/modules/resolution/ERC20ResolutionModule.sol b/solidity/contracts/modules/resolution/ERC20ResolutionModule.sol index ebbb46a7..9e187af0 100644 --- a/solidity/contracts/modules/resolution/ERC20ResolutionModule.sol +++ b/solidity/contracts/modules/resolution/ERC20ResolutionModule.sol @@ -11,10 +11,10 @@ import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle import {IERC20ResolutionModule} from '../../../interfaces/modules/resolution/IERC20ResolutionModule.sol'; -import {_CAST_VOTE_TYPEHASH, _CLAIM_VOTE_TYPEHASH} from '../../utils/Typehash.sol'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; +import {ModuleTypehash} from '../../utils/ModuleTypehash.sol'; +import {ModuleAccessController} from '../access/ModuleAccessController.sol'; -contract ERC20ResolutionModule is AccessControllerModule, IERC20ResolutionModule { +contract ERC20ResolutionModule is ModuleAccessController, IERC20ResolutionModule { using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; @@ -29,7 +29,7 @@ contract ERC20ResolutionModule is AccessControllerModule, IERC20ResolutionModule */ mapping(bytes32 _disputeId => EnumerableSet.AddressSet _votersSet) internal _voters; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { @@ -61,8 +61,8 @@ contract ERC20ResolutionModule is AccessControllerModule, IERC20ResolutionModule ) external hasAccess( - _request.accessControlModule, - _CAST_VOTE_TYPEHASH, + _request.accessModule, + ModuleTypehash._CAST_VOTE_TYPEHASH, abi.encode(_request, _dispute, _numberOfVotes, _numberOfVotes), _accessControl ) @@ -140,7 +140,7 @@ contract ERC20ResolutionModule is AccessControllerModule, IERC20ResolutionModule AccessControl calldata _accessControl ) external - hasAccess(_request.accessControlModule, _CLAIM_VOTE_TYPEHASH, abi.encode(_request, _dispute), _accessControl) + hasAccess(_request.accessModule, ModuleTypehash._CLAIM_VOTE_TYPEHASH, abi.encode(_request, _dispute), _accessControl) { bytes32 _disputeId = _validateDispute(_request, _dispute); Escalation memory _escalation = escalations[_disputeId]; diff --git a/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol b/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol index 7dd0a173..d71705ea 100644 --- a/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol +++ b/solidity/contracts/modules/resolution/PrivateERC20ResolutionModule.sol @@ -6,14 +6,14 @@ import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; -import {_COMMIT_VOTE_TYPEHASH, _REVEAL_VOTE_TYPEHASH} from '../../utils/Typehash.sol'; +import {ModuleTypehash} from '../../utils/ModuleTypehash.sol'; import {IModule, Module} from '@defi-wonderland/prophet-core/solidity/contracts/Module.sol'; import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; import {IPrivateERC20ResolutionModule} from '../../../interfaces/modules/resolution/IPrivateERC20ResolutionModule.sol'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; +import {ModuleAccessController} from '../access/ModuleAccessController.sol'; -contract PrivateERC20ResolutionModule is AccessControllerModule, IPrivateERC20ResolutionModule { +contract PrivateERC20ResolutionModule is ModuleAccessController, IPrivateERC20ResolutionModule { using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; @@ -28,7 +28,7 @@ contract PrivateERC20ResolutionModule is AccessControllerModule, IPrivateERC20Re */ mapping(bytes32 _disputeId => EnumerableSet.AddressSet _votersSet) internal _voters; - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} + constructor(IOracle _oracle) ModuleAccessController(_oracle) {} /// @inheritdoc IModule function moduleName() external pure returns (string memory _moduleName) { @@ -60,8 +60,8 @@ contract PrivateERC20ResolutionModule is AccessControllerModule, IPrivateERC20Re ) external hasAccess( - _request.accessControlModule, - _COMMIT_VOTE_TYPEHASH, + _request.accessModule, + ModuleTypehash._COMMIT_VOTE_TYPEHASH, abi.encode(_request, _dispute, _commitment), _accessControl ) @@ -94,8 +94,8 @@ contract PrivateERC20ResolutionModule is AccessControllerModule, IPrivateERC20Re ) external hasAccess( - _request.accessControlModule, - _REVEAL_VOTE_TYPEHASH, + _request.accessModule, + ModuleTypehash._REVEAL_VOTE_TYPEHASH, abi.encode(_request, _dispute, _numberOfVotes, _salt), _accessControl ) diff --git a/solidity/contracts/modules/response/BondedResponseModule.sol b/solidity/contracts/modules/response/BondedResponseModule.sol index c552c1aa..cb52b7cb 100644 --- a/solidity/contracts/modules/response/BondedResponseModule.sol +++ b/solidity/contracts/modules/response/BondedResponseModule.sol @@ -5,10 +5,9 @@ import {IModule, Module} from '@defi-wonderland/prophet-core/solidity/contracts/ import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; import {IBondedResponseModule} from '../../../interfaces/modules/response/IBondedResponseModule.sol'; -import {AccessControllerModule} from '../accessControl/AccessControllerModule.sol'; -contract BondedResponseModule is AccessControllerModule, IBondedResponseModule { - constructor(IOracle _oracle) AccessControllerModule(_oracle) {} +contract BondedResponseModule is Module, IBondedResponseModule { + constructor(IOracle _oracle) Module(_oracle) {} /// @inheritdoc IModule function moduleName() public pure returns (string memory _moduleName) { diff --git a/solidity/contracts/utils/ModuleTypehash.sol b/solidity/contracts/utils/ModuleTypehash.sol new file mode 100644 index 00000000..37f44ec3 --- /dev/null +++ b/solidity/contracts/utils/ModuleTypehash.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +library ModuleTypehash { + bytes32 internal constant _PLEDGE_FOR_DISPUTE_TYPEHASH = + keccak256('pledgeForDispute(Request _request, Dispute _dispute,IAccessController.AccessControl _accessControl)'); + + bytes32 internal constant _PLEDGE_AGAINST_DISPUTE_TYPEHASH = + keccak256('pledgeAgainstDispute(Request _request,Dispute _dispute,IAccessController.AccessControl _accessControl)'); + + bytes32 internal constant _CLAIM_PLEDGE_TYPEHASH = + keccak256('claimPledge(Request _request,Dispute _dispute,AccessControl _accessControl)'); + + bytes32 internal constant _CLAIM_VOTE_TYPEHASH = + keccak256('claimVote(Request _request,Dispute _dispute,AccessControl _accessControl)'); + + bytes32 internal constant _CAST_VOTE_TYPEHASH = + keccak256('castVote(Request _request,Dispute _dispute,uint256 _numberOfVotes,AccessControl _accessControl)'); + + bytes32 internal constant _COMMIT_VOTE_TYPEHASH = + keccak256('commitVote(Request _request,Dispute _dispute,bytes32 _commitment,AccessControl _accessControl)'); + + bytes32 internal constant _REVEAL_VOTE_TYPEHASH = keccak256( + 'revealVote(Request _request,Dispute _dispute,uint256 _numberOfVotes,bytes32 _salt,AccessControl _accessControl)' + ); +} diff --git a/solidity/contracts/utils/Typehash.sol b/solidity/contracts/utils/Typehash.sol deleted file mode 100644 index a64ddead..00000000 --- a/solidity/contracts/utils/Typehash.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -bytes32 constant _PLEDGE_FOR_DISPUTE_TYPEHASH = - keccak256('pledgeForDispute(Request _request, Dispute _dispute,IAccessController.AccessControl _accessControl)'); - -bytes32 constant _PLEDGE_AGAINST_DISPUTE_TYPEHASH = - keccak256('pledgeAgainstDispute(Request _request,Dispute _dispute,IAccessController.AccessControl _accessControl)'); - -bytes32 constant _CLAIM_PLEDGE_TYPEHASH = - keccak256('claimPledge(Request _request,Dispute _dispute,AccessControl _accessControl)'); - -bytes32 constant _CLAIM_VOTE_TYPEHASH = - keccak256('claimVote(Request _request,Dispute _dispute,AccessControl _accessControl)'); - -bytes32 constant _CAST_VOTE_TYPEHASH = - keccak256('castVote(Request _request,Dispute _dispute,uint256 _numberOfVotes,AccessControl _accessControl)'); -bytes32 constant _COMMIT_VOTE_TYPEHASH = - keccak256('commitVote(Request _request,Dispute _dispute,bytes32 _commitment,AccessControl _accessControl)'); -bytes32 constant _REVEAL_VOTE_TYPEHASH = keccak256( - 'revealVote(Request _request,Dispute _dispute,uint256 _numberOfVotes,bytes32 _salt,AccessControl _accessControl)' -); diff --git a/solidity/interfaces/modules/access/IModuleAccessController.sol b/solidity/interfaces/modules/access/IModuleAccessController.sol new file mode 100644 index 00000000..1713b7de --- /dev/null +++ b/solidity/interfaces/modules/access/IModuleAccessController.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IAccessController} from '@defi-wonderland/prophet-core/solidity/interfaces/IAccessController.sol'; + +/** + * @title Module Access Controller Interface + * @notice Interface for the module access controller + */ +interface IModuleAccessController is IAccessController { + /*/////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /*/////////////////////////////////////////////////////////////// + STRUCTS + //////////////////////////////////////////////////////////////*/ + + /*/////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Thrown when user has not approved the access module + */ + error ModuleAccessController_AccessModuleNotApproved(); + + /*/////////////////////////////////////////////////////////////// + VARIABLES + //////////////////////////////////////////////////////////////*/ + + /*/////////////////////////////////////////////////////////////// + LOGIC + //////////////////////////////////////////////////////////////*/ +} diff --git a/solidity/test/integration/IntegrationBase.sol b/solidity/test/integration/IntegrationBase.sol index cb86d3dc..21e0edbc 100644 --- a/solidity/test/integration/IntegrationBase.sol +++ b/solidity/test/integration/IntegrationBase.sol @@ -6,8 +6,9 @@ pragma solidity ^0.8.19; import {console} from 'forge-std/console.sol'; import { - AccessController, IAccessController -} from '@defi-wonderland/prophet-core/solidity/contracts/AccessController.sol'; + CommonAccessController, + IAccessController +} from '@defi-wonderland/prophet-core/solidity/contracts/CommonAccessController.sol'; import {IOracle, Oracle} from '@defi-wonderland/prophet-core/solidity/contracts/Oracle.sol'; import {IDisputeModule} from '@defi-wonderland/prophet-core/solidity/interfaces/modules/dispute/IDisputeModule.sol'; import {IFinalityModule} from '@defi-wonderland/prophet-core/solidity/interfaces/modules/finality/IFinalityModule.sol'; diff --git a/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol b/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol index 8927bfa7..1adf211a 100644 --- a/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol +++ b/solidity/test/unit/modules/dispute/BondEscalationModule.t.sol @@ -8,9 +8,8 @@ import {Helpers} from '../../../utils/Helpers.sol'; import {IAccessController} from '@defi-wonderland/prophet-core/solidity/interfaces/IAccessController.sol'; import {IModule} from '@defi-wonderland/prophet-core/solidity/interfaces/IModule.sol'; -import {IOracle} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; -import {IAccessControlModule} from - '@defi-wonderland/prophet-core/solidity/interfaces/modules/accessControl/IAccessControlModule.sol'; +import {IOracle, IOracleAccessController} from '@defi-wonderland/prophet-core/solidity/interfaces/IOracle.sol'; +import {IAccessModule} from '@defi-wonderland/prophet-core/solidity/interfaces/modules/access/IAccessModule.sol'; import {ValidatorLib} from '@defi-wonderland/prophet-core/solidity/libraries/ValidatorLib.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import {Strings} from '@openzeppelin/contracts/utils/Strings.sol'; @@ -19,11 +18,10 @@ import { BondEscalationModule, IBondEscalationModule } from '../../../../contracts/modules/dispute/BondEscalationModule.sol'; -import { - _PLEDGE_AGAINST_DISPUTE_TYPEHASH, _PLEDGE_FOR_DISPUTE_TYPEHASH -} from '../../../../contracts/utils/Typehash.sol'; +import {ModuleTypehash} from '../../../../contracts/utils/ModuleTypehash.sol'; import {IAccountingExtension} from '../../../../interfaces/extensions/IAccountingExtension.sol'; import {IBondEscalationAccounting} from '../../../../interfaces/extensions/IBondEscalationAccounting.sol'; +import {IModuleAccessController} from '../../../../interfaces/modules/access/IModuleAccessController.sol'; /** * @dev Harness to set an entry in the requestData mapping, without triggering setup request hooks @@ -1501,14 +1499,14 @@ contract BondEscalationModule_Unit_SettleBondEscalation is BaseTest { } contract BondEscalationModule_Unit_AccessControl is BaseTest { - address internal _accessControlModule = makeAddr('accessControlModule'); + address internal _accessModule = makeAddr('accessModule'); function setUp() public override { - mockRequest.accessControlModule = _accessControlModule; + mockRequest.accessModule = _accessModule; super.setUp(); } - function test_pledgeForDispute_accessControl( + function test_pledgeForDispute_accessControl_granted( address _caller, address _user, bytes memory _data, @@ -1533,20 +1531,27 @@ contract BondEscalationModule_Unit_AccessControl is BaseTest { uint256 _numAgainstPledgers = _numForPledgers + 1; _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); + // expect a call checking whether the access module has been approved by the user + _mockAndExpect( + address(oracle), + abi.encodeCall(IOracleAccessController.isAccessModuleApproved, (_user, _accessModule)), + abi.encode(true) + ); + IAccessController.AccessControl memory _accessControl = IAccessController.AccessControl({user: _user, data: _data}); // Mock and expect call to access control module vm.mockCall( - _accessControlModule, + _accessModule, abi.encodeCall( - IAccessControlModule.hasAccess, + IAccessModule.hasAccess, ( abi.encode( - IAccessControlModule.AccessControlParameters({ + IAccessModule.AccessControlParameters({ sender: _caller, - typehash: _PLEDGE_FOR_DISPUTE_TYPEHASH, - params: abi.encode(mockRequest, _dispute), - accessControl: _accessControl + accessControl: _accessControl, + typehash: ModuleTypehash._PLEDGE_FOR_DISPUTE_TYPEHASH, + typehashParams: abi.encode(mockRequest, _dispute) }) ) ) @@ -1566,7 +1571,29 @@ contract BondEscalationModule_Unit_AccessControl is BaseTest { bondEscalationModule.pledgeForDispute(mockRequest, _dispute, _accessControl); } - function test_pledgeAgainstDispute_accessControl( + function test_pledgeForDispute_accessControl_notGranted( + address _caller, + address _user, + bytes memory _data, + IBondEscalationModule.RequestParameters memory _params + ) public assumeFuzzable(address(_params.accountingExtension)) { + vm.assume(_caller != _user); + + // mock and expect a call checking whether the access module has been approved by the user + _mockAndExpect( + address(oracle), + abi.encodeCall(IOracleAccessController.isAccessModuleApproved, (_user, _accessModule)), + abi.encode(false) + ); + + IAccessController.AccessControl memory _accessControl = IAccessController.AccessControl({user: _user, data: _data}); + + vm.expectRevert(IModuleAccessController.ModuleAccessController_AccessModuleNotApproved.selector); + vm.prank(_caller); + bondEscalationModule.pledgeForDispute(mockRequest, mockDispute, _accessControl); + } + + function test_pledgeAgainstDispute_accessControl_granted( address _caller, address _user, bytes memory _data, @@ -1591,6 +1618,13 @@ contract BondEscalationModule_Unit_AccessControl is BaseTest { _setBondEscalation(_requestId, _numForPledgers, _numAgainstPledgers); + // todo: extract to helper when we add tests for the other access controlled functions + _mockAndExpect( + address(oracle), + abi.encodeCall(IOracleAccessController.isAccessModuleApproved, (_user, _accessModule)), + abi.encode(true) + ); + _mockAndExpect( address(_params.accountingExtension), abi.encodeCall( @@ -1603,16 +1637,16 @@ contract BondEscalationModule_Unit_AccessControl is BaseTest { // Mock and expect call to access control module vm.mockCall( - _accessControlModule, + _accessModule, abi.encodeCall( - IAccessControlModule.hasAccess, + IAccessModule.hasAccess, ( abi.encode( - IAccessControlModule.AccessControlParameters({ + IAccessModule.AccessControlParameters({ sender: _caller, - typehash: _PLEDGE_AGAINST_DISPUTE_TYPEHASH, - params: abi.encode(mockRequest, _dispute), - accessControl: _accessControl + accessControl: _accessControl, + typehash: ModuleTypehash._PLEDGE_AGAINST_DISPUTE_TYPEHASH, + typehashParams: abi.encode(mockRequest, _dispute) }) ) ) diff --git a/solidity/test/utils/Helpers.sol b/solidity/test/utils/Helpers.sol index b92a301e..cd3d2add 100644 --- a/solidity/test/utils/Helpers.sol +++ b/solidity/test/utils/Helpers.sol @@ -13,7 +13,7 @@ contract Helpers is DSTestPlus, TestConstants { // Mock objects IOracle.Request public mockRequest = IOracle.Request({ - accessControlModule: address(0), + accessModule: address(0), requestModule: address(0), responseModule: address(0), disputeModule: address(0), diff --git a/yarn.lock b/yarn.lock index e9f077bd..ac0d62e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -193,10 +193,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@defi-wonderland/prophet-core@0.0.0-3afab791": - version "0.0.0-3afab791" - resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-3afab791.tgz#e9e40fabf2ae50b1edbfca806d4159b29b64daec" - integrity sha512-0zvdUCehT2yMDzRPG60XUlMIwSESxeVqaWwVswnDlr3G4ISYhFl1kZvg4fShJTbB9pu9G9tfj19/zFXt0BFaHw== +"@defi-wonderland/prophet-core@0.0.0-823459fc": + version "0.0.0-823459fc" + resolved "https://registry.yarnpkg.com/@defi-wonderland/prophet-core/-/prophet-core-0.0.0-823459fc.tgz#a48f7b35899968468f37f5c9eb2c67a1c8a823ff" + integrity sha512-lqTFlKFUwt4yjBGnSUJf9PwNQE6MP4KJHUSCov2+yxJCkKHKzFlYQ7M25dAdebiwa6Hfd+XHQfLx1bzff6mM6Q== "@defi-wonderland/solidity-utils@0.0.0-3e9c8e8b": version "0.0.0-3e9c8e8b"