Nick Mudge (@mudgen), Dan Finlay <dan@danfinlay.com>
This specification defines standard functions for owning or controlling a contract.
An implementation allows reading the current owner (owner() returns (address)) and transferring ownership (transferOwnership(address newOwner)) along with a standardized event for when ownership is changed (OwnershipTransferred(address indexed previousOwner, address indexed newOwner)).
Many smart contracts require that they be owned or controlled in some way. For example to withdraw funds or perform administrative actions. It is so common that the contract interface used to handle contract ownership should be standardized to allow compatibility with user interfaces and contracts that manage contracts.
Here are some examples of kinds of contracts and applications that can benefit from this standard:
Every ERC-173 compliant contract must implement the ERC173 interface. Contracts should also implement ERC165 for the ERC-173 interface.
/// @title ERC-173 Contract Ownership Standard
/// Note: the ERC-165 identifier for this interface is 0x7f5828d0
interface ERC173 /* is ERC165 */ {
/// @dev This emits when ownership of a contract changes.
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/// @notice Get the address of the owner
/// @return The address of the owner.
function owner() view external returns(address);
/// @notice Set the address of the new owner of the contract
/// @dev Set _newOwner to address(0) to renounce any ownership.
/// @param _newOwner The address of the new owner of the contract
function transferOwnership(address _newOwner) external;
}
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
The owner() function may be implemented as pure or view.
The transferOwnership(address _newOwner) function may be implemented as public or external.
To renounce any ownership of a contract set _newOwner to the zero address: transferOwnership(address(0)). If this is done then a contract is no longer owned by anybody.
The OwnershipTransferred event should be emitted when a contract is created.
Key factors influencing the standard:
Several ownership schemes were considered. The scheme chosen in this standard was chosen because of its simplicity, low gas cost and backwards compatibility with existing contracts.
Here are other schemes that were considered:
owner() function could look up the owner address of a particular ENS name and use that as the owning address of the contract. Using this scheme a contract could be transferred by transferring the ownership of the ENS domain name to a different address. Short comings to this approach are that it is not backwards compatible with existing contracts and requires gas to make external calls to ENS related contracts to get the owner address.This standard does not exclude the above ownership schemes or other schemes from also being implemented in the same contract. For example a contract could implement this standard and also implement the other schemes so that ownership could be managed and transferred in multiple ways. This standard does provide a simple ownership scheme that is backwards compatible, is light-weight and simple to implement, and can be widely adopted and depended on.
This standard can be (and has been) extended by other standards to add additional ownership functionality.
If the address returned by owner() is an externally owned account then its private key must not be lost or compromised.
Many existing contracts already implement this standard.
Copyright and related rights waived via CC0.