We manage your security to weather the AI storm →

← Resource Hub

Ownable vs AccessControl vs AccessManager in Solidity

By Owen Thurm Published 5 min read

Ownable vs AccessControl vs AccessManager in Solidity

Quick answer. Use Ownable2Step for a single contract with one admin, AccessControl when one contract needs separate powers, and AccessManager when many contracts share one permission system with delays. In every case, put the admin behind a multisig.

Watch: Ownable vs AccessControl vs AccessManager in Solidity 1:43
Video transcript

Access control decides who can mint, pause, upgrade and move funds. Each OpenZeppelin model fails in its own way.

OWASP's Smart Contract Top 10 for 2026 ranks access control vulnerabilities first.

Use Ownable2Step for one admin on one contract, AccessControl for separate powers, and AccessManager when many contracts share one permission system.

Ownable2Step fixes the handoff, not renounceOwnership. One call can still set the owner to the zero address.

Audits found it at Ethena, Yellow Network and Kairos, risking frozen settings and locked treasury funds. If an owner is always required, override it to revert.

In AccessControl, one admin role controls every role by default, which OpenZeppelin warns carries significant risk. The Default Admin Rules extension allows one admin, moved in two steps with a delay.

Audits also find a second top admin, owners and roles out of step, role math that could collapse to the default admin, and zero delays.

AccessManager keeps every permission in one contract. Mark sensitive functions restricted, give the admin role to a multisig, and run version five point seven or later.

The top key decides everything, so hold it in a multisig. Guardian audits start with a design review, then attack privileged flows. After launch, Managed Security monitors role changes.

Read the full guide for upgradeable variants and every finding. Or get your roles reviewed before launch at guardian.security.

Access control decides who can mint, pause, upgrade and move funds. OWASP's Smart Contract Top 10 for 2026 ranks access control vulnerabilities first.

OpenZeppelin Contracts offers three models for it. This guide follows the current release, v5.7.0, published July 29, 2026.

Each model fails in its own way. Here is how they compare, what audits find in each, and how to choose.

The Three Models at a Glance

Contract Who holds power How power moves Best for
OwnableOne owner addressOne call, takes effect at onceSimple contracts, prototypes
Ownable2StepOne owner addressNew owner must acceptSingle-admin contracts in production
AccessControlHolders of bytes32 rolesEach role's admin grants and revokesOne contract with several distinct powers
AccessControlDefaultAdminRulesRoles, with one top adminTop admin moves in two steps, with a delayRoles with a hardened top admin
AccessManageruint64 roles in one central contractGrants, calls and admin changes can be delayedA system of many contracts

The extensions matter as much as the base contracts. They fix the handoff mistakes audits keep finding.

Ownable and Ownable2Step

Ownable gives one address, the owner, exclusive access to functions marked onlyOwner. OpenZeppelin calls it "perfectly reasonable for contracts that have a single administrative user".

Since v5.0, its constructor takes an initialOwner and reverts on address(0).

Plain transferOwnership hands over control in one call. Send it to a wrong address, or to a contract that cannot call this one, and the admin functions are lost.

Ownable2Step splits the handoff. Nothing changes until the new owner calls acceptOwnership.

What audits find

The common trap: Ownable2Step does not override renounceOwnership. One call still sets the owner to address(0), and it clears any pending owner too.

  • Ethena L-04: renouncing would have frozen every onlyOwner setting on EthenaSafeGuard.
  • Yellow Network L-04: renouncing during the handoff to a Timelock could lock treasury funds for good.
  • Kairos L-12: the inherited function bypassed a three-day renouncement process.

All three were resolved. If a contract must always have an owner, override the function to revert:

error RenounceDisabled();

function renounceOwnership() public pure override {
    revert RenounceDisabled();
}

AccessControl and Admin Roles

AccessControl splits power into roles, each a bytes32 id checked with onlyRole. A minter can mint without being able to pause.

Holding a role does not let you grant it. Each role has an admin role, and only its holders can call grantRole and revokeRole.

By default, DEFAULT_ADMIN_ROLE (0x00) is the admin of every role, including itself. OpenZeppelin warns that it "carries significant risk".

To reduce that risk, OpenZeppelin recommends AccessControlDefaultAdminRules. It allows one default admin, and moving that role takes two steps with a configurable delay.

