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:
- Allowlist enforcement for outbound transfers.
- Per-lane, per-direction CCV configuration.
- Threshold-based CCV escalation for large transfers.
- 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
AuthorizedCallersIAdvancedPoolHooksITypeAndVersion
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
authorizedCallerstoAuthorizedCallers, 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.applyAllowListUpdatesreverts withAllowListNotEnabledfor the life of the deployment. - Initializes the threshold amount.
0disables 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.originalSenderagainst the allowlist, if enabled. Reverts withSenderNotAllowedon failure. - Runs the policy engine with
tokenArgsas 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.offchainTokenDataas 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
outboundCCVsor withininboundCCVs. - 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:
Inbounddirection resolvesinboundCCVsandthresholdInboundCCVs.Outbounddirection resolvesoutboundCCVsandthresholdOutboundCCVs.
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
newPolicyEngineequals the current engine. - Calls
detach()on the old engine. If the call reverts, the update reverts withPolicyEngineDetachReverted. - 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)onlyAuthorizedCallersmodifier- Events
AuthorizedCallerAdded/AuthorizedCallerRemoved - Errors
UnauthorizedCaller/ZeroAddressNotAllowed
Ownership follows Ownable2StepMsgSender through the same inheritance chain.
Related Interfaces & Contracts
AuthorizedCallersIAdvancedPoolHooksTokenPoolLockReleaseTokenPoolPool(definesLockOrBurnInV1andReleaseOrMintInV1)CCVConfigValidation