Skip to content
Lattice

CCTPHookVault

Git Source

Inherits: ICCTPHookReceiver

Title: CCTPHookVault

Author: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80)

Example CCTP v2 hook receiver: an auto-credit USDC vault. When USDC is bridged to this vault with a Lattice hook envelope, the source diamond's CCTPHookExecutor calls onCCTPHook AFTER the mint and the vault books the freshly-minted amount to the beneficiary encoded in payload — a "programmable USDC" primitive where ONE attested cross-chain message both MOVES funds and CREDITS an account. The beneficiary later withdraws their booked balance.

SECURITY MODEL. Two invariants keep the vault solvent (booked credits are always backed 1:1 by USDC the vault actually holds):

  1. AUTHENTICITY — onCCTPHook accepts calls ONLY from executor, the per-diamond, role-less, fund-less CCTPHookExecutor that fires solely on a real Iris-attested burn addressed to its diamond.
  2. BACKING — it requires the attested mintRecipient to be THIS vault, so the amount credited is USDC that was just minted here (the interface warns targets MUST NOT assume the mint went to them: an attacker may set the hook target to this vault while minting the USDC elsewhere). amount is the attested NET-MINTED value (burn amount minus attested feeExecuted), so a credit equals USDC received. payload is attacker-controlled, but it selects only WHO is credited — never HOW MUCH (that comes from the attested mint) — so a hostile payload can at worst mis-address a credit it also funded. A revert here is swallowed by the executor (the mint stands, the CCTP nonce is consumed). TESTNET SHOWCASE contract; not audited.

Note:

Constants

executor

The source diamond's CCTPHookExecutor — the ONLY authorized caller of onCCTPHook.

address public immutable executor;

usdc

The USDC minted into this vault (e.g. Base Sepolia USDC in the showcase).

address public immutable usdc;

State Variables

creditOf

USDC booked to each beneficiary, withdrawable by them.

mapping(address beneficiary => uint256 amount) public creditOf;

totalCredited

Total USDC booked across all beneficiaries (== the USDC this vault holds against credits).

uint256 public totalCredited;

Functions

constructor

constructor(address executor_, address usdc_);

Parameters

NameTypeDescription
executor_addressThe diamond's CCTPHookExecutor (read from ICCTPBridgeAdapter.hookExecutor()).
usdc_addressThe destination-chain USDC that CCTP mints into this vault.

onCCTPHook

Invoked by the CCTPHookExecutor after the attested USDC mint, with Circle-attested context.

Books amount (attested net-minted USDC) to the beneficiary in the first 20 bytes of payload.

function onCCTPHook(
        uint32 sourceDomain,
        bytes32 sender,
        bytes32 mintRecipient,
        uint256 amount,
        bytes calldata payload
    ) external;

Parameters

NameTypeDescription
sourceDomainuint32The CCTP domain the burn originated on (from the attested message header).
senderbytes32The burner on the source domain, as a right-aligned bytes32 (attested).
mintRecipientbytes32The bytes32 recipient the USDC was minted to on this chain (attested).
amountuint256The USDC amount actually minted to mintRecipient (attested burn amount minus
attested feeExecuted).
payloadbytesATTACKER-CONTROLLED hook payload bytes (the Lattice envelope's tail). Untrusted.

withdraw

Withdraw amount of the caller's booked USDC to the caller (checks-effects-interactions).

function withdraw(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256

Events

Credited

event Credited(address indexed beneficiary, uint256 amount, uint32 sourceDomain, bytes32 sender);

Parameters

NameTypeDescription
beneficiaryaddress
amountuint256
sourceDomainuint32
senderbytes32

Withdrawn

event Withdrawn(address indexed beneficiary, uint256 amount);

Parameters

NameTypeDescription
beneficiaryaddress
amountuint256

Errors

CCTPHookVault__ZeroAddress

error CCTPHookVault__ZeroAddress();

CCTPHookVault__NotExecutor

error CCTPHookVault__NotExecutor();

CCTPHookVault__NotMintRecipient

error CCTPHookVault__NotMintRecipient();

CCTPHookVault__BadPayload

error CCTPHookVault__BadPayload();

CCTPHookVault__InsufficientCredit

error CCTPHookVault__InsufficientCredit();