# CCIP v2.0.0 AdvancedPoolHooks API Reference
Source: https://docs.chain.link/ccip/evm/api-reference/v2.0.0/advanced-pool-hooks

> For the complete documentation index, see [llms.txt](/llms.txt).

## Summary

`AdvancedPoolHooks` is an optional extension contract that can be attached to a `[TokenPool](/ccip/evm/api-reference/v2.0.0/token-pool)` to add:

1. Allowlist enforcement for outbound transfers.
2. Per-lane, per-direction CCV configuration.
3. Threshold-based CCV escalation for large transfers.
4. External policy engine execution hooks.

Token pools invoke it during `preflightCheck` (outbound), `postflightCheck` (inbound), and `getRequiredCCVs` (verifier resolution).

This contract is optional and not required for base pool operation.

***

## Contract

`chains/evm/contracts/pools/AdvancedPoolHooks.sol`

***

## Import

```solidity
import {AdvancedPoolHooks} from "chainlink-ccip/chains/evm/contracts/pools/AdvancedPoolHooks.sol";
```

***

## Inheritance

- `AuthorizedCallers`
- `IAdvancedPoolHooks`
- `ITypeAndVersion`

***

## typeAndVersion

```solidity
function typeAndVersion() external pure virtual override returns (string memory)
```

Returns `"AdvancedPoolHooks 2.0.0"`.

***

## State

### Immutables

```solidity
bool internal immutable i_allowlistEnabled;
```

Whether allowlist enforcement was enabled at deployment. Set from `allowlist.length > 0` in the constructor and cannot change afterward.

***

### Storage

```solidity
EnumerableSet.AddressSet internal s_allowlist;

uint256 internal s_thresholdAmountForAdditionalCCVs;

IPolicyEngine internal s_policyEngine;

mapping(uint64 remoteChainSelector => CCVConfig ccvConfig) internal s_verifierConfig;

EnumerableSet.UintSet internal s_configuredChainSelectors;
```

`s_configuredChainSelectors` tracks every remote chain selector that has a nonempty outbound or inbound CCV list.

***

## Constructor

```solidity
constructor(
  address[] memory allowlist,
  uint256 thresholdAmountForAdditionalCCVs,
  address policyEngine,
  address[] memory authorizedCallers
)
```

Behavior:

- Passes `authorizedCallers` to `AuthorizedCallers`, initializing the authorized caller set.
- If `allowlist.length > 0`, allowlist enforcement is permanently enabled and the initial entries are applied.
- If `allowlist.length == 0`, allowlist enforcement is permanently disabled. `applyAllowListUpdates` reverts with `AllowListNotEnabled` for the life of the deployment.
- Initializes the threshold amount. `0` disables threshold escalation.
- Sets the initial policy engine. A nonzero address is attached immediately; `address(0)` leaves policy checks disabled.

***

## External API

### Preflight Hook

```solidity
function preflightCheck(
  Pool.LockOrBurnInV1 calldata lockOrBurnIn,
  bytes4 requestedFinalityConfig,
  bytes calldata tokenArgs,
  uint256 amountPostFee
) external
```

Called by the Token Pool before locking or burning tokens on the source chain.

Behavior:

- Validates the caller via `AuthorizedCallers`.
- Checks `lockOrBurnIn.originalSender` against the allowlist, if enabled. Reverts with `SenderNotAllowed` on failure.
- Runs the policy engine with `tokenArgs` as context, if configured.

This implementation ignores `requestedFinalityConfig` and `amountPostFee`. CCV requirements are resolved separately through `getRequiredCCVs`, not in this function.

***

### Postflight Hook

```solidity
function postflightCheck(
  Pool.ReleaseOrMintInV1 calldata releaseOrMintIn,
  uint256 localAmount,
  bytes4 requestedFinalityConfig
) external
```

Called by the Token Pool before releasing or minting tokens on the destination chain.

Behavior:

