✅OpenZeppelin Ownable
Last updated
Last updated
The most common and basic form of access control is the concept of ownership: there's an account that is the owner
of a contract and can do administrative tasks on it. This approach is perfectly reasonable for contracts that have a single administrative user.
OpenZeppelin Contracts provides Ownable
for implementing ownership in your contracts.
By default, the owner
of an Ownable
contract is the account that deployed it, which is usually exactly what you want.
Ownable also lets you:
transferOwnership
from the owner account to a new one, and
renounceOwnership
for the owner to relinquish this administrative privilege, a common pattern after an initial stage with centralized administration is over.
Warning
Removing the owner altogether will mean that administrative tasks that are protected by onlyOwner
will no longer be callable!
Note that a contract can also be the owner of another one! This opens the door to using, for example, a Gnosis Safe, an Aragon DAO, or a totally custom contract that you create.
In this way you can use composability to add additional layers of access control complexity to your contracts. Instead of having a single regular Ethereum account (Externally Owned Account, or EOA) as the owner, you could use a 2-of-3 multisig run by your project leads, for example. Prominent projects in the space, such as MakerDAO, use systems similar to this one.
There is only one state variable in this contract:
Note that when a contract inherits Ownable, _owner
will be stored in storage slot 0.
During initialization, the msg.sender
(the deployer) becomes owner.
This is a one-step ownership transfer function. In general this pattern is not recommended because owner's private key can be stolen, etc. We want to use something like 2-of-3 signature and timelock delay for doing ownership transfer.
"Renouncing" ownership means setting the zero address as the owner. Note that after calling renounceOwnership()
, any call to transferOwnership()
would revert because of the following check in transferOwnership()
: