Example 05: ExtraArgsV3 No-Execution-Tag (Manual Execution Path)
This example sends a Hello World data message from an EOA, but disables automatic execution by setting executor to NO_EXECUTION_ADDRESS inside ExtraArgsV3.
Task: example05 (implementation: tasks/Example05.ts).
What You Will Do
- Ensure a compatible destination receiver exists (default finality or Fast Transfers (FTF) based on your
blockConfirmations). - Send a CCIP data message with
ExtraArgsV3no-execution-tag using theexample05task. - Observe pending execution in CCIP Explorer and execute manually.
Before You Start
Important: Keystore first
Use a local keystore account for task execution:
npx hardhat keystore set AMOY_PRIVATE_KEY npx hardhat keystore set SEPOLIA_PRIVATE_KEY npx hardhat keystore set AMOY_RPC_URL npx hardhat keystore set SEPOLIA_RPC_URL
If you do not have a receiver deployed yet
Choose deployment based on your
blockConfirmations:npx hardhat ignition deploy ignition/modules/BasicMessageReceiver.ts --network <NETWORK_NAME> --parameters <PARAMETERS_FILE>Use this for default finality (
blockConfirmations = 0). Save this as<BASIC_MESSAGE_RECEIVER_ADDRESS>.npx hardhat ignition deploy ignition/modules/BasicMessageReceiverWithCCVs.ts --network <NETWORK_NAME> --parameters <PARAMETERS_FILE>If you use Fast Transfers (
blockConfirmations > 0), configure min block depth for your source chain:npx hardhat set-basic-message-receiver-with-ccvs-min-block-depth --network <NETWORK_NAME> \ --receiver <BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS> \ --source-chain-selector <SOURCE_CHAIN_SELECTOR> \ --min-block-depth <MIN_BLOCK_DEPTH>Use
<MIN_BLOCK_DEPTH> > 0for Fast Transfers.Use this for Fast Transfers (
blockConfirmations > 0). Save this as<BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS>.
--parametersis the path to the chain’s Ignition parameters JSON; it supplies router and other addresses to the module.
Understanding ExtraArgsV3
The ExtraArgsV3 is a structured set of delivery/execution options encoded and attached to a CCIP message.
struct GenericExtraArgsV3 {
uint32 gasLimit;
bytes4 requestedFinalityConfig;
address[] ccvs;
bytes[] ccvArgs;
address executor;
bytes executorArgs;
bytes tokenReceiver;
bytes tokenArgs;
}
(On-chain this struct lives in ExtraArgsCodec from @chainlink/contracts-ccip.)
gasLimit: gas allocated for callback execution on destination. If0and message data is empty, no callback executes.requestedFinalityConfig:bytes4finality mode + parameters perFinalityCodec(not a bareuint16). All-zero means wait for default/lane finality. For block-depth style Fast Transfers, encode withFinalityCodec._encodeBlockDepth(uint16)(see CCIP /FinalityCodecNatSpec). Example05 andEncodeExtraArgsOffchain.encodeV3/encodeV3Basictake ablockConfirmationsargument only as a convenience and set this field toFinalityCodec._encodeBlockDepth(blockConfirmations).ccvs: list of cross-chain verifier addresses. Empty means default verifiers.ccvArgs: optional arguments for each CCV. Must matchccvslength.executor: executor address on source chain.address(0)uses default executor.executorArgs: chain/executor-specific args (format depends on chain family/executor implementation).tokenReceiver: encoded destination token receiver. If empty, receiver address is used.tokenArgs: extra token transfer args (pool-specific format).
Related helpers in scripts/CallEncodeExtraArgsOffchain.ts:
encodeV3Basic(gasLimit, blockConfirmations)for a minimal V3 payload.getNoExecutionAddress()returnsClient.NO_EXECUTION_ADDRESSfor the manual execution path.
The example05 task uses these to build ExtraArgsV3 with the no-execution tag.
Step 1: Send Message With No-Execution-Tag
Run the example05 task. It sends a data-only message with executor set to NO_EXECUTION_ADDRESS, so execution stays pending until triggered manually.
npx hardhat example05 --network <NETWORK_NAME> \
--source-router <SOURCE_ROUTER> \
--destination-chain-selector <DESTINATION_CHAIN_SELECTOR> \
--receiver <BASIC_MESSAGE_RECEIVER_ADDRESS_OR_BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS> \
--message-text "Hello, World" \
--gas-limit <GAS_LIMIT> \
--block-confirmations <BLOCK_CONFIRMATIONS> \
--fee-token-address <FEE_TOKEN_ADDRESS>
Parameter notes:
--gas-limitmust be> 0because the receiver callback needs gas (e.g.200000).--block-confirmationscan be0(default finality) or> 0.- If
<BLOCK_CONFIRMATIONS> > 0, destination receiver must accept Fast Transfers (minBlockDepth > 0) for this source chain. - If
<BLOCK_CONFIRMATIONS> = 0, a default-finality receiver is sufficient. --fee-token-address: LINK token address on the source chain to pay fees in LINK, or0x0000000000000000000000000000000000000000to pay in native coin.- This example sets executor to
NO_EXECUTION_ADDRESS, so execution is not automatic; the message remains in a pending/manual execution state.
Defaults (can be omitted): --gas-limit 200000, --block-confirmations 1, --fee-token-address 0x0000000000000000000000000000000000000000.
Verify Result
The example05 task logs the CCIP message ID and a link to monitor.
Monitor and execute manually: https://ccip.chain.link
Expected behavior:
- Message is delivered to a pending/manual execution state because automatic execution is disabled.
- Use the CCIP Explorer to view the message and trigger execution manually when supported.