- Validates the caller via `AuthorizedCallers`.
- Runs the policy engine with `releaseOrMintIn.offchainTokenData` as context, if configured.

This implementation ignores `localAmount` and `requestedFinalityConfig`. The allowlist does not run during postflight.

***

### Allowlist Management

```solidity
function applyAllowListUpdates(
  address[] calldata removes,
  address[] calldata adds
) external onlyOwner
```

Updates the allowlist entries. Removals are processed first, then additions. `address(0)` entries in `adds` are skipped. Emits `AllowListRemove` and `AllowListAdd` for each applied change.

Reverts `AllowListNotEnabled()` if the allowlist was not enabled at deployment.

***

```solidity
function checkAllowList(address sender) external view
```

Reverts `SenderNotAllowed(sender)` if the allowlist is enabled and `sender` is not present. Does not revert when the allowlist is disabled or the sender is present.

***

```solidity
function getAllowListEnabled() external view returns (bool)
```

Returns whether allowlist enforcement was enabled at deployment.

***

```solidity
function getAllowList() external view returns (address[] memory)
```

Returns the current allowlist entries.

***

### CCV Configuration

```solidity
function applyCCVConfigUpdates(
  CCVConfigArg[] calldata ccvConfigArgs
) external onlyOwner
```

Sets the CCV configuration for each remote chain in the array, replacing any existing configuration for that chain.

Validation:

- No duplicate addresses within `outboundCCVs` or within `inboundCCVs`.
- Threshold CCVs require a nonempty base list for the same direction, otherwise `MustSpecifyUnderThresholdCCVsForThresholdCCVs`.
- No duplicate addresses within each threshold list, or between a base list and its threshold list.
- `address(0)` in a base list requires the default CCV alongside any other listed CCVs.

A chain with empty outbound and inbound lists is removed from the configured set, clearing its requirements.

Emits `CCVConfigUpdated` per chain.

***

```solidity
function getCCVConfig(
  uint64 remoteChainSelector
) external view returns (CCVConfig memory)
```

Returns the CCV configuration for a remote chain. Returns empty lists for an unconfigured chain.

***

```solidity
function getAllCCVConfigs() external view returns (CCVConfigArg[] memory)
```

Returns one `CCVConfigArg` per configured remote chain selector.

***

```solidity
function getRequiredCCVs(
  address localToken,
  uint64 remoteChainSelector,
  uint256 amount,
  bytes4 requestedFinalityConfig,
  bytes calldata extraData,
  IPoolV2.MessageDirection direction
) external view returns (address[] memory requiredCCVs)
```

Returns the CCVs required for a transfer to or from a remote chain:

- `Inbound` direction resolves `inboundCCVs` and `thresholdInboundCCVs`.
- `Outbound` direction resolves `outboundCCVs` and `thresholdOutboundCCVs`.

Base CCVs are always returned. Threshold CCVs are appended when `thresholdAmount != 0 && amount >= thresholdAmount` and the threshold list is nonempty.

This implementation ignores `localToken`, `requestedFinalityConfig`, and `extraData`.

***

### Threshold Control

```solidity
function setThresholdAmount(uint256 thresholdAmount) external onlyOwner
```

Sets the amount at or above which threshold CCVs are required. `0` disables threshold escalation for every remote chain. Emits `ThresholdAmountSet`.

***

```solidity
function getThresholdAmount() external view returns (uint256)
```

Returns the current threshold amount.

***

### Policy Engine

```solidity
function setPolicyEngine(address newPolicyEngine) external onlyOwner
```

Replaces the current policy engine:

- No-op if `newPolicyEngine` equals the current engine.
- Calls `detach()` on the old engine. If the call reverts, the update reverts with `PolicyEngineDetachReverted`.
- Stores the new engine and calls `attach()` on it when nonzero.

`address(0)` disconnects the current engine and disables policy checks. `PolicyEngineAttached` is emitted with the new address, including `address(0)` on disconnect.

***

```solidity
function setPolicyEngineAllowFailedDetach(address newPolicyEngine) external onlyOwner
```

Same as `setPolicyEngine`, except a reverting `detach()` on the old engine emits `PolicyEngineDetachFailed` and the update proceeds. Use this when an old engine blocks its own replacement.

***

```solidity
function getPolicyEngine() external view returns (address)
```

Returns the current policy engine address, or `address(0)` when policy checks are disabled.

***

## Events

```solidity
event AllowListAdd(address sender);
event AllowListRemove(address sender);
event CCVConfigUpdated(
  uint64 indexed remoteChainSelector,
  address[] outboundCCVs,
  address[] thresholdOutboundCCVs,
  address[] inboundCCVs,
  address[] thresholdInboundCCVs
);
event ThresholdAmountSet(uint256 thresholdAmount);
event PolicyEngineAttached(address indexed policyEngine);
event PolicyEngineDetachFailed(address indexed policyEngine, bytes reason);
```

***

## Errors

```solidity
error AllowListNotEnabled();
error SenderNotAllowed(address sender);
error MustSpecifyUnderThresholdCCVsForThresholdCCVs();
error PolicyEngineDetachReverted(address oldPolicyEngine, bytes err);
```

***

## Structs

```solidity
struct CCVConfig {
  address[] outboundCCVs;
  address[] thresholdOutboundCCVs;
  address[] inboundCCVs;
  address[] thresholdInboundCCVs;
}
```

```solidity
struct CCVConfigArg {
  uint64 remoteChainSelector;
  address[] outboundCCVs;
  address[] thresholdOutboundCCVs;
  address[] inboundCCVs;
  address[] thresholdInboundCCVs;
}
```

***

## Internal Functions

```solidity
function _resolveRequiredCCVs(
  address[] memory baseCCVs,
  address[] storage requiredCCVsAboveThresholdStorage,
  uint256 amount
) internal view returns (address[] memory requiredCCVs)
```

Returns `baseCCVs` unless the threshold is nonzero, `amount >= threshold`, and the threshold list is nonempty, in which case returns the base and threshold lists concatenated.

***

```solidity
function _setPolicyEngine(
  address newPolicyEngine,
  bool allowFailedDetach
) internal virtual
```

Implements the detach and attach sequence shared by `setPolicyEngine` and `setPolicyEngineAllowFailedDetach`.

***

```solidity
function _applyAllowListUpdates(
  address[] memory removes,
  address[] memory adds
) internal virtual
```

Implements the allowlist update loop, reused by the constructor and `applyAllowListUpdates`.

***

## Inherited from AuthorizedCallers

See the [`AuthorizedCallers`](/ccip/evm/api-reference/v2.0.0/authorized-callers) reference for the full surface:

- `getAllAuthorizedCallers()`
- `applyAuthorizedCallerUpdates(AuthorizedCallerArgs)`
- `onlyAuthorizedCallers` modifier
- Events `AuthorizedCallerAdded` / `AuthorizedCallerRemoved`
- Errors `UnauthorizedCaller` / `ZeroAddressNotAllowed`

Ownership follows `Ownable2StepMsgSender` through the same inheritance chain.

***

## Related Interfaces & Contracts

- [`AuthorizedCallers`](/ccip/evm/api-reference/v2.0.0/authorized-callers)
- [`IAdvancedPoolHooks`](/ccip/evm/api-reference/v2.0.0/i-advanced-pool-hooks)
- [`TokenPool`](/ccip/evm/api-reference/v2.0.0/token-pool)
- [`LockReleaseTokenPool`](/ccip/evm/api-reference/v2.0.0/lock-release-token-pool)
- [`Pool`](/ccip/evm/api-reference/v2.0.0/pool) (defines `LockOrBurnInV1` and `ReleaseOrMintInV1`)
- [`CCVConfigValidation`](/ccip/evm/api-reference/v2.0.0/ccv-config-validation)