> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/circlefin/evm-cctp-contracts/llms.txt
> Use this file to discover all available pages before exploring further.

# Ownable & Ownable2Step

> Ownership and access control for CCTP contracts

The `Ownable` and `Ownable2Step` contracts provide ownership and access control mechanisms for CCTP contracts. `Ownable2Step` extends `Ownable` with a two-step ownership transfer pattern for additional security.

**Contracts:**

* `src/roles/Ownable.sol`
* `src/roles/Ownable2Step.sol`

## Ownable

Base contract providing single-owner access control mechanism.

### State Variables

#### \_owner

```solidity theme={null}
address private _owner
```

Private state variable storing the current owner address.

### Functions

#### owner

```solidity theme={null}
function owner() public view virtual returns (address)
```

Returns the address of the current owner.

**Returns:** Address of the current owner

**Source:** [Ownable.sol:65](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable.sol#L65)

#### transferOwnership

```solidity theme={null}
function transferOwnership(address newOwner) public virtual onlyOwner
```

Transfers ownership of the contract to a new account. In the base `Ownable` contract, this is a single-step process.

**Parameters:**

* `newOwner`: Address of the new owner

**Requirements:**

* Caller must be the current owner
* New owner must be non-zero address

**Emits:** `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Source:** [Ownable.sol:80](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable.sol#L80)

### Internal Functions

#### \_checkOwner

```solidity theme={null}
function _checkOwner() internal view virtual
```

Verifies that the caller is the owner.

**Reverts:** "Ownable: caller is not the owner" if caller is not the owner

**Source:** [Ownable.sol:72](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable.sol#L72)

#### \_transferOwnership

```solidity theme={null}
function _transferOwnership(address newOwner) internal virtual
```

Internal function to transfer ownership without access restriction.

**Parameters:**

* `newOwner`: Address of the new owner

**Emits:** `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Source:** [Ownable.sol:92](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable.sol#L92)

### Modifiers

#### onlyOwner

```solidity theme={null}
modifier onlyOwner()
```

Restricts function access to the owner only.

**Reverts:** "Ownable: caller is not the owner" if caller is not the owner

**Source:** [Ownable.sol:57](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable.sol#L57)

### Events

#### OwnershipTransferred

```solidity theme={null}
event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
)
```

Emitted when ownership is transferred.

**Parameters:**

* `previousOwner`: Address of the previous owner
* `newOwner`: Address of the new owner

***

## Ownable2Step

Extends `Ownable` with a two-step ownership transfer pattern for enhanced security.

### Key Concepts

**Two-Step Transfer Pattern:**

1. Current owner calls `transferOwnership()` to propose a new owner
2. New owner must call `acceptOwnership()` to complete the transfer

This prevents accidental transfers to incorrect addresses and ensures the new owner can access the account.

### State Variables

#### \_pendingOwner

```solidity theme={null}
address private _pendingOwner
```

Private state variable storing the pending owner address during transfer.

### Functions

#### pendingOwner

```solidity theme={null}
function pendingOwner() public view virtual returns (address)
```

Returns the address of the pending owner during a transfer.

**Returns:** Address of the pending owner, or zero address if no transfer is pending

**Source:** [Ownable2Step.sol:47](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable2Step.sol#L47)

#### transferOwnership

```solidity theme={null}
function transferOwnership(address newOwner)
    public
    virtual
    override
    onlyOwner
```

Starts the ownership transfer by setting the pending owner. This overrides the base `Ownable` function.

**Parameters:**

* `newOwner`: Address of the proposed new owner

**Requirements:**

* Caller must be the current owner

**Effects:**

* Sets `_pendingOwner` to `newOwner`
* Does NOT immediately transfer ownership

**Emits:** `OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)`

**Source:** [Ownable2Step.sol:55](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable2Step.sol#L55)

#### acceptOwnership

```solidity theme={null}
function acceptOwnership() external
```

Completes the ownership transfer. Must be called by the pending owner.

**Requirements:**

* Caller must be the pending owner

**Effects:**

* Transfers ownership to the caller
* Clears the pending owner

**Emits:** `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Source:** [Ownable2Step.sol:77](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable2Step.sol#L77)

### Internal Functions

#### \_transferOwnership

```solidity theme={null}
function _transferOwnership(address newOwner) internal virtual override
```

Internal function to complete ownership transfer. Clears the pending owner before transferring.

**Parameters:**

* `newOwner`: Address of the new owner

**Source:** [Ownable2Step.sol:69](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Ownable2Step.sol#L69)

### Events

#### OwnershipTransferStarted

```solidity theme={null}
event OwnershipTransferStarted(
    address indexed previousOwner,
    address indexed newOwner
)
```

Emitted when an ownership transfer is initiated.

**Parameters:**

* `previousOwner`: Address of the current owner
* `newOwner`: Address of the proposed new owner

## Usage Examples

### Ownable2Step (Recommended)

```solidity theme={null}
// Step 1: Current owner initiates transfer
ownable2Step.transferOwnership(0xNEW_OWNER_ADDRESS);

// Check pending owner
address pending = ownable2Step.pendingOwner(); // 0xNEW_OWNER_ADDRESS

// Step 2: New owner accepts ownership
// (Must be called by 0xNEW_OWNER_ADDRESS)
ownable2Step.acceptOwnership();

// Verify new owner
address currentOwner = ownable2Step.owner(); // 0xNEW_OWNER_ADDRESS
```

### Replacing a Pending Transfer

```solidity theme={null}
// Initiate transfer to address A
ownable2Step.transferOwnership(0xADDRESS_A);

// Change mind and transfer to address B instead
// This replaces the pending transfer
ownable2Step.transferOwnership(0xADDRESS_B);

// Now only address B can accept ownership
```

## Owner Privileges

In CCTP contracts, the owner role typically has the following privileges:

* Update the attester manager (`Attestable`)
* Update the pauser (`Pausable`)
* Update the rescuer (`Rescuable`)
* Update the token controller (`TokenController`)
* Other administrative functions

## Security Considerations

### Why Use Ownable2Step?

1. **Prevents Typos**: Cannot accidentally transfer to wrong address
2. **Verifies Access**: Ensures new owner can sign transactions from that address
3. **Allows Cancellation**: Can initiate new transfer to different address before acceptance
4. **No Renounce**: Neither contract includes `renounceOwnership()` to prevent accidental loss of control

### Best Practices

* Use `Ownable2Step` for all production contracts (as CCTP does)
* Owner should be a multisig or DAO governance contract
* Never transfer ownership to an unverified address
* Ensure the new owner address is controlled and accessible
* Monitor for `OwnershipTransferStarted` events
* Complete pending transfers promptly or replace them

## Inheritance Hierarchy

```
Context (OpenZeppelin)
    └── Ownable
            └── Ownable2Step
```

All CCTP role contracts inherit from `Ownable2Step` for maximum security.

## Origin

Forked from [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7c5f6bc2c8743d83443fa46395d75f2f3f99054a/contracts/access/) with modifications:

* Updated Solidity version from 0.8.0 to 0.7.6
* Removed `renounceOwnership()` function for safety
* Based on v8 contracts which include internal `_transferOwnership` method
