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

# Denylistable

> Role contract for managing address denylists in V2

# Denylistable Role

The `Denylistable` contract provides denylist management capabilities for CCTP V2 contracts. It allows designated denylister addresses to add or remove accounts from a denylist, preventing them from participating in cross-chain transfers.

**Source**: [Denylistable.sol](https://github.com/circlefin/evm-cctp-contracts/blob/master/src/roles/v2/Denylistable.sol)

<Info>
  Denylistable is a V2-only feature. V1 contracts do not support denylisting.
</Info>

## Overview

Denylistable extends `Ownable2Step` and provides:

* A designated denylister role that can manage the denylist
* Functions to add and remove addresses from the denylist
* A modifier to check if an address is denylisted
* Events for tracking denylist changes

This role is used by `TokenMessengerV2` to enforce compliance and prevent sanctioned addresses from using CCTP.

## State Variables

### \_denylister

```solidity theme={null}
address internal _denylister;
```

The address with permission to add or remove accounts from the denylist.

### \_denylisted

```solidity theme={null}
mapping(address => uint256) internal _denylisted;
```

Maps addresses to their denylist status (1 = denylisted, 0 = not denylisted). Uses uint256 instead of bool for gas optimization.

## Events

### DenylisterChanged

Emitted when the denylister address is updated.

```solidity theme={null}
event DenylisterChanged(
    address indexed oldDenylister,
    address indexed newDenylister
);
```

### Denylisted

Emitted when an account is added to the denylist.

```solidity theme={null}
event Denylisted(address indexed account);
```

### UnDenylisted

Emitted when an account is removed from the denylist.

```solidity theme={null}
event UnDenylisted(address indexed account);
```

## Functions

### updateDenylister

Updates the denylister address. Only callable by the contract owner.

```solidity theme={null}
function updateDenylister(address newDenylister) external onlyOwner;
```

**Parameters:**

* `newDenylister` (address): The address of the new denylister

**Requirements:**

* Caller must be the contract owner
* `newDenylister` must not be the zero address

**Reference**: `src/roles/v2/Denylistable.sol:71`

### addToDenylist

Adds an account to the denylist. Only callable by the denylister.

```solidity theme={null}
function addToDenylist(address account) external onlyDenylister;
```

**Parameters:**

* `account` (address): The address to add to the denylist

**Requirements:**

* Caller must be the denylister
* `account` must not already be denylisted

**Emits**: `Denylisted` event

**Reference**: `src/roles/v2/Denylistable.sol:87`

### removeFromDenylist

Removes an account from the denylist. Only callable by the denylister.

```solidity theme={null}
function removeFromDenylist(address account) external onlyDenylister;
```

**Parameters:**

* `account` (address): The address to remove from the denylist

**Requirements:**

* Caller must be the denylister
* `account` must currently be denylisted

**Emits**: `UnDenylisted` event

**Reference**: `src/roles/v2/Denylistable.sol:101`

### isDenylisted

Checks if an address is on the denylist.

```solidity theme={null}
function isDenylisted(address account) external view returns (bool);
```

**Parameters:**

* `account` (address): The address to check

**Returns:**

* `bool`: `true` if the account is denylisted, `false` otherwise

**Reference**: `src/roles/v2/Denylistable.sol:113`

### denylister

Returns the current denylister address.

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

**Returns:**

* `address`: The address of the current denylister

**Reference**: `src/roles/v2/Denylistable.sol:121`

## Modifiers

### onlyDenylister

Restricts function access to the denylister address only.

```solidity theme={null}
modifier onlyDenylister();
```

**Reverts** with "Caller is not the denylister" if the caller is not the denylister.

### notDenylisted

Checks that an address is not on the denylist.

```solidity theme={null}
modifier notDenylisted(address account);
```

**Parameters:**

* `account` (address): The address to check

**Reverts** with "Account is denylisted" if the address is on the denylist.

## Usage in TokenMessengerV2

TokenMessengerV2 uses Denylistable to prevent denylisted addresses from:

* Depositing USDC for burn
* Receiving minted USDC on the destination chain

### Deposit Validation

```solidity theme={null}
function depositForBurn(
    uint256 amount,
    uint32 destinationDomain,
    bytes32 mintRecipient,
    address burnToken,
    uint256 maxFee,
    uint32 minFinalityThreshold,
    bytes32 destinationCaller
) external notDenylisted(msg.sender) returns (uint64) {
    // Deposit logic...
}
```

### Mint Recipient Validation

Before minting, TokenMessengerV2 checks that the mint recipient is not denylisted:

```solidity theme={null}
bytes32 mintRecipient = burnMessage.mintRecipient();
address mintRecipientAddress = mintRecipient.toAddress();

require(
    !isDenylisted(mintRecipientAddress),
    "Mint recipient is denylisted"
);
```

## Configuration Example

Setting up denylist management:

```solidity theme={null}
// Deploy TokenMessengerV2 with denylister role
address denylister = 0x123...; // Compliance team address

// Update denylister (owner only)
tokenMessengerV2.updateDenylister(denylister);

// Add address to denylist (denylister only)
address sanctionedAddress = 0x456...;
tokenMessengerV2.addToDenylist(sanctionedAddress);

// Check if address is denylisted
bool isDenied = tokenMessengerV2.isDenylisted(sanctionedAddress);
// Returns: true

// Remove from denylist when appropriate
tokenMessengerV2.removeFromDenylist(sanctionedAddress);
```

## Security Considerations

<Warning>
  The denylister role has significant power to block addresses from using CCTP. This role should be assigned to trusted compliance personnel or multi-sig wallets.
</Warning>

### Access Control

* **Owner Control**: Only the contract owner can change the denylister address
* **Denylister Independence**: The denylister operates independently from the owner for day-to-day denylist management
* **Two-Step Ownership**: Inherits secure ownership transfer from Ownable2Step

### Best Practices

1. **Multi-Sig Denylister**: Use a multi-sig wallet as the denylister to prevent single-point-of-failure
2. **Monitoring**: Emit and monitor all denylist events for transparency
3. **Regular Reviews**: Periodically review the denylist and remove addresses when appropriate
4. **Emergency Procedures**: Have documented procedures for urgent denylist additions
5. **Legal Compliance**: Ensure denylist operations comply with applicable regulations

### Gas Optimization

The contract uses `uint256` constants (`_TRUE = 1`, `_FALSE = 0`) instead of booleans for the denylist mapping to optimize gas costs during storage operations.

## Related Contracts

* [TokenMessengerV2](/api/v2/token-messenger-v2) - Implements Denylistable for deposit and mint protection
* [Ownable2Step](/api/roles/ownable) - Base contract providing secure ownership management
* [V2 Overview](/v2/overview) - Learn more about V2 features including denylist

## Comparison with V1

V1 contracts do not have denylist functionality. This is a new feature in V2 designed to enhance compliance capabilities:

| Feature          | V1   | V2           |
| ---------------- | ---- | ------------ |
| Denylist Support | ❌ No | ✅ Yes        |
| Compliance Role  | ❌ No | ✅ Denylister |
| Address Blocking | ❌ No | ✅ Yes        |
| Granular Control | ❌ No | ✅ Yes        |

## Migration Considerations

When migrating from V1 to V2, you'll need to:

1. Designate a denylister address
2. Import any existing blocklists from external sources
3. Update client code to handle denylist-related errors
4. Implement monitoring for denylist events

See the [V2 Migration Guide](/v2/migration-guide) for complete migration instructions.