The base contract cannot list role holders onchain. Index the RoleGranted and RoleRevoked events, or use AccessControlEnumerable.

What audits find

  • A second top admin. In Bracket L-13, a vault creator could take DEFAULT_ADMIN_ROLE and revoke the multisig.
  • Owner and roles out of step. In Trueo L-01, a former owner could keep DEFAULT_ADMIN_ROLE and PAUSER_ROLE.
  • Custom role math. In Strata M-02, a derived role id could collapse to bytes32(0), the default admin.
  • A zero delay. Glider I-03 set the default admin delay to zero, removing the review window.

For the wider bug patterns, see access control vulnerabilities in smart contracts.

AccessManager for Many Contracts

AccessManager arrived in v5.0 in October 2023. It "stores all the permissions in a single contract", so a protocol has one place to audit.

Managed contracts inherit AccessManaged and mark functions restricted. The manager maps each function selector on each contract to one role.

Roles are uint64 numbers, not names. ADMIN_ROLE is 0, and every address holds PUBLIC_ROLE.

Until configured, every restricted function is open only to ADMIN_ROLE. Delays are built in:

  • Execution delay: set per member; the call is scheduled, then executed after the wait.
  • Grant delay: set per role; a new member's role takes effect later.
  • Target admin delay: set per contract; covers its function roles, closing it and changing its authority.

Each role also has a guardian that can cancel scheduled operations. Admins can close a whole contract with setTargetClosed during an incident.

What to check

  • Every sensitive function carries restricted. Without it, the manager's rules "won't be applied".
  • restricted sits on external functions. OpenZeppelin warns internal use can have "critical security implications".
  • A multisig or governance holds ADMIN_ROLE, the default admin and guardian of every role.
  • Contracts moved from Ownable now see the manager as msg.sender.
  • You run 5.7.0 or later. It stops execute from bypassing the delay on updateAuthority.

Which Model to Use

If you need Use
One admin for one contractOwnable2Step, owned by a multisig
Separate powers in one contractAccessControl with AccessControlDefaultAdminRules
Role holders readable onchainAdd AccessControlEnumerable
One permission map across many contractsAccessManager
Delays on sensitive calls and grantsAccessManager, or a TimelockController as admin
Contracts behind a proxyThe upgradeable variant of the same contract

Behind a proxy

Each model has a twin in @openzeppelin/contracts-upgradeable, such as OwnableUpgradeable and AccessManagerUpgradeable.

Constructors become initializers, like __Ownable_init(initialOwner). Skipping one can leave a contract with no owner; see five upgradeable contract vulnerabilities.

From v5.0, these variants use ERC-7201 namespaced storage. A live v4 proxy cannot switch to them in place, as our v4 to v5 migration guide explains.

Whichever model you pick, the top key decides everything. Hold it in a multisig, following our multisig best practices.

How Guardian Reviews Access Control

A Guardian smart contract audit starts with a design review of governance, roles and upgrade paths, before implementation locks in the expensive risks.

Senior researchers then attack privileged flows with exploit-driven review.

Vanguard puts two independent teams on the same scope and reviews updates for six months after production.

After launch, Managed Security monitors privileged calls, role and ownership changes and upgrades on every block.

Frequently Asked Questions

Is Ownable2Step safer than Ownable?

For transfers, yes: the new owner must call acceptOwnership, so a typo cannot hand the contract to a dead address. But renounceOwnership is still a single call in both, so override it if the contract must always have an owner.

What is DEFAULT_ADMIN_ROLE in AccessControl?

It is the role with id 0x00 that administers every role by default, including itself. Whoever holds it can grant and revoke those roles. AccessControlDefaultAdminRules limits it to one account and moves it in two steps with a delay.

When should I use AccessManager instead of AccessControl?

When several contracts need permissions you want to see and change in one place, or when you want delays on grants and sensitive calls. For one contract with a few roles, AccessControl is simpler.

Can an Ownable contract move to AccessManager?

Yes. OpenZeppelin's docs say to transfer ownership to the manager. After that, onlyOwner functions are called through the manager's execute function, and the contract sees the AccessManager as msg.sender.

Sources

Get your roles reviewed before launch

Guardian reviews who can mint, pause and upgrade your contracts, and how that power moves, before an attacker tests it.