// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IOwnable2StepUpgradeable} from "./IOwnable2StepUpgradeable.sol"; import {IOwnable2StepStorageV1} from "./IOwnable2StepStorageV1.sol"; import {Initializable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; /// @title Ownable /// @author Rohan Kulkarni / Iain Nash /// @notice Modified from OpenZeppelin Contracts v4.7.3 (access/OwnableUpgradeable.sol) /// - Uses custom errors declared in IOwnable /// - Adds optional two-step ownership transfer (`safeTransferOwnership` + `acceptOwnership`) abstract contract Ownable2StepUpgradeable is IOwnable2StepUpgradeable, IOwnable2StepStorageV1, Initializable { /// /// /// STORAGE /// /// /// /// @dev Modifier to check if the address argument is the zero/burn address modifier notZeroAddress(address check) { if (check == address(0)) { revert OWNER_CANNOT_BE_ZERO_ADDRESS(); } _; } /// /// /// MODIFIERS /// /// /// /// @dev Ensures the caller is the owner modifier onlyOwner() { if (msg.sender != _owner) { revert ONLY_OWNER(); } _; } /// @dev Ensures the caller is the pending owner modifier onlyPendingOwner() { if (msg.sender != _pendingOwner) { revert ONLY_PENDING_OWNER(); } _; } /// /// /// FUNCTIONS /// /// /// /// @dev Initializes contract ownership /// @param _initialOwner The initial owner address function __Ownable_init(address _initialOwner) internal notZeroAddress(_initialOwner) onlyInitializing { _owner = _initialOwner; emit OwnerUpdated(address(0), _initialOwner); } /// @notice The address of the owner function owner() public view virtual returns (address) { return _owner; } /// @notice The address of the pending owner function pendingOwner() public view returns (address) { return _pendingOwner; } /// @notice Forces an ownership transfer from the last owner /// @param _newOwner The new owner address function transferOwnership(address _newOwner) public notZeroAddress(_newOwner) onlyOwner { _transferOwnership(_newOwner); } /// @notice Forces an ownership transfer from any sender /// @param _newOwner New owner to transfer contract to /// @dev Ensure is called only from trusted internal code, no access control checks. function _transferOwnership(address _newOwner) internal { emit OwnerUpdated(_owner, _newOwner); _owner = _newOwner; if (_pendingOwner != address(0)) { delete _pendingOwner; } } /// @notice Initiates a two-step ownership transfer /// @param _newOwner The new owner address function safeTransferOwnership(address _newOwner) public notZeroAddress(_newOwner) onlyOwner { _pendingOwner = _newOwner; emit OwnerPending(_owner, _newOwner); } /// @notice Resign ownership of contract /// @dev only callably by the owner, dangerous call. function resignOwnership() public onlyOwner { _transferOwnership(address(0)); } /// @notice Accepts an ownership transfer function acceptOwnership() public onlyPendingOwner { emit OwnerUpdated(_owner, msg.sender); _transferOwnership(msg.sender); } /// @notice Cancels a pending ownership transfer function cancelOwnershipTransfer() public onlyOwner { emit OwnerCanceled(_owner, _pendingOwner); delete _pendingOwner; } }