CCIP v2.0.0 AdvancedPoolHooks API Reference

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

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

Inheritance

  • AuthorizedCallers
  • IAdvancedPoolHooks
  • ITypeAndVersion

typeAndVersion

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

Returns "AdvancedPoolHooks 2.0.0".


State

Immutables

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

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

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

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

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

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.


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.


function getAllowListEnabled() external view returns (bool)

Returns whether allowlist enforcement was enabled at deployment.


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

Returns the current allowlist entries.


CCV Configuration

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.


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

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


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

Returns one CCVConfigArg per configured remote chain selector.


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

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.


function getThresholdAmount() external view returns (uint256)

Returns the current threshold amount.


Policy Engine

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.


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.


function getPolicyEngine() external view returns (address)

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


Events

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

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

Structs

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

Internal Functions

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.


function _setPolicyEngine(
  address newPolicyEngine,
  bool allowFailedDetach
) internal virtual

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


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 reference for the full surface:

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

Ownership follows Ownable2StepMsgSender through the same inheritance chain.


Get the latest Chainlink content straight to your inbox.