Access Controls

The Access Control system implements granular, function-level permissions across all contracts of Cap. It provides a sophisticated role-based access control mechanism that allows precise management of who can call specific functions on specific contracts, building on OpenZeppelin's AccessControlEnumberable Integration.

Roles are managed by the Access Control admin, currently set to Cap's multisig address

Mechanics

  • Each function on each contract has its own unique 32-byte role ID

  • The role ID is generated by combining:

    • The function selector (first 4 bytes of the function signature)

    • The contract address

  • Permissions can be granted/revoked at the function level

  • Contracts inherit access control through the Access abstract contract and uses the checkAccess modifier on protected functions

Architecture

  • Access.sol: Inheritable abstract contract that provides the base functionality for access control

  • AccessControl.sol: Central contract that implements the access control logic

Access Control

Core Functions

grantAccess: Grants permission to call a specific function on a specific contract

function grantAccess(bytes4 _selector, address _contract, address _address) external
  • _selector: Function selector (4-byte identifier) of the method to grant access to

  • _contract: Address of the contract containing the method

  • _address: Address to grant access to

revokeAccess: Revokes permission to call a specific function on a specific contract

function revokeAccess(bytes4 _selector, address _contract, address _address) external
  • _selector: Function selector (4-byte identifier) of the method to revoke access from

  • _contract: Address of the contract containing the method

  • _address: Address to revoke access from

checkAccess: Verifies if an address has permission to call a specific function

function checkAccess(bytes4 _selector, address _contract, address _caller) external view returns (bool hasAccess)
  • Returns: True if access is granted, false otherwise

When a access controlled function is called, the checkAccess modifier calls _checkRole with the function's selector, contract and message sender.

role: Gets the role identifier for a specific function selector on a contract

function role(bytes4 _selector, address _contract) public pure returns (bytes32 roleId)
  • _selector: Function selector (4-byte identifier) of the method

  • _contract: Address of the contract containing the method

  • Returns: Unique role identifier derived from selector and contract address

Role Hierarchy

DEFAULT_ADMIN_ROLE
├── access_control_admin
│   ├── oracle_admin
│   ├── rate_oracle_admin
│   ├── lender_admin
│   ├── delegation_admin
│   └── vault_config_admin
└── Emergency Admin
  1. DEFAULT_ADMIN_ROLE: Can upgrade the AccessControl contract

  2. Access Management Roles: Can grant/revoke permissions

  3. Function-Specific Roles: Control access to individual functions

Permission Types

1. Administrative Permissions

  • Contract upgrades (bytes4(0))

  • Access management (grantAccess, revokeAccess)

2. Operational Permissions

  • Vault operations (borrow, repay, mint, burn)

  • Oracle managements (setOracleData, setStaleness, setRates)

  • Asset management (addAsset, removeAsset, pauseAsset, setReserve)

  • Fee Auctions (setDuration, setStartPrice ,setPaymentToken)

  • Delegations ( addAgent, modifyAgent ,registerNetwork)

3. Emergency Permissions

  • Protocol pause (pauseProtocol, unpauseProtocol)

  • Emergency functions (emergencyWithdraw, rescueERC20)

Last updated