> ## 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.

# Attestable

> Manages attesters and signature verification for CCTP messages

The `Attestable` contract provides attester management and signature verification functionality for Cross-Chain Transfer Protocol messages. It implements an m-of-n multisig mechanism where m attesters must sign messages for them to be considered valid.

**Contract:** `src/roles/Attestable.sol`

## Key Concepts

* **Attesters**: Authorized signers who can attest to message validity
* **Signature Threshold**: Minimum number of signatures required (m in m/n multisig)
* **Attester Manager**: Role responsible for managing attesters and threshold

## State Variables

### signatureThreshold

```solidity theme={null}
uint256 public signatureThreshold
```

Number of signatures from distinct attesters required for a message to be received (m in m/n multisig).

### enabledAttesters

```solidity theme={null}
EnumerableSet.AddressSet private enabledAttesters
```

Set of enabled attesters (message signers). The length represents n in m/n multisig.

## Functions

### enableAttester

```solidity theme={null}
function enableAttester(address newAttester) public onlyAttesterManager
```

Enables an attester to sign messages.

**Parameters:**

* `newAttester`: Address of the attester to enable

**Requirements:**

* Caller must be the attester manager
* New attester must be non-zero address
* Attester must not already be enabled

**Emits:** `AttesterEnabled(address indexed attester)`

**Source:** [Attestable.sol:100](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L100)

### disableAttester

```solidity theme={null}
function disableAttester(address attester) external onlyAttesterManager
```

Disables an attester from signing messages.

**Parameters:**

* `attester`: Address of the attester to disable

**Requirements:**

* Caller must be the attester manager
* Must have more than one enabled attester
* Number of enabled attesters must exceed signature threshold
* Attester must currently be enabled

**Emits:** `AttesterDisabled(address indexed attester)`

**Source:** [Attestable.sol:138](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L138)

### setSignatureThreshold

```solidity theme={null}
function setSignatureThreshold(uint256 newSignatureThreshold) external onlyAttesterManager
```

Updates the threshold of signatures required to attest to a message (m in m/n multisig).

**Parameters:**

* `newSignatureThreshold`: New signature threshold value

**Requirements:**

* Caller must be the attester manager
* New threshold must be non-zero
* New threshold must not exceed number of enabled attesters
* New threshold must be different from current threshold

**Emits:** `SignatureThresholdUpdated(uint256 oldSignatureThreshold, uint256 newSignatureThreshold)`

**Source:** [Attestable.sol:161](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L161)

### updateAttesterManager

```solidity theme={null}
function updateAttesterManager(address newAttesterManager) external onlyOwner
```

Transfers attester manager control to a new address.

**Parameters:**

* `newAttesterManager`: Address of the new attester manager

**Requirements:**

* Caller must be the owner
* New attester manager must be non-zero address

**Emits:** `AttesterManagerUpdated(address indexed previousAttesterManager, address indexed newAttesterManager)`

**Source:** [Attestable.sol:125](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L125)

### isEnabledAttester

```solidity theme={null}
function isEnabledAttester(address attester) public view returns (bool)
```

Checks if an address is an enabled attester.

**Parameters:**

* `attester`: Address to check

**Returns:** `true` if the address is an enabled attester, `false` otherwise

**Source:** [Attestable.sol:109](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L109)

### getNumEnabledAttesters

```solidity theme={null}
function getNumEnabledAttesters() public view returns (uint256)
```

Returns the number of enabled attesters.

**Returns:** Count of enabled attesters

**Source:** [Attestable.sol:117](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L117)

### getEnabledAttester

```solidity theme={null}
function getEnabledAttester(uint256 index) external view returns (address)
```

Gets the enabled attester at a specific index.

**Parameters:**

* `index`: Index of the attester in the set

**Returns:** Address of the attester at the given index

**Source:** [Attestable.sol:180](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L180)

### attesterManager

```solidity theme={null}
function attesterManager() external view returns (address)
```

Returns the address of the current attester manager.

**Returns:** Attester manager address

**Source:** [Attestable.sol:171](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L171)

## Signature Verification

### Internal Verification

The contract includes internal signature verification logic:

```solidity theme={null}
function _verifyAttestationSignatures(
    bytes calldata _message,
    bytes calldata _attestation
) internal view
```

Verifies that an attestation is valid according to these rules:

1. Attestation length must equal `signatureLength * signatureThreshold` (65 bytes per signature)
2. Recovered addresses must be in increasing order (prevents duplicates)
3. All signers must be enabled attesters
4. Uses ECDSA signature recovery

**Source:** [Attestable.sol:227](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/Attestable.sol#L227)

## Modifiers

### onlyAttesterManager

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

Restricts function access to the attester manager only.

**Reverts:** "Caller not attester manager" if caller is not the attester manager

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

## Events

### AttesterEnabled

```solidity theme={null}
event AttesterEnabled(address indexed attester)
```

Emitted when an attester is enabled.

### AttesterDisabled

```solidity theme={null}
event AttesterDisabled(address indexed attester)
```

Emitted when an attester is disabled.

### SignatureThresholdUpdated

```solidity theme={null}
event SignatureThresholdUpdated(
    uint256 oldSignatureThreshold,
    uint256 newSignatureThreshold
)
```

Emitted when the signature threshold is updated.

### AttesterManagerUpdated

```solidity theme={null}
event AttesterManagerUpdated(
    address indexed previousAttesterManager,
    address indexed newAttesterManager
)
```

Emitted when the attester manager is updated.

## Usage Example

```solidity theme={null}
// Enable a new attester (as attester manager)
attestable.enableAttester(0x123...);

// Update signature threshold to require 2 signatures
attestable.setSignatureThreshold(2);

// Check if an address is an enabled attester
bool isEnabled = attestable.isEnabledAttester(0x123...);

// Get total number of attesters
uint256 count = attestable.getNumEnabledAttesters();
```

## Security Considerations

* The signature threshold must always be less than or equal to the number of enabled attesters
* Cannot disable attesters if it would reduce the count below the threshold
* Must maintain at least one enabled attester at all times
* Signatures must be provided in ascending order by signer address to prevent duplicates
* Uses ECDSA signature recovery from OpenZeppelin for security
