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.
Script path: script/examples/Example05.s.sol
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. - Observe pending execution in CCIP Explorer and execute manually.
Before You Start
Important: Keystore first
Use a local keystore account for script execution:
cast wallet import myAccount --interactive Enter private key: Enter password: `myAccount` keystore was saved successfully. Address: <YOUR_EOA_ADDRESS_SHOULD_APPEAR_HERE>This chapter assumes
--account myAccount.
If you do not have a receiver deployed yet
Choose deployment based on your
blockConfirmations:forge script script/examples/Example04.s.sol:DeployBasicMessageReceiver \ --rpc-url polygonAmoy \ --account myAccount \ --broadcast \ --sig "run(address)" \ <DESTINATION_ROUTER>Use this for default finality (
blockConfirmations = 0). Save this as<BASIC_MESSAGE_RECEIVER_ADDRESS>.forge script script/examples/Example02.s.sol:DeployBasicMessageReceiverWithCCVs \ --rpc-url polygonAmoy \ --account myAccount \ --broadcast \ --sig "run(address)" \ <DESTINATION_ROUTER>If you use Fast Transfers (
blockConfirmations > 0), configure min block depth for your source chain:forge script script/examples/Example02.s.sol:SetBasicMessageReceiverWithCCVsMinBlockDepth \ --rpc-url polygonAmoy \ --account myAccount \ --broadcast \ --sig "run(address,uint64,uint16)" \ <BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS> \ <SOURCE_CHAIN_SELECTOR> \ <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>.
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 script/EncodeExtraArgsOffchain.s.sol:
encodeV3Basic(gasLimit, blockConfirmations)for a minimal V3 payload.getNoExecutionAddress()returnsClient.NO_EXECUTION_ADDRESSfor manual execution path.
Step 1: Send Message With No-Execution-Tag
forge script script/examples/Example05.s.sol:Example05 \
--rpc-url ethereumSepolia \
--account myAccount \
--broadcast \
--sig "run(address,uint64,address,string,uint32,uint16,address)" \
<SOURCE_ROUTER> \
<DESTINATION_CHAIN_SELECTOR> \
<BASIC_MESSAGE_RECEIVER_ADDRESS_OR_BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS> \
"Hello, World" \
<GAS_LIMIT> \
<BLOCK_CONFIRMATIONS> \
<FEE_TOKEN_ADDRESS>
Parameter notes:
<GAS_LIMIT>must be> 0because the receiver callback needs gas.<BLOCK_CONFIRMATIONS>can 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>: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass0x0000000000000000000000000000000000000000- This example sets executor to
NO_EXECUTION_ADDRESS, so execution is not automatic.
Verify Result
Example05 logs a CCIP message ID.
Use that ID in CCIP Explorer:
- https://ccip.chain.link
Expected behavior:
- Message is delivered to a pending/manual execution state because automatic execution is disabled.