Secure Smart Contract library for Solidity with upgradeable implementations of standards like ERC20 and ERC721, flexible role-based permissioning schemes, and reusable components for building custom contracts and complex decentralized systems.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive permission management systems for smart contracts, including role-based access control, ownership patterns, and advanced access management with time-based operations.
The AccessControl system provides flexible role-based permissions where roles can be granted and revoked dynamically.
/**
* @dev Role-based access control mechanism
*/
abstract contract AccessControlUpgradeable {
function __AccessControl_init() internal onlyInitializing;
/**
* @dev Returns true if account has been granted role
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls role
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants role to account. Caller must have admin role
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes role from account. Caller must have admin role
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes role from calling account
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
/**
* @dev Modifier that checks that account has specific role
*/
modifier onlyRole(bytes32 role);
// Default admin role (0x00)
bytes32 constant DEFAULT_ADMIN_ROLE = 0x00;
}
// Custom errors
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
error AccessControlBadConfirmation();
// Events
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);Usage Example:
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
contract MyContract is AccessControlUpgradeable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
function initialize(address defaultAdmin) initializer public {
__AccessControl_init();
_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
}
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
// Minting logic
}
}Extended access control with enhanced default administration features including time delays for admin changes.
/**
* @dev Extension with enhanced default admin functionality
*/
abstract contract AccessControlDefaultAdminRulesUpgradeable {
function __AccessControlDefaultAdminRules_init(uint48 initialDelay, address initialDefaultAdmin) internal onlyInitializing;
/**
* @dev Returns the current default admin
*/
function defaultAdmin() external view returns (address);
/**
* @dev Returns the pending default admin and its schedule
*/
function pendingDefaultAdmin() external view returns (address newAdmin, uint48 schedule);
/**
* @dev Returns the current delay for default admin changes
*/
function defaultAdminDelay() external view returns (uint48);
/**
* @dev Returns the pending delay and its schedule
*/
function pendingDefaultAdminDelay() external view returns (uint48 newDelay, uint48 schedule);
/**
* @dev Initiates a default admin transfer with delay
*/
function beginDefaultAdminTransfer(address newAdmin) external;
/**
* @dev Accepts the pending default admin transfer
*/
function acceptDefaultAdminTransfer() external;
/**
* @dev Changes the default admin delay
*/
function changeDefaultAdminDelay(uint48 newDelay) external;
/**
* @dev Cancels a pending default admin delay change
*/
function rollbackDefaultAdminDelay() external;
}Access control extension that allows enumeration of role members.
/**
* @dev Extension that allows enumerating the members of each role
*/
abstract contract AccessControlEnumerableUpgradeable {
function __AccessControlEnumerable_init() internal onlyInitializing;
/**
* @dev Returns one of the accounts that have role. index must be between 0 and getRoleMemberCount
*/
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
/**
* @dev Returns the number of accounts that have role
*/
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}Traditional single-owner access control pattern.
/**
* @dev Contract module providing basic ownership functionality
*/
abstract contract OwnableUpgradeable {
function __Ownable_init(address initialOwner) internal onlyInitializing;
/**
* @dev Returns the address of the current owner
*/
function owner() external view returns (address);
/**
* @dev Transfers ownership to a new account
*/
function transferOwnership(address newOwner) external onlyOwner;
/**
* @dev Leaves the contract without owner (renounces ownership)
*/
function renounceOwnership() external onlyOwner;
/**
* @dev Throws if called by any account other than the owner
*/
modifier onlyOwner();
}
// Custom errors
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
// Events
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);Enhanced ownership pattern that requires new owner to accept ownership to prevent accidental transfers.
/**
* @dev Extension of Ownable that adds a two-step ownership transfer
*/
abstract contract Ownable2StepUpgradeable {
function __Ownable2Step_init(address initialOwner) internal onlyInitializing;
/**
* @dev Returns the address of the pending owner
*/
function pendingOwner() external view returns (address);
/**
* @dev Transfers ownership to a new account (two-step process)
*/
function transferOwnership(address newOwner) external override onlyOwner;
/**
* @dev The new owner accepts the ownership transfer
*/
function acceptOwnership() external;
}
// Events
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);Advanced access control system with fine-grained permissions and scheduling.
/**
* @dev AccessManager is a central contract for access control
*/
contract AccessManagerUpgradeable {
function __AccessManager_init(address initialAdmin) internal onlyInitializing;
/**
* @dev Check if caller can call target with selector
*/
function canCall(address caller, address target, bytes4 selector) external view returns (bool immediate, uint32 delay);
/**
* @dev Grant role to account with execution delay
*/
function grantRole(uint64 roleId, address account, uint32 executionDelay) external;
/**
* @dev Revoke role from account
*/
function revokeRole(uint64 roleId, address account) external;
/**
* @dev Set which role can call specific functions
*/
function setTargetFunctionRole(address target, bytes4[] calldata selectors, uint64 roleId) external;
/**
* @dev Schedule an operation for future execution
*/
function schedule(address target, bytes calldata data, uint48 when) external returns (bytes32);
/**
* @dev Execute a scheduled operation
*/
function execute(address target, bytes calldata data) external payable returns (bytes32);
/**
* @dev Cancel a scheduled operation
*/
function cancel(address caller, address target, bytes calldata data) external returns (bytes32);
}Contract base for integration with AccessManager.
/**
* @dev This contract module allows children to restrict access to specific functions
*/
abstract contract AccessManagedUpgradeable {
function __AccessManaged_init(address initialAuthority) internal onlyInitializing;
/**
* @dev Returns the current authority
*/
function authority() external view returns (address);
/**
* @dev Transfers control to a new authority
*/
function setAuthority(address newAuthority) external restricted;
/**
* @dev Returns true if the function is being executed by the manager during a scheduled operation
*/
function isConsumingScheduledOp() external view returns (bytes4);
/**
* @dev Restricts access to the calling account
*/
modifier restricted();
}contract MyToken is ERC20Upgradeable, AccessControlUpgradeable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
function initialize(address defaultAdmin, address minter) initializer public {
__ERC20_init("MyToken", "MTK");
__AccessControl_init();
_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
_grantRole(MINTER_ROLE, minter);
}
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
}function setupRoles() external onlyRole(DEFAULT_ADMIN_ROLE) {
// Create manager role that can grant minter role
_setRoleAdmin(MINTER_ROLE, MANAGER_ROLE);
_grantRole(MANAGER_ROLE, managerAddress);
}contract HybridAccess is OwnableUpgradeable, AccessControlUpgradeable {
function initialize(address owner) initializer public {
__Ownable_init(owner);
__AccessControl_init();
_grantRole(DEFAULT_ADMIN_ROLE, owner);
}
// Owner can always grant roles
function grantRole(bytes32 role, address account) public override {
require(hasRole(getRoleAdmin(role), _msgSender()) || owner() == _msgSender(), "Access denied");
_grantRole(role, account);
}
}Install with Tessl CLI
npx tessl i tessl/npm-openzeppelin--contracts-upgradeable