From 9685ad6da5d0d2381f5b3bbdf0bbae643c6a454d Mon Sep 17 00:00:00 2001 From: nje <8985830+Nalon@users.noreply.github.com> Date: Fri, 23 Oct 2026 16:49:38 -0700 Subject: [PATCH] docs(book): use environment variables instead of manual placeholders --- .env.example | 31 +++++ ...e01-token-transfer-faster-than-finality.md | 45 ++++--- ...2-hello-world-to-basic-message-receiver.md | 49 ++++--- ...grammable-token-transfer-data-and-token.md | 62 +++++---- ...ansfer-default-finality-sender-contract.md | 53 +++++--- ...rgsv3-no-execution-tag-manual-execution.md | 59 ++++++--- ...e06-cct01-burnmint-token-and-pool-setup.md | 125 ++++++++++-------- ...-cct02-lockrelease-token-and-pool-setup.md | 105 ++++++++------- ...cct03-burnmint-with-advanced-pool-hooks.md | 100 ++++++++------ ...-pool-based-ccvs-on-advanced-pool-hooks.md | 82 +++++++----- ...05-policy-engine-on-advanced-pool-hooks.md | 61 ++++++--- .../legacy01-extraargsv1-data-message.md | 33 +++-- .../legacy02-extraargsv2-data-message.md | 38 ++++-- book/src/index.md | 45 ++++++- book/src/tools/ccip-sdk-ccip-send.md | 36 +++-- book/src/tools/ccip-sdk-ccip-track.md | 10 +- book/src/tools/using-the-cli.md | 85 ++++++------ 17 files changed, 648 insertions(+), 371 deletions(-) diff --git a/.env.example b/.env.example index dc10a24..998fc55 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,37 @@ AVALANCHE_FUJI_RPC_URL=https://your-avalanche-fuji-rpc-url POLYGON_AMOY_RPC_URL=https://your-polygon-amoy-rpc-url BASE_SEPOLIA_RPC_URL=https://your-base-sepolia-rpc-url +# Your account address. Fill in with: cast wallet address --account myAccount +MY_EOA= + +# Network constants used by the book (book/src). Fill these in from https://docs.chain.link/ccip/directory +# (router, chain selector, LINK, CCIP-BnM, RMN/ARM proxy, registry module owner, token admin registry). +# Only fill the chains you plan to run. +# Ethereum Sepolia +SEPOLIA_CHAIN_SELECTOR= +SEPOLIA_ROUTER= +SEPOLIA_LINK= +SEPOLIA_CCIP_BNM= +SEPOLIA_ARM_PROXY= +SEPOLIA_REGISTRY_MODULE_OWNER_CUSTOM= +SEPOLIA_TOKEN_ADMIN_REGISTRY= +# Polygon Amoy +AMOY_CHAIN_SELECTOR= +AMOY_ROUTER= +AMOY_LINK= +AMOY_CCIP_BNM= +AMOY_ARM_PROXY= +AMOY_REGISTRY_MODULE_OWNER_CUSTOM= +AMOY_TOKEN_ADMIN_REGISTRY= +# Avalanche Fuji (Legacy examples) +FUJI_CHAIN_SELECTOR= +FUJI_ROUTER= +FUJI_LINK= +FUJI_CCIP_BNM= + +# Optional. The SDK examples (sdk-examples) read USER_KEY (or PRIVATE_KEY) for non-dry-run sends. +# USER_KEY= + # Optional. Fork tests (test/fork, FOUNDRY_PROFILE=fork) are pinned to the blocks in test/fork/utils/CCTForkTest.sol. # Set these to run against a different block, for example a recent one to check whether the live lane has drifted. # ETHEREUM_SEPOLIA_FORK_BLOCK= diff --git a/book/src/examples/example01-token-transfer-faster-than-finality.md b/book/src/examples/example01-token-transfer-faster-than-finality.md index 9039af1..01a0de7 100644 --- a/book/src/examples/example01-token-transfer-faster-than-finality.md +++ b/book/src/examples/example01-token-transfer-faster-than-finality.md @@ -26,6 +26,18 @@ Script path: `script/examples/Example01.s.sol` > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export GAS_LIMIT=0 # token-only transfer to an EOA +export BLOCK_CONFIRMATIONS=1 # Fast Transfers depth, must be > 0 +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +``` + ## Step 1: Get 1 CCIP-BnM Token Use the faucet script on the source chain: @@ -36,17 +48,18 @@ forge script script/Faucet.s.sol:Faucet \ --account myAccount \ --broadcast \ --sig "run(address)" \ - + $SEPOLIA_CCIP_BNM ``` ## Step 2: (Optional) Check Executor Allowed Finality Before choosing a Fast Transfers depth in `ExtraArgsV3`, you can read what finality modes the **Executor** allows. The on-chain API is **`getAllowedFinalityConfig() → bytes4`**, encoded with **`FinalityCodec`** (same family of values as `requestedFinalityConfig` in your message’s ExtraArgs). -From a shell (replace RPC and address): +From a shell. The executor address is printed as `[GATE] Executor:` by the finality-gates check further down this step; run that first, then export it: ```bash -cast call "getAllowedFinalityConfig()(bytes4)" --rpc-url ethereumSepolia +export EXECUTOR_ADDRESS=0x... +cast call $EXECUTOR_ADDRESS "getAllowedFinalityConfig()(bytes4)" --rpc-url ethereumSepolia ``` Why this matters: @@ -59,7 +72,7 @@ Check the source pool, executor, and CCV finality settings before sending: forge script script/examples/Example06.s.sol:Example06CheckFinalityGates \ --rpc-url ethereumSepolia \ --sig "run(address,uint64,address,uint16)" \ - + $SEPOLIA_ROUTER $AMOY_CHAIN_SELECTOR $SEPOLIA_CCIP_BNM $BLOCK_CONFIRMATIONS ``` A quote alone does not prove `ccipSend` will succeed with a non-`IPoolV2` pool. @@ -74,22 +87,22 @@ forge script script/examples/Example01.s.sol:Example01 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,uint16,address)" \ - \ - \ - \ - \ - \ - \ - \ - + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_CCIP_BNM \ + $AMOUNT \ + $GAS_LIMIT \ + $BLOCK_CONFIRMATIONS \ + $FEE_TOKEN ``` Parameter notes: -- ``: token amount in token decimals (for 18 decimals, `1e18` is 1 token). -- ``: set to `0` for token-only transfer to an EOA receiver. -- ``: must be `> 0` and meet the source pool and executor minimums from Step 2. -- ``: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass `0x0000000000000000000000000000000000000000` +- `$AMOUNT`: token amount in token decimals (for 18 decimals, `1e18` is 1 token). +- `$GAS_LIMIT`: set to `0` for token-only transfer to an EOA receiver. +- `$BLOCK_CONFIRMATIONS`: must be `> 0` and meet the source pool and executor minimums from Step 2. +- `$FEE_TOKEN`: native coin by default (`0x0000000000000000000000000000000000000000`). To pay CCIP fees in LINK instead, run `export FEE_TOKEN=$SEPOLIA_LINK`. ## Verify Result diff --git a/book/src/examples/example02-hello-world-to-basic-message-receiver.md b/book/src/examples/example02-hello-world-to-basic-message-receiver.md index 55e9d18..8567a8a 100644 --- a/book/src/examples/example02-hello-world-to-basic-message-receiver.md +++ b/book/src/examples/example02-hello-world-to-basic-message-receiver.md @@ -29,6 +29,17 @@ Scripts used: > > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export GAS_LIMIT=200000 # the receiver callback needs gas +export BLOCK_CONFIRMATIONS=1 # Fast Transfers depth, must be > 0 +export MIN_BLOCK_DEPTH=1 # receiver minimum, must be <= BLOCK_CONFIRMATIONS +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +``` + ## Receiver Contract Context ### Pre-v2.0 @@ -99,10 +110,14 @@ forge script script/examples/Example02.s.sol:DeployBasicMessageReceiverWithCCVs --account myAccount \ --broadcast \ --sig "run(address)" \ - + $AMOY_ROUTER ``` -Save the deployed address as ``. +Copy the deployed address from the `[RESULT]` log and export it: + +```bash +export BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS=0x... +``` By default, this receiver starts with `minBlockDepth = 0` (default finality only) for all source chains. @@ -116,12 +131,12 @@ forge script script/examples/Example02.s.sol:SetBasicMessageReceiverWithCCVsMinB --account myAccount \ --broadcast \ --sig "run(address,uint64,uint16)" \ - \ - \ - + $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ + $SEPOLIA_CHAIN_SELECTOR \ + $MIN_BLOCK_DEPTH ``` -For this chapter, use ` = 1`. +This chapter uses `MIN_BLOCK_DEPTH=1` (set in Chapter Parameters). - `0` means deafault finality-only behavior. - `> 0` enables Fast Transfers with that minimum depth. @@ -136,23 +151,23 @@ forge script script/examples/Example02.s.sol:Example02 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,string,uint32,uint16,address)" \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ "Hello, World" \ - \ - \ - + $GAS_LIMIT \ + $BLOCK_CONFIRMATIONS \ + $FEE_TOKEN ``` Parameter notes: -- `` must be `> 0` because the destination receiver callback needs gas. -- `` must be `> 0` for Fast Transfers. -- `` should be greater than or equal to ``. +- `$GAS_LIMIT` must be `> 0` because the destination receiver callback needs gas. +- `$BLOCK_CONFIRMATIONS` must be `> 0` for Fast Transfers. +- `$BLOCK_CONFIRMATIONS` should be greater than or equal to `$MIN_BLOCK_DEPTH`. - Executor may enforce a minimum block confirmations value and revert if too low. - If requested confirmations exceed chain finality, default finality is used. -- ``: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass `0x0000000000000000000000000000000000000000` +- `$FEE_TOKEN`: native coin by default (`0x0000000000000000000000000000000000000000`). To pay CCIP fees in LINK instead, run `export FEE_TOKEN=$SEPOLIA_LINK`. ## Verify Result @@ -165,5 +180,5 @@ Use that ID in the CCIP Explorer: You can inspect receiver state on destination chain: ```bash -cast call "latestMessage()(bytes)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS "latestMessage()(bytes)" --rpc-url polygonAmoy ``` diff --git a/book/src/examples/example03-programmable-token-transfer-data-and-token.md b/book/src/examples/example03-programmable-token-transfer-data-and-token.md index d0d40d1..177e13f 100644 --- a/book/src/examples/example03-programmable-token-transfer-data-and-token.md +++ b/book/src/examples/example03-programmable-token-transfer-data-and-token.md @@ -21,6 +21,18 @@ This chapter uses Fast Transfers (`blockConfirmations > 0`), so destination rece - Deploy `BasicMessageReceiverWithCCVs` before running this chapter. - For default-finality programmable token transfer (`blockConfirmations = 0`), use Example04. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export GAS_LIMIT=200000 # the receiver callback handles data +export BLOCK_CONFIRMATIONS=1 # Fast Transfers depth, must be > 0 +export MIN_BLOCK_DEPTH=1 # receiver minimum, must be <= BLOCK_CONFIRMATIONS +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +``` + ## Before You Start > **Important: Keystore first** @@ -46,7 +58,7 @@ This chapter uses Fast Transfers (`blockConfirmations > 0`), so destination rece > --account myAccount \ > --broadcast \ > --sig "run(address)" \ -> +> $AMOY_ROUTER > ``` > > Then configure min block depth for your source chain: @@ -57,16 +69,20 @@ This chapter uses Fast Transfers (`blockConfirmations > 0`), so destination rece > --account myAccount \ > --broadcast \ > --sig "run(address,uint64,uint16)" \ -> \ -> \ -> +> $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ +> $SEPOLIA_CHAIN_SELECTOR \ +> $MIN_BLOCK_DEPTH > ``` > -> For this Fast Transfers example, use ` > 0` and check the source pool minimum too. +> For this Fast Transfers example, `MIN_BLOCK_DEPTH` must be `> 0` (the default is `1`). Check the source pool minimum too. +> +> The script argument accepts `$MIN_BLOCK_DEPTH` (a `uint16` passed to `BasicMessageReceiverWithCCVs.setMinBlockDepth`). On-chain, the receiver does not return that integer directly to CCIP: `getCCVsAndFinalityConfig` sets `allowedFinalityConfig` to `FinalityCodec._encodeBlockDepth(minBlockDepth)` — the same `bytes4` finality encoding CCIP 2.0 uses elsewhere for allowed finality (depth `0` means wait for full/default finality). > -> The script argument accepts `` (a `uint16` passed to `BasicMessageReceiverWithCCVs.setMinBlockDepth`). On-chain, the receiver does not return that integer directly to CCIP: `getCCVsAndFinalityConfig` sets `allowedFinalityConfig` to `FinalityCodec._encodeBlockDepth(minBlockDepth)` — the same `bytes4` finality encoding CCIP 2.0 uses elsewhere for allowed finality (depth `0` means wait for full/default finality). +> Copy the receiver address from the `[RESULT]` log and export it for Step 2 below: > -> Save the receiver address from the `[RESULT]` log and use it in Step 2 below. +> ```bash +> export BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS=0x... +> ``` ## Step 1: Get 1 CCIP-BnM Token on Sepolia @@ -78,7 +94,7 @@ forge script script/Faucet.s.sol:Faucet \ --account myAccount \ --broadcast \ --sig "run(address)" \ - + $SEPOLIA_CCIP_BNM ``` ## Step 2: Send Hello World + CCIP-BnM @@ -89,25 +105,25 @@ forge script script/examples/Example03.s.sol:Example03 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,string,address,uint256,uint32,uint16,address)" \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ "Hello, World" \ - \ - \ - \ - \ - + $SEPOLIA_CCIP_BNM \ + $AMOUNT \ + $GAS_LIMIT \ + $BLOCK_CONFIRMATIONS \ + $FEE_TOKEN ``` Parameter notes: -- `` uses token decimals (`1e18` is 1 token for 18-decimal tokens). -- `` must be `> 0` because the receiver contract callback handles data. -- `` must meet the source pool and receiver minimums. +- `$AMOUNT` uses token decimals (`1e18` is 1 token for 18-decimal tokens). +- `$GAS_LIMIT` must be `> 0` because the receiver contract callback handles data. +- `$BLOCK_CONFIRMATIONS` must meet the source pool and receiver minimums. - Executor may enforce a minimum block confirmation value and revert if too low. - If requested confirmations exceed chain finality, default finality is used. -- ``: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass `0x0000000000000000000000000000000000000000` +- `$FEE_TOKEN`: native coin by default (`0x0000000000000000000000000000000000000000`). To pay CCIP fees in LINK instead, run `export FEE_TOKEN=$SEPOLIA_LINK`. ## Verify Result @@ -118,7 +134,7 @@ Parameter notes: Optional receiver checks on Amoy: ```bash -cast call "latestMessage()(bytes)" --rpc-url polygonAmoy -cast call "latestSender()(address)" --rpc-url polygonAmoy -cast call "latestSourceChainSelector()(uint64)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS "latestMessage()(bytes)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS "latestSender()(address)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS "latestSourceChainSelector()(uint64)" --rpc-url polygonAmoy ``` diff --git a/book/src/examples/example04-programmable-token-transfer-default-finality-sender-contract.md b/book/src/examples/example04-programmable-token-transfer-default-finality-sender-contract.md index 7048ff9..d1df908 100644 --- a/book/src/examples/example04-programmable-token-transfer-default-finality-sender-contract.md +++ b/book/src/examples/example04-programmable-token-transfer-default-finality-sender-contract.md @@ -21,6 +21,15 @@ Scripts used: 3. Mint 1 `CCIP-BnM` on Sepolia. 4. Quote fee, fund sender contract with that exact fee amount, then send data+token. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export GAS_LIMIT=200000 # the receiver callback handles data +``` + ## Before You Start > **Important: Keystore first** @@ -46,10 +55,14 @@ Scripts used: > --account myAccount \ > --broadcast \ > --sig "run(address)" \ -> +> $AMOY_ROUTER > ``` > -> Save the receiver address from the `[RESULT]` log and use it in Step 3. +> Copy the receiver address from the `[RESULT]` log and export it for Step 3: +> +> ```bash +> export BASIC_MESSAGE_RECEIVER_ADDRESS=0x... +> ``` ## Step 1: Deploy `BasicMessageSender` on Sepolia @@ -59,11 +72,15 @@ forge script script/examples/Example04.s.sol:DeployBasicMessageSender \ --account myAccount \ --broadcast \ --sig "run(address,address)" \ - \ - + $SEPOLIA_ROUTER \ + $SEPOLIA_LINK ``` -Save the deployed sender address from the `[RESULT]` log. +Copy the deployed sender address from the `[RESULT]` log and export it: + +```bash +export BASIC_MESSAGE_SENDER_ADDRESS=0x... +``` ## Step 2: Get 1 CCIP-BnM Token on Sepolia @@ -75,7 +92,7 @@ forge script script/Faucet.s.sol:Faucet \ --account myAccount \ --broadcast \ --sig "run(address)" \ - + $SEPOLIA_CCIP_BNM ``` ## Step 3: Send Hello World + CCIP-BnM Through Sender Contract @@ -86,21 +103,21 @@ forge script script/examples/Example04.s.sol:Example04 \ --account myAccount \ --broadcast \ --sig "run(address,address,uint64,address,string,address,uint256,uint32)" \ - \ - \ - \ - \ + $BASIC_MESSAGE_SENDER_ADDRESS \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $BASIC_MESSAGE_RECEIVER_ADDRESS \ "Hello, World" \ - \ - \ - + $SEPOLIA_CCIP_BNM \ + $AMOUNT \ + $GAS_LIMIT ``` Parameter notes: - This example always uses default finality by setting `blockConfirmations = 0` in the script. -- `` uses token decimals (`1e18` is 1 token for 18-decimal tokens). -- `` must be `> 0` because the receiver contract callback handles data. +- `$AMOUNT` uses token decimals (`1e18` is 1 token for 18-decimal tokens). +- `$GAS_LIMIT` must be `> 0` because the receiver contract callback handles data. - The script first quotes the fee, then funds sender contract with that exact amount before calling `send`. - If fee conditions change between quote and send, rerun the script to re-quote and retry. @@ -113,7 +130,7 @@ Parameter notes: Optional receiver checks on Amoy: ```bash -cast call "latestMessage()(bytes)" --rpc-url polygonAmoy -cast call "latestSender()(address)" --rpc-url polygonAmoy -cast call "latestSourceChainSelector()(uint64)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_ADDRESS "latestMessage()(bytes)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_ADDRESS "latestSender()(address)" --rpc-url polygonAmoy +cast call $BASIC_MESSAGE_RECEIVER_ADDRESS "latestSourceChainSelector()(uint64)" --rpc-url polygonAmoy ``` diff --git a/book/src/examples/example05-extraargsv3-no-execution-tag-manual-execution.md b/book/src/examples/example05-extraargsv3-no-execution-tag-manual-execution.md index 784e760..a9cd596 100644 --- a/book/src/examples/example05-extraargsv3-no-execution-tag-manual-execution.md +++ b/book/src/examples/example05-extraargsv3-no-execution-tag-manual-execution.md @@ -10,6 +10,17 @@ Script path: `script/examples/Example05.s.sol` 2. Send a CCIP data message with `ExtraArgsV3` no-execution-tag. 3. Observe pending execution in CCIP Explorer and execute manually. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export GAS_LIMIT=200000 # the receiver callback needs gas +export BLOCK_CONFIRMATIONS=0 # 0 = default finality, > 0 = Fast Transfers +export MIN_BLOCK_DEPTH=1 # only used if you deploy the CCVs receiver for Fast Transfers +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +``` + ## Before You Start > **Important: Keystore first** @@ -35,10 +46,15 @@ Script path: `script/examples/Example05.s.sol` > --account myAccount \ > --broadcast \ > --sig "run(address)" \ -> +> $AMOY_ROUTER > ``` > -> Use this for default finality (`blockConfirmations = 0`). Save this as ``. +> Use this for default finality (`blockConfirmations = 0`). Copy the address from the `[RESULT]` log and export it: +> +> ```bash +> export BASIC_MESSAGE_RECEIVER_ADDRESS=0x... +> export RECEIVER=$BASIC_MESSAGE_RECEIVER_ADDRESS +> ``` > > ```bash > forge script script/examples/Example02.s.sol:DeployBasicMessageReceiverWithCCVs \ @@ -46,7 +62,7 @@ Script path: `script/examples/Example05.s.sol` > --account myAccount \ > --broadcast \ > --sig "run(address)" \ -> +> $AMOY_ROUTER > ``` > > If you use Fast Transfers (`blockConfirmations > 0`), configure min block depth for your source chain: @@ -57,14 +73,19 @@ Script path: `script/examples/Example05.s.sol` > --account myAccount \ > --broadcast \ > --sig "run(address,uint64,uint16)" \ -> \ -> \ -> +> $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ +> $SEPOLIA_CHAIN_SELECTOR \ +> $MIN_BLOCK_DEPTH > ``` > -> Use ` > 0` for Fast Transfers. +> `MIN_BLOCK_DEPTH` must be `> 0` for Fast Transfers. +> +> Use this for Fast Transfers (`blockConfirmations > 0`). Copy the address of the `DeployBasicMessageReceiverWithCCVs` deployment from the `[RESULT]` log and export it before running the min block depth command above: > -> Use this for Fast Transfers (`blockConfirmations > 0`). Save this as ``. +> ```bash +> export BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS=0x... +> export RECEIVER=$BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS +> ``` ## Understanding ExtraArgsV3 @@ -107,22 +128,22 @@ forge script script/examples/Example05.s.sol:Example05 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,string,uint32,uint16,address)" \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ "Hello, World" \ - \ - \ - + $GAS_LIMIT \ + $BLOCK_CONFIRMATIONS \ + $FEE_TOKEN ``` Parameter notes: -- `` must be `> 0` because the receiver callback needs gas. -- `` can be `0` (default finality) or `> 0`. -- If ` > 0`, destination receiver must accept Fast Transfers (`minBlockDepth > 0`) for this source chain. -- If ` = 0`, a default-finality receiver is sufficient. -- ``: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass `0x0000000000000000000000000000000000000000` +- `$GAS_LIMIT` must be `> 0` because the receiver callback needs gas. +- `$BLOCK_CONFIRMATIONS` can be `0` (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`: native coin by default (`0x0000000000000000000000000000000000000000`). To pay CCIP fees in LINK instead, run `export FEE_TOKEN=$SEPOLIA_LINK`. - This example sets executor to `NO_EXECUTION_ADDRESS`, so execution is not automatic. ## Verify Result diff --git a/book/src/examples/example06-cct01-burnmint-token-and-pool-setup.md b/book/src/examples/example06-cct01-burnmint-token-and-pool-setup.md index ef80492..16a8e7a 100644 --- a/book/src/examples/example06-cct01-burnmint-token-and-pool-setup.md +++ b/book/src/examples/example06-cct01-burnmint-token-and-pool-setup.md @@ -33,6 +33,19 @@ Scripts used: > > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA on Amoy +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export GAS_LIMIT=0 # token-only transfer to an EOA +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +export BLOCK_CONFIRMATIONS=1 # Fast Transfers depth, must be > 0 +export ALLOWED_FINALITY_CONFIG=0x00000001 # pool minimum block depth (Step 5) +``` + ## Script Defaults `DeployCCTBurnMintTokenAndPool` deploys a **CrossChainToken** (via `BaseERC20.ConstructorParams`) with: @@ -72,16 +85,18 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:DeployCCTBurnMi --account myAccount \ --broadcast \ --sig "run(address,address,address,address)" \ - \ - \ - \ - + $SEPOLIA_TOKEN_ADMIN_REGISTRY \ + $SEPOLIA_REGISTRY_MODULE_OWNER_CUSTOM \ + $SEPOLIA_ARM_PROXY \ + $SEPOLIA_ROUTER ``` -Save from logs: +Copy these from the logs and export them: -- `` -- `` +```bash +export SEPOLIA_TOKEN_ADDRESS=0x... +export SEPOLIA_POOL_ADDRESS=0x... +``` ## Step 2: Deploy Token + Pool on Amoy (destination) @@ -91,16 +106,18 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:DeployCCTBurnMi --account myAccount \ --broadcast \ --sig "run(address,address,address,address)" \ - \ - \ - \ - + $AMOY_TOKEN_ADMIN_REGISTRY \ + $AMOY_REGISTRY_MODULE_OWNER_CUSTOM \ + $AMOY_ARM_PROXY \ + $AMOY_ROUTER ``` -Save from logs: +Copy these from the logs and export them: -- `` -- `` +```bash +export AMOY_TOKEN_ADDRESS=0x... +export AMOY_POOL_ADDRESS=0x... +``` ## Step 3: Configure Sepolia Pool With Amoy Remote @@ -110,10 +127,10 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:Example06 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address)" \ - \ - \ - \ - + $SEPOLIA_POOL_ADDRESS \ + $AMOY_CHAIN_SELECTOR \ + $AMOY_TOKEN_ADDRESS \ + $AMOY_POOL_ADDRESS ``` ## Step 4: Configure Amoy Pool With Sepolia Remote @@ -124,10 +141,10 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:Example06 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address)" \ - \ - \ - \ - + $AMOY_POOL_ADDRESS \ + $SEPOLIA_CHAIN_SELECTOR \ + $SEPOLIA_TOKEN_ADDRESS \ + $SEPOLIA_POOL_ADDRESS ``` ## Step 5: Enable Fast Transfers on Both Pools @@ -140,21 +157,21 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:Example06SetPoo --account myAccount \ --broadcast \ --sig "run(address,bytes4)" \ - \ - + $SEPOLIA_POOL_ADDRESS \ + $ALLOWED_FINALITY_CONFIG ``` -Repeat on Amoy with `--rpc-url polygonAmoy` and ``. Read back each pool: +Repeat on Amoy with `--rpc-url polygonAmoy` and `$AMOY_POOL_ADDRESS`. Read back each pool: ```bash FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:Example06GetPoolAllowedFinalityConfig \ --rpc-url ethereumSepolia \ --sig "run(address)" \ - + $SEPOLIA_POOL_ADDRESS FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:Example06GetPoolAllowedFinalityConfig \ --rpc-url polygonAmoy \ --sig "run(address)" \ - + $AMOY_POOL_ADDRESS ``` `0x00000000` disables FTF; values `0x00000001`–`0x0000ffff` set the minimum block depth. The staged wait-for-safe flag is not usable @@ -168,10 +185,10 @@ The read-only check reports the pool, executor, and CCV settings before an FTF s FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:Example06CheckFinalityGates \ --rpc-url ethereumSepolia \ --sig "run(address,uint64,address,uint16)" \ - \ - \ - \ - + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $SEPOLIA_TOKEN_ADDRESS \ + $BLOCK_CONFIRMATIONS ``` A `getFee` quote alone does not prove `ccipSend` will succeed for a non-`IPoolV2` pool. @@ -184,23 +201,21 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,address)" \ - \ - \ - \ - \ - \ - \ - + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS \ + $AMOUNT \ + $GAS_LIMIT \ + $FEE_TOKEN ``` Parameter notes: -- `` uses token decimals (`1e18` is 1 token for 18-decimal token). -- For token-only transfer to EOA receiver, use `` = `0`. +- `$AMOUNT` uses token decimals (`1e18` is 1 token for 18-decimal token). +- For token-only transfer to EOA receiver, use `$GAS_LIMIT` = `0`. - This sender uses `ExtraArgsV3` with `blockConfirmations = 0` (default finality). -- ``: - - native fee: `0x0000000000000000000000000000000000000000` - - LINK fee: LINK token address on Sepolia (the source chain) +- `$FEE_TOKEN`: native fee by default. For a LINK fee, run `export FEE_TOKEN=$SEPOLIA_LINK`. For the FTF version, use the existing custom-finality sender after Steps 5 and 6: @@ -210,8 +225,8 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,uint16,address)" \ - \ - + $SEPOLIA_ROUTER $AMOY_CHAIN_SELECTOR $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS $AMOUNT $GAS_LIMIT $BLOCK_CONFIRMATIONS $FEE_TOKEN ``` ## Step 8: Verify BurnMint Behavior @@ -219,26 +234,26 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit Verify token->pool registration: ```bash -cast call "getPool(address)(address)" --rpc-url ethereumSepolia -cast call "getPool(address)(address)" --rpc-url polygonAmoy +cast call $SEPOLIA_TOKEN_ADMIN_REGISTRY "getPool(address)(address)" $SEPOLIA_TOKEN_ADDRESS --rpc-url ethereumSepolia +cast call $AMOY_TOKEN_ADMIN_REGISTRY "getPool(address)(address)" $AMOY_TOKEN_ADDRESS --rpc-url polygonAmoy ``` Verify remote lane mapping: ```bash -cast call "getRemoteToken(uint64)(bytes)" --rpc-url ethereumSepolia -cast call "getRemotePools(uint64)(bytes[])" --rpc-url ethereumSepolia -cast call "getRemoteToken(uint64)(bytes)" --rpc-url polygonAmoy -cast call "getRemotePools(uint64)(bytes[])" --rpc-url polygonAmoy +cast call $SEPOLIA_POOL_ADDRESS "getRemoteToken(uint64)(bytes)" $AMOY_CHAIN_SELECTOR --rpc-url ethereumSepolia +cast call $SEPOLIA_POOL_ADDRESS "getRemotePools(uint64)(bytes[])" $AMOY_CHAIN_SELECTOR --rpc-url ethereumSepolia +cast call $AMOY_POOL_ADDRESS "getRemoteToken(uint64)(bytes)" $SEPOLIA_CHAIN_SELECTOR --rpc-url polygonAmoy +cast call $AMOY_POOL_ADDRESS "getRemotePools(uint64)(bytes[])" $SEPOLIA_CHAIN_SELECTOR --rpc-url polygonAmoy ``` Verify balances and supplies after transfer finalizes: ```bash -cast call "balanceOf(address)(uint256)" --rpc-url ethereumSepolia -cast call "balanceOf(address)(uint256)" --rpc-url polygonAmoy -cast call "totalSupply()(uint256)" --rpc-url ethereumSepolia -cast call "totalSupply()(uint256)" --rpc-url polygonAmoy +cast call $SEPOLIA_TOKEN_ADDRESS "balanceOf(address)(uint256)" $MY_EOA --rpc-url ethereumSepolia +cast call $AMOY_TOKEN_ADDRESS "balanceOf(address)(uint256)" $RECEIVER --rpc-url polygonAmoy +cast call $SEPOLIA_TOKEN_ADDRESS "totalSupply()(uint256)" --rpc-url ethereumSepolia +cast call $AMOY_TOKEN_ADDRESS "totalSupply()(uint256)" --rpc-url polygonAmoy ``` Monitor message status with the message ID on: diff --git a/book/src/examples/example07-cct02-lockrelease-token-and-pool-setup.md b/book/src/examples/example07-cct02-lockrelease-token-and-pool-setup.md index 7656692..dc069b4 100644 --- a/book/src/examples/example07-cct02-lockrelease-token-and-pool-setup.md +++ b/book/src/examples/example07-cct02-lockrelease-token-and-pool-setup.md @@ -30,6 +30,17 @@ Scripts used: > > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA on Amoy +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +export LIQUIDITY_AMOUNT=10000000000000000000 # 10 tokens for the Amoy lock box (Step 5) +``` + ## Script Defaults `DeployCCTLockReleaseTokenAndPool` deploys a **CrossChainToken** (same defaults as Example 06) for the underlying ERC-20, with: @@ -68,17 +79,19 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example07.s.sol:DeployCCTLockRe --account myAccount \ --broadcast \ --sig "run(address,address,address,address)" \ - \ - \ - \ - + $SEPOLIA_TOKEN_ADMIN_REGISTRY \ + $SEPOLIA_REGISTRY_MODULE_OWNER_CUSTOM \ + $SEPOLIA_ARM_PROXY \ + $SEPOLIA_ROUTER ``` -Save from logs: +Copy these from the logs and export them: -- `` -- `` -- `` +```bash +export SEPOLIA_TOKEN_ADDRESS=0x... +export SEPOLIA_LOCKBOX_ADDRESS=0x... +export SEPOLIA_POOL_ADDRESS=0x... +``` ## Step 2: Deploy Token + Lock Box + Pool on Amoy @@ -88,17 +101,19 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example07.s.sol:DeployCCTLockRe --account myAccount \ --broadcast \ --sig "run(address,address,address,address)" \ - \ - \ - \ - + $AMOY_TOKEN_ADMIN_REGISTRY \ + $AMOY_REGISTRY_MODULE_OWNER_CUSTOM \ + $AMOY_ARM_PROXY \ + $AMOY_ROUTER ``` -Save from logs: +Copy these from the logs and export them: -- `` -- `` -- `` +```bash +export AMOY_TOKEN_ADDRESS=0x... +export AMOY_LOCKBOX_ADDRESS=0x... +export AMOY_POOL_ADDRESS=0x... +``` ## Step 3: Configure Sepolia Pool With Amoy Remote @@ -108,10 +123,10 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example07.s.sol:Example07 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address)" \ - \ - \ - \ - + $SEPOLIA_POOL_ADDRESS \ + $AMOY_CHAIN_SELECTOR \ + $AMOY_TOKEN_ADDRESS \ + $AMOY_POOL_ADDRESS ``` ## Step 4: Configure Amoy Pool With Sepolia Remote @@ -122,10 +137,10 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example07.s.sol:Example07 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address)" \ - \ - \ - \ - + $AMOY_POOL_ADDRESS \ + $SEPOLIA_CHAIN_SELECTOR \ + $SEPOLIA_TOKEN_ADDRESS \ + $SEPOLIA_POOL_ADDRESS ``` ## Step 5: Fund Destination Lock Box Liquidity @@ -138,9 +153,9 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example07.s.sol:FundCCTLockBoxL --account myAccount \ --broadcast \ --sig "run(address,address,uint256)" \ - \ - \ - + $AMOY_TOKEN_ADDRESS \ + $AMOY_LOCKBOX_ADDRESS \ + $LIQUIDITY_AMOUNT ``` If you also want Amoy -> Sepolia transfers, fund Sepolia lock box too with the same script. @@ -153,48 +168,46 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,address)" \ - \ - \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS \ + $AMOUNT \ 0 \ - + $FEE_TOKEN ``` Parameter notes: -- `` uses token decimals (`1e18` is 1 token for 18-decimal token). +- `$AMOUNT` uses token decimals (`1e18` is 1 token for 18-decimal token). - `gasLimit` is set to `0` in this command because this is token-only transfer to an EOA receiver. - This sender uses `ExtraArgsV3` with `blockConfirmations = 0` (default finality). -- ``: - - native fee: `0x0000000000000000000000000000000000000000` - - LINK fee: LINK token address on Sepolia +- `$FEE_TOKEN`: native fee by default. For a LINK fee, run `export FEE_TOKEN=$SEPOLIA_LINK`. ## Step 7: Verify LockRelease Behavior Verify token->pool registration: ```bash -cast call "getPool(address)(address)" --rpc-url ethereumSepolia -cast call "getPool(address)(address)" --rpc-url polygonAmoy +cast call $SEPOLIA_TOKEN_ADMIN_REGISTRY "getPool(address)(address)" $SEPOLIA_TOKEN_ADDRESS --rpc-url ethereumSepolia +cast call $AMOY_TOKEN_ADMIN_REGISTRY "getPool(address)(address)" $AMOY_TOKEN_ADDRESS --rpc-url polygonAmoy ``` Verify remote lane mapping: ```bash -cast call "getRemoteToken(uint64)(bytes)" --rpc-url ethereumSepolia -cast call "getRemotePools(uint64)(bytes[])" --rpc-url ethereumSepolia -cast call "getRemoteToken(uint64)(bytes)" --rpc-url polygonAmoy -cast call "getRemotePools(uint64)(bytes[])" --rpc-url polygonAmoy +cast call $SEPOLIA_POOL_ADDRESS "getRemoteToken(uint64)(bytes)" $AMOY_CHAIN_SELECTOR --rpc-url ethereumSepolia +cast call $SEPOLIA_POOL_ADDRESS "getRemotePools(uint64)(bytes[])" $AMOY_CHAIN_SELECTOR --rpc-url ethereumSepolia +cast call $AMOY_POOL_ADDRESS "getRemoteToken(uint64)(bytes)" $SEPOLIA_CHAIN_SELECTOR --rpc-url polygonAmoy +cast call $AMOY_POOL_ADDRESS "getRemotePools(uint64)(bytes[])" $SEPOLIA_CHAIN_SELECTOR --rpc-url polygonAmoy ``` Verify lock box balances and receiver balance after transfer finalizes: ```bash -cast call "balanceOf(address)(uint256)" --rpc-url ethereumSepolia -cast call "balanceOf(address)(uint256)" --rpc-url polygonAmoy -cast call "balanceOf(address)(uint256)" --rpc-url polygonAmoy +cast call $SEPOLIA_TOKEN_ADDRESS "balanceOf(address)(uint256)" $SEPOLIA_LOCKBOX_ADDRESS --rpc-url ethereumSepolia +cast call $AMOY_TOKEN_ADDRESS "balanceOf(address)(uint256)" $AMOY_LOCKBOX_ADDRESS --rpc-url polygonAmoy +cast call $AMOY_TOKEN_ADDRESS "balanceOf(address)(uint256)" $RECEIVER --rpc-url polygonAmoy ``` Monitor message status with the message ID on: diff --git a/book/src/examples/example08-cct03-burnmint-with-advanced-pool-hooks.md b/book/src/examples/example08-cct03-burnmint-with-advanced-pool-hooks.md index 17412cc..15f2741 100644 --- a/book/src/examples/example08-cct03-burnmint-with-advanced-pool-hooks.md +++ b/book/src/examples/example08-cct03-burnmint-with-advanced-pool-hooks.md @@ -53,6 +53,16 @@ Scripts used: > > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA on Amoy +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +``` + ## Script Defaults `DeployCCTBurnMintTokenAndPoolWithAdvancedPoolHook` deploys **CrossChainToken** with the same token defaults as Example 06 (`BaseERC20.ConstructorParams` + `registerAdminViaGetCCIPAdmin`): @@ -90,18 +100,20 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:DeployCCTBurnMi --account myAccount \ --broadcast \ --sig "run(address,address,address,address,uint256)" \ - \ - \ - \ - \ + $SEPOLIA_TOKEN_ADMIN_REGISTRY \ + $SEPOLIA_REGISTRY_MODULE_OWNER_CUSTOM \ + $SEPOLIA_ARM_PROXY \ + $SEPOLIA_ROUTER \ 1 ``` -Save from logs: +Copy these from the logs and export them: -- `` -- `` -- `` +```bash +export SEPOLIA_TOKEN_ADDRESS=0x... +export SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS=0x... +export SEPOLIA_POOL_ADDRESS=0x... +``` ## Step 2: Deploy Token + Hook + Pool on Amoy @@ -111,18 +123,20 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:DeployCCTBurnMi --account myAccount \ --broadcast \ --sig "run(address,address,address,address,uint256)" \ - \ - \ - \ - \ + $AMOY_TOKEN_ADMIN_REGISTRY \ + $AMOY_REGISTRY_MODULE_OWNER_CUSTOM \ + $AMOY_ARM_PROXY \ + $AMOY_ROUTER \ 1 ``` -Save from logs: +Copy these from the logs and export them: -- `` -- `` -- `` +```bash +export AMOY_TOKEN_ADDRESS=0x... +export AMOY_ADVANCED_POOL_HOOK_ADDRESS=0x... +export AMOY_POOL_ADDRESS=0x... +``` ## Step 3: Configure Sepolia Pool With Amoy Remote @@ -132,10 +146,10 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:Example08 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address)" \ - \ - \ - \ - + $SEPOLIA_POOL_ADDRESS \ + $AMOY_CHAIN_SELECTOR \ + $AMOY_TOKEN_ADDRESS \ + $AMOY_POOL_ADDRESS ``` ## Step 4: Configure Amoy Pool With Sepolia Remote @@ -146,10 +160,10 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:Example08 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address)" \ - \ - \ - \ - + $AMOY_POOL_ADDRESS \ + $SEPOLIA_CHAIN_SELECTOR \ + $SEPOLIA_TOKEN_ADDRESS \ + $SEPOLIA_POOL_ADDRESS ``` ## Step 5: Send Transfer (Reuse Example06 Sender) @@ -160,13 +174,13 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,address)" \ - \ - \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS \ + $AMOUNT \ 0 \ - + $FEE_TOKEN ``` ## Optional: Update Hook Allowlist @@ -176,26 +190,28 @@ Use this if you want to add or remove senders in the allowlist after deployment. Add one sender address: ```bash +export ADDRESS_TO_ADD=0x... FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:Example08UpdateAllowlist \ --rpc-url ethereumSepolia \ --account myAccount \ --broadcast \ --sig "run(address,address[],address[])" \ - \ + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS \ "[]" \ - "[]" + "[$ADDRESS_TO_ADD]" ``` Remove one sender address: ```bash +export ADDRESS_TO_REMOVE=0x... FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:Example08UpdateAllowlist \ --rpc-url ethereumSepolia \ --account myAccount \ --broadcast \ --sig "run(address,address[],address[])" \ - \ - "[]" \ + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS \ + "[$ADDRESS_TO_REMOVE]" \ "[]" ``` @@ -204,24 +220,24 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example08.s.sol:Example08Update Verify token->pool registration: ```bash -cast call "getPool(address)(address)" --rpc-url ethereumSepolia -cast call "getPool(address)(address)" --rpc-url polygonAmoy +cast call $SEPOLIA_TOKEN_ADMIN_REGISTRY "getPool(address)(address)" $SEPOLIA_TOKEN_ADDRESS --rpc-url ethereumSepolia +cast call $AMOY_TOKEN_ADMIN_REGISTRY "getPool(address)(address)" $AMOY_TOKEN_ADDRESS --rpc-url polygonAmoy ``` Verify attached hook on each pool: ```bash -cast call "getAdvancedPoolHooks()(address)" --rpc-url ethereumSepolia -cast call "getAdvancedPoolHooks()(address)" --rpc-url polygonAmoy +cast call $SEPOLIA_POOL_ADDRESS "getAdvancedPoolHooks()(address)" --rpc-url ethereumSepolia +cast call $AMOY_POOL_ADDRESS "getAdvancedPoolHooks()(address)" --rpc-url polygonAmoy ``` Verify allowlist status: ```bash -cast call "getAllowListEnabled()(bool)" --rpc-url ethereumSepolia -cast call "getAllowList()(address[])" --rpc-url ethereumSepolia -cast call "getAllowListEnabled()(bool)" --rpc-url polygonAmoy -cast call "getAllowList()(address[])" --rpc-url polygonAmoy +cast call $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS "getAllowListEnabled()(bool)" --rpc-url ethereumSepolia +cast call $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS "getAllowList()(address[])" --rpc-url ethereumSepolia +cast call $AMOY_ADVANCED_POOL_HOOK_ADDRESS "getAllowListEnabled()(bool)" --rpc-url polygonAmoy +cast call $AMOY_ADVANCED_POOL_HOOK_ADDRESS "getAllowList()(address[])" --rpc-url polygonAmoy ``` Monitor message status with the message ID on: diff --git a/book/src/examples/example09-cct04-pool-based-ccvs-on-advanced-pool-hooks.md b/book/src/examples/example09-cct04-pool-based-ccvs-on-advanced-pool-hooks.md index 2eb1fdb..7313091 100644 --- a/book/src/examples/example09-cct04-pool-based-ccvs-on-advanced-pool-hooks.md +++ b/book/src/examples/example09-cct04-pool-based-ccvs-on-advanced-pool-hooks.md @@ -36,12 +36,12 @@ Scripts used: > **Note on real CCVs** > -> This starter kit does not deploy a real CCV. To try pool-based CCVs end to end on the live testnets, deploy your own CCV with the [CCV starter kit](https://docs.chain.link/ccip/ccv-starter-kit) and use its resolver address as `` below. The short version: +> This starter kit does not deploy a real CCV. To try pool-based CCVs end to end on the live testnets, deploy your own CCV with the [CCV starter kit](https://docs.chain.link/ccip/ccv-starter-kit) and use its resolver address as `$CCV_ADDRESS` below. The short version: > > 1. **On-chain contracts, on both chains** — use the [on-chain contracts kit](https://github.com/smartcontractkit/chainlink-ccv-starter-kit-contracts) to deploy the CREATE2 factory, the `VersionedVerifierResolver`, and the committee verifier, then apply the lane and signature config. The kit's [full flow](https://github.com/smartcontractkit/chainlink-ccv-starter-kit-contracts/blob/main/docs/src/full-flow.md) walks the exact `make` commands; the resolver lands at the same address on both chains by construction (`make deployments-check` asserts the parity). > 2. **Off-chain cell** — use the [off-chain kit](https://github.com/smartcontractkit/chainlink-ccv-starter-kit) to run the verifier and aggregator that actually attest messages (a Helm chart in Kubernetes, or the [local docker-compose stack](https://github.com/smartcontractkit/chainlink-ccv-starter-kit/tree/main/local) for testing). Without a running cell, the CCV exists on-chain but never attests, so messages requiring it will not execute. > -> Use the **resolver** address (not the committee verifier implementation) as ``: a pool that lists the implementation address reverts during the fee quote. +> Use the **resolver** address (not the committee verifier implementation) as `$CCV_ADDRESS`: a pool that lists the implementation address reverts during the fee quote. ## Before You Start @@ -58,16 +58,33 @@ Scripts used: > > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. Everything except `CCV_ADDRESS` has a working default. + +```bash +export RECEIVER=$MY_EOA # destination EOA on Amoy +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +export CCV_ADDRESS=0x... # your CCV resolver address, the same on both chains (see the note above) +``` + ## Step 1: Deploy Token + Hook + Pool on Both Chains -Follow Example 08 steps 1-4 to deploy the token, hook and pool on both chains and link the lanes. Save from the logs: +Follow Example 08 steps 1-4 to deploy the token, hook and pool on both chains and link the lanes. If you ran them in this terminal, these variables are already exported. Otherwise copy them from the logs: -- ``, ``, `` -- ``, ``, `` +```bash +export SEPOLIA_TOKEN_ADDRESS=0x... +export SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS=0x... +export SEPOLIA_POOL_ADDRESS=0x... +export AMOY_TOKEN_ADDRESS=0x... +export AMOY_ADVANCED_POOL_HOOK_ADDRESS=0x... +export AMOY_POOL_ADDRESS=0x... +``` ## Step 2: Set Pool CCV Config on Sepolia -Require `` for both outbound and inbound traffic to Amoy: +Require `$CCV_ADDRESS` for both outbound and inbound traffic to Amoy: ```bash FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetPoolCCVConfig \ @@ -75,17 +92,17 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetPoo --account myAccount \ --broadcast \ --sig "run(address,uint64,address[],address[],address[],address[])" \ - \ - \ - "[]" \ + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS \ + $AMOY_CHAIN_SELECTOR \ + "[$CCV_ADDRESS]" \ "[]" \ - "[]" \ + "[$CCV_ADDRESS]" \ "[]" ``` ## Step 3: Set Pool CCV Config on Amoy -Require the same `` for traffic to Sepolia: +Require the same `$CCV_ADDRESS` for traffic to Sepolia: ```bash FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetPoolCCVConfig \ @@ -93,11 +110,11 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetPoo --account myAccount \ --broadcast \ --sig "run(address,uint64,address[],address[],address[],address[])" \ - \ - \ - "[]" \ + $AMOY_ADVANCED_POOL_HOOK_ADDRESS \ + $SEPOLIA_CHAIN_SELECTOR \ + "[$CCV_ADDRESS]" \ "[]" \ - "[]" \ + "[$CCV_ADDRESS]" \ "[]" ``` @@ -109,23 +126,24 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,address)" \ - \ - \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS \ + $AMOUNT \ 0 \ - + $FEE_TOKEN ``` -The source OnRamp now consults `` outbound, and the destination OffRamp verifies the message with the same address before minting. +The source OnRamp now consults `$CCV_ADDRESS` outbound, and the destination OffRamp verifies the message with the same address before minting. > **Note on execution with a self-run CCV** > > Until your CCV is onboarded into the CCIP indexer, the default executor cannot fetch its attestation, so the message sits at `UNTOUCHED` after it is sent. Execute it yourself with the [CCIP CLI](https://docs.chain.link/ccip/tools/cli/) (1.14.0 or later), reading the attestation directly from your own aggregator: > > ```bash -> ccip-cli manual-exec --verifiers grpcs://:443 +> export SOURCE_TX_HASH=0x... # transaction hash of your send +> ccip-cli manual-exec $SOURCE_TX_HASH --verifiers grpcs://:443 > ``` > > See [Test your setup](https://docs.chain.link/ccip/ccv-starter-kit/evm/test-your-setup) in the CCV starter kit docs for the full walkthrough. @@ -140,7 +158,7 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetThr --account myAccount \ --broadcast \ --sig "run(address,uint256)" \ - \ + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS \ 10000000000000000000000 ``` @@ -152,11 +170,11 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetThr --account myAccount \ --broadcast \ --sig "run(address,uint256)" \ - \ + $AMOY_ADVANCED_POOL_HOOK_ADDRESS \ 10000000000000000000000 ``` -To use threshold CCVs, set a config with non-empty threshold lists, for example base `[]` and threshold `[]` (duplicates across lists are rejected). +To use threshold CCVs, set a config with non-empty threshold lists, for example base `[$CCV_ADDRESS]` and threshold `[$SECOND_CCV_ADDRESS]` (`export SECOND_CCV_ADDRESS=0x...` first) (duplicates across lists are rejected). ## Step 6: Clear the CCV Config @@ -168,8 +186,8 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetPoo --account myAccount \ --broadcast \ --sig "run(address,uint64,address[],address[],address[],address[])" \ - \ - \ + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS \ + $AMOY_CHAIN_SELECTOR \ "[]" \ "[]" \ "[]" \ @@ -181,15 +199,15 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example09.s.sol:Example09SetPoo Verify the stored CCV config: ```bash -cast call "getCCVConfig(uint64)((address[],address[],address[],address[]))" --rpc-url ethereumSepolia -cast call "getCCVConfig(uint64)((address[],address[],address[],address[]))" --rpc-url polygonAmoy +cast call $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS "getCCVConfig(uint64)((address[],address[],address[],address[]))" $AMOY_CHAIN_SELECTOR --rpc-url ethereumSepolia +cast call $AMOY_ADVANCED_POOL_HOOK_ADDRESS "getCCVConfig(uint64)((address[],address[],address[],address[]))" $SEPOLIA_CHAIN_SELECTOR --rpc-url polygonAmoy ``` Verify the threshold amount: ```bash -cast call "getThresholdAmount()(uint256)" --rpc-url ethereumSepolia -cast call "getThresholdAmount()(uint256)" --rpc-url polygonAmoy +cast call $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS "getThresholdAmount()(uint256)" --rpc-url ethereumSepolia +cast call $AMOY_ADVANCED_POOL_HOOK_ADDRESS "getThresholdAmount()(uint256)" --rpc-url polygonAmoy ``` Monitor message status with the message ID on: diff --git a/book/src/examples/example10-cct05-policy-engine-on-advanced-pool-hooks.md b/book/src/examples/example10-cct05-policy-engine-on-advanced-pool-hooks.md index e6baf09..56a2f1f 100644 --- a/book/src/examples/example10-cct05-policy-engine-on-advanced-pool-hooks.md +++ b/book/src/examples/example10-cct05-policy-engine-on-advanced-pool-hooks.md @@ -46,12 +46,27 @@ Scripts used: > > This chapter assumes `--account myAccount`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA on Amoy +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $SEPOLIA_LINK to pay in LINK +``` + ## Step 1: Deploy Token + Hook + Pool on Both Chains -Follow Example 08 steps 1-4 to deploy the token, hook and pool on both chains and link the lanes. Save from the logs: +Follow Example 08 steps 1-4 to deploy the token, hook and pool on both chains and link the lanes. If you ran them in this terminal, these variables are already exported. Otherwise copy them from the logs: -- ``, ``, `` -- ``, ``, `` +```bash +export SEPOLIA_TOKEN_ADDRESS=0x... +export SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS=0x... +export SEPOLIA_POOL_ADDRESS=0x... +export AMOY_TOKEN_ADDRESS=0x... +export AMOY_ADVANCED_POOL_HOOK_ADDRESS=0x... +export AMOY_POOL_ADDRESS=0x... +``` ## Step 2: Deploy the Example Policy Engine on Sepolia @@ -62,9 +77,11 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example10.s.sol:Example10Deploy --broadcast ``` -Save from the logs: +Copy the engine address from the logs and export it: -- `` +```bash +export SEPOLIA_POLICY_ENGINE_ADDRESS=0x... +``` The example engine's default cap is `10 ether`, and only its owner (the deploying account) can change it with `setCap`. To use a real ACE policy engine instead, skip this step and follow [Use a real ACE policy engine](#use-a-real-ace-policy-engine) below, then pass the ACE engine's onchain address to Step 3. @@ -76,8 +93,8 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example10.s.sol:Example10Attach --account myAccount \ --broadcast \ --sig "run(address,address)" \ - \ - + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS \ + $SEPOLIA_POLICY_ENGINE_ADDRESS ``` The hook calls the engine's `attach()`, which records the hook as an attached target. @@ -90,13 +107,13 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,address)" \ - \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS \ 1000000000000000000 \ 0 \ - + $FEE_TOKEN ``` `1 ether` is within the `10 ether` cap, so the engine allows the transfer. @@ -111,13 +128,13 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example06.s.sol:SendCCTTokenWit --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint32,address)" \ - \ - \ - \ - \ + $SEPOLIA_ROUTER \ + $AMOY_CHAIN_SELECTOR \ + $RECEIVER \ + $SEPOLIA_TOKEN_ADDRESS \ 11000000000000000000 \ 0 \ - + $FEE_TOKEN ``` The source-side `preflightCheck` calls the engine, which reverts with `AmountExceedsCap`, and the send reverts. @@ -130,14 +147,14 @@ FOUNDRY_PROFILE=cct forge script script/examples/Example10.s.sol:Example10Detach --account myAccount \ --broadcast \ --sig "run(address)" \ - + $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS ``` The hook calls the engine's `detach()`. Transfers are no longer policy-checked. ## Optional: Destination-Side Engine -Attach an engine to the Amoy hook too (deploy a second engine on Amoy, then attach it to ``). A destination-side rejection does not revert the send — the message is sent, but its execution on Amoy fails; check the message status on https://ccip.chain.link. +Attach an engine to the Amoy hook too (deploy a second engine on Amoy, then attach it to `$AMOY_ADVANCED_POOL_HOOK_ADDRESS`). A destination-side rejection does not revert the send — the message is sent, but its execution on Amoy fails; check the message status on https://ccip.chain.link. ## Use a real ACE policy engine @@ -155,19 +172,19 @@ One mapping gotcha from the ACE guide: the hook sets the payload sender to `msg. Verify the attached engine: ```bash -cast call "getPolicyEngine()(address)" --rpc-url ethereumSepolia +cast call $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS "getPolicyEngine()(address)" --rpc-url ethereumSepolia ``` Verify the engine records the hook as attached: ```bash -cast call "isAttached(address)(bool)" --rpc-url ethereumSepolia +cast call $SEPOLIA_POLICY_ENGINE_ADDRESS "isAttached(address)(bool)" $SEPOLIA_ADVANCED_POOL_HOOK_ADDRESS --rpc-url ethereumSepolia ``` Verify the cap: ```bash -cast call "getCap()(uint256)" --rpc-url ethereumSepolia +cast call $SEPOLIA_POLICY_ENGINE_ADDRESS "getCap()(uint256)" --rpc-url ethereumSepolia ``` Monitor message status with the message ID on: diff --git a/book/src/examples/legacy01-extraargsv1-data-message.md b/book/src/examples/legacy01-extraargsv1-data-message.md index 48633c6..d68c338 100644 --- a/book/src/examples/legacy01-extraargsv1-data-message.md +++ b/book/src/examples/legacy01-extraargsv1-data-message.md @@ -28,6 +28,17 @@ Script path: `script/examples/Legacy01.s.sol` You do not need to deploy a receiver contract for this token-only example. Use a destination EOA as the receiver and pass `GAS_LIMIT = 0`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA (Fuji -> Sepolia lane) +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export GAS_LIMIT=0 # token-only transfer to an EOA +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $FUJI_LINK to pay in LINK +``` + ## Step 1: Get 1 CCIP-BnM Token on Source Chain ```bash @@ -36,7 +47,7 @@ forge script script/Faucet.s.sol:Faucet \ --account myAccount \ --broadcast \ --sig "run(address)" \ - + $FUJI_CCIP_BNM ``` ## Step 2: Send Token With ExtraArgsV1 @@ -47,20 +58,20 @@ forge script script/examples/Legacy01.s.sol:Legacy01 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint256,address)" \ - \ - \ - \ - \ - \ - \ - + $FUJI_ROUTER \ + $SEPOLIA_CHAIN_SELECTOR \ + $RECEIVER \ + $FUJI_CCIP_BNM \ + $AMOUNT \ + $GAS_LIMIT \ + $FEE_TOKEN ``` Parameter notes: -- ``: token amount in token decimals (for 18 decimals, `1e18` is 1 token). -- ``: set `0` for token-only transfer to an EOA receiver. Use `> 0` for contract callback. -- ``: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass `0x0000000000000000000000000000000000000000` +- `$AMOUNT`: token amount in token decimals (for 18 decimals, `1e18` is 1 token). +- `$GAS_LIMIT`: set `0` for token-only transfer to an EOA receiver. Use `> 0` for contract callback. +- `$FEE_TOKEN`: native coin by default (`0x0000000000000000000000000000000000000000`). To pay CCIP fees in LINK instead, run `export FEE_TOKEN=$FUJI_LINK`. ## Verify Result diff --git a/book/src/examples/legacy02-extraargsv2-data-message.md b/book/src/examples/legacy02-extraargsv2-data-message.md index 7fbd30f..1e10192 100644 --- a/book/src/examples/legacy02-extraargsv2-data-message.md +++ b/book/src/examples/legacy02-extraargsv2-data-message.md @@ -31,6 +31,18 @@ You can toggle `allowOutOfOrderExecution` via CLI arg to cover both scenarios in You do not need to deploy a receiver contract for this token-only example. Use a destination EOA as the receiver and pass `GAS_LIMIT = 0`. +## Chapter Parameters + +Set the parameters for this chapter. The defaults work as they are; change a value only if you want something different. + +```bash +export RECEIVER=$MY_EOA # destination EOA (Fuji -> Sepolia lane) +export AMOUNT=1000000000000000000 # 1 token (18 decimals) +export GAS_LIMIT=0 # token-only transfer to an EOA +export FEE_TOKEN=0x0000000000000000000000000000000000000000 # native fee; use $FUJI_LINK to pay in LINK +export ALLOW_OUT_OF_ORDER_EXECUTION=true +``` + ## Step 1: Get 1 CCIP-BnM Token on Source Chain ```bash @@ -39,7 +51,7 @@ forge script script/Faucet.s.sol:Faucet \ --account myAccount \ --broadcast \ --sig "run(address)" \ - + $FUJI_CCIP_BNM ``` ## Step 2: Send Token With ExtraArgsV2 @@ -50,22 +62,22 @@ forge script script/examples/Legacy02.s.sol:Legacy02 \ --account myAccount \ --broadcast \ --sig "run(address,uint64,address,address,uint256,uint256,bool,address)" \ - \ - \ - \ - \ - \ - \ - \ - + $FUJI_ROUTER \ + $SEPOLIA_CHAIN_SELECTOR \ + $RECEIVER \ + $FUJI_CCIP_BNM \ + $AMOUNT \ + $GAS_LIMIT \ + $ALLOW_OUT_OF_ORDER_EXECUTION \ + $FEE_TOKEN ``` Parameter notes: -- ``: token amount in token decimals (for 18 decimals, `1e18` is 1 token). -- ``: set `0` for token-only transfer to an EOA receiver. Use `> 0` for contract callback. -- ``: `true` or `false`. -- ``: Pass the LINK token address on the source chain here. If you want to pay for CCIP fees in native coin instead, pass `0x0000000000000000000000000000000000000000` +- `$AMOUNT`: token amount in token decimals (for 18 decimals, `1e18` is 1 token). +- `$GAS_LIMIT`: set `0` for token-only transfer to an EOA receiver. Use `> 0` for contract callback. +- `$ALLOW_OUT_OF_ORDER_EXECUTION`: `true` or `false`. +- `$FEE_TOKEN`: native coin by default (`0x0000000000000000000000000000000000000000`). To pay CCIP fees in LINK instead, run `export FEE_TOKEN=$FUJI_LINK`. ## Verify Result diff --git a/book/src/index.md b/book/src/index.md index 3a29f3c..e3a3cd4 100644 --- a/book/src/index.md +++ b/book/src/index.md @@ -19,15 +19,54 @@ The goal is not to re-teach CCIP fundamentals. It is to provide runnable example > > Examples in this book assume `--account myAccount`. -### RPC URLs +### Environment Variables + +Commands in this book use shell variables (`$SEPOLIA_ROUTER`, `$AMOY_CHAIN_SELECTOR`, ...) instead of `` you edit inside every command. You still supply each value yourself, but only once: you set a variable, and every command that uses it picks it up. + +> **How the commands handle values** +> +> - A word starting with `$` is a shell variable. Before the command runs, your shell replaces `$SEPOLIA_ROUTER` with whatever you exported under that name, so `forge` and `cast` receive the real address. +> - Nothing in this repo ships with values. You provide them in three places: your `.env` file (network constants and RPC URLs), the **Chapter Parameters** block at the top of a chapter (amounts, gas limit, receiver), and `export` lines after a deploy step (addresses you just created). +> - If a variable was never set, the shell expands it to an empty string and the command fails with a confusing argument error. Run `echo $VAR_NAME` to check a value. +> - Variables exported in a terminal last only for that terminal. In a new terminal, load `.env` again and re-export any deployed addresses. -Set RPC URLs in a local `.env` file (do not commit secrets): +Create your local `.env` (do not commit it): ```bash cp .env.example .env ``` -Populate RPC URL variables only for the chains you actually plan to run. +Then fill in `.env`: + +1. The RPC URLs for the chains you plan to run (at minimum `ETHEREUM_SEPOLIA_RPC_URL` and `POLYGON_AMOY_RPC_URL`). +2. `MY_EOA`, your keystore address: `cast wallet address --account myAccount`. +3. The network constants for those chains (`SEPOLIA_ROUTER`, `SEPOLIA_CHAIN_SELECTOR`, `SEPOLIA_LINK`, `SEPOLIA_CCIP_BNM`, and the `AMOY_` / `FUJI_` equivalents; the CCT chapters also use `*_ARM_PROXY`, `*_REGISTRY_MODULE_OWNER_CUSTOM` and `*_TOKEN_ADMIN_REGISTRY`). Copy them from the [CCIP Directory](https://docs.chain.link/ccip/directory/). + +Load the file into your shell. Do this in every new terminal, and again after you edit `.env`: + +```bash +set -a; source .env; set +a +``` + +`set -a` exports every variable, so `forge`, `cast`, `npm` and `ccip-cli` all see them. + +Each chapter then follows the same pattern: + +- **Chapter parameters**: a short block of `export` lines with sensible defaults (`AMOUNT`, `GAS_LIMIT`, `BLOCK_CONFIRMATIONS`, `RECEIVER`, `FEE_TOKEN`, ...). Change a value only if you want something different. +- **Deployed addresses**: when a step deploys a contract, copy the address from the `[RESULT]` log into the `export` line shown right after the command. Later steps use it automatically. + +Shared variables used across chapters: + +| Variable | Meaning | +|---|---| +| `MY_EOA` | Your keystore account address | +| `RECEIVER` | Destination address for token-only transfers (defaults to `$MY_EOA`) | +| `AMOUNT` | Token amount in token decimals (`1000000000000000000` is 1 token with 18 decimals) | +| `GAS_LIMIT` | Destination callback gas (`0` for token-only transfers to an EOA) | +| `BLOCK_CONFIRMATIONS` | Fast Transfers depth (`0` is default finality) | +| `FEE_TOKEN` | Fee token address: native (`0x0000000000000000000000000000000000000000`) by default, or `$SEPOLIA_LINK` to pay in LINK | + +### RPC URLs In `foundry.toml`, each chain alias points to an env var (for example `polygonAmoy = "${POLYGON_AMOY_RPC_URL}"`). diff --git a/book/src/tools/ccip-sdk-ccip-send.md b/book/src/tools/ccip-sdk-ccip-send.md index 10b4518..6cc7636 100644 --- a/book/src/tools/ccip-sdk-ccip-send.md +++ b/book/src/tools/ccip-sdk-ccip-send.md @@ -67,6 +67,16 @@ For actual sends (non-`--dry-run`), set `USER_KEY` (or `PRIVATE_KEY`) in the roo - fallback: `ETHEREUM_SEPOLIA_RPC_URL`, `POLYGON_AMOY_RPC_URL` +## Variables + +The commands below use the variables from your `.env` (see [Environment Variables](../index.md#environment-variables)); load them with `set -a; source .env; set +a`. Set the message parameters once: + +```bash +export RECEIVER=$MY_EOA # token-only: destination EOA on Amoy +export BLOCK_CONFIRMATIONS=1 # token modes: > 0 for Fast Transfers +export BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS=0x... # data modes: the Amoy receiver from Example 02 / 03 +``` + ## 1) Data-Only Fast Transfers (`blockConfirmations=1`): @@ -76,8 +86,8 @@ npm --prefix sdk-examples run ccip-send -- \ --mode data \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ --dest-rpc-url "$POLYGON_AMOY_RPC_URL" \ - --router \ - --receiver \ + --router $SEPOLIA_ROUTER \ + --receiver $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ --block-confirmations 1 ``` @@ -88,8 +98,8 @@ npm --prefix sdk-examples run ccip-send -- \ --mode data \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ --dest-rpc-url "$POLYGON_AMOY_RPC_URL" \ - --router \ - --receiver \ + --router $SEPOLIA_ROUTER \ + --receiver $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ --block-confirmations 0 ``` @@ -102,11 +112,11 @@ npm --prefix sdk-examples run ccip-send -- \ --mode token \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ --dest-rpc-url "$POLYGON_AMOY_RPC_URL" \ - --router \ - --receiver \ - --token \ + --router $SEPOLIA_ROUTER \ + --receiver $RECEIVER \ + --token $SEPOLIA_CCIP_BNM \ --amount 1 \ - --block-confirmations + --block-confirmations $BLOCK_CONFIRMATIONS ``` ## 3) Token + Data @@ -118,12 +128,12 @@ npm --prefix sdk-examples run ccip-send -- \ --mode token-data \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ --dest-rpc-url "$POLYGON_AMOY_RPC_URL" \ - --router \ - --receiver \ - --token \ + --router $SEPOLIA_ROUTER \ + --receiver $BASIC_MESSAGE_RECEIVER_WITH_CCVS_ADDRESS \ + --token $SEPOLIA_CCIP_BNM \ --amount 1 \ --data "hello + token" \ - --block-confirmations + --block-confirmations $BLOCK_CONFIRMATIONS ``` ## If You Need Testnet Tokens @@ -136,5 +146,5 @@ forge script script/Faucet.s.sol:Faucet \ --account myAccount \ --broadcast \ --sig "run(address)" \ - + $SEPOLIA_CCIP_BNM ``` diff --git a/book/src/tools/ccip-sdk-ccip-track.md b/book/src/tools/ccip-sdk-ccip-track.md index 2e7a48c..5367278 100644 --- a/book/src/tools/ccip-sdk-ccip-track.md +++ b/book/src/tools/ccip-sdk-ccip-track.md @@ -48,7 +48,9 @@ npm --prefix sdk-examples install - fallback: `ETHEREUM_SEPOLIA_RPC_URL` ```bash -source .env +set -a; source .env; set +a +export SOURCE_TX_HASH=0x... # from your send logs +export MESSAGE_ID=0x... # from your send logs ``` ## 1) Track by Source Transaction Hash @@ -58,7 +60,7 @@ Use a source tx hash from your Foundry run (for example `Example01`-`Example08`) ```bash npm --prefix sdk-examples run ccip-track -- \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ - --tx-hash + --tx-hash $SOURCE_TX_HASH ``` ## 2) Track by Message ID @@ -66,7 +68,7 @@ npm --prefix sdk-examples run ccip-track -- \ ```bash npm --prefix sdk-examples run ccip-track -- \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ - --message-id + --message-id $MESSAGE_ID ``` Output prints the same concise SDK summary for that message ID. @@ -77,7 +79,7 @@ Output prints the same concise SDK summary for that message ID. npm --prefix sdk-examples run ccip-track -- \ --source-rpc-url "$ETHEREUM_SEPOLIA_RPC_URL" \ --limit 10 \ - --sender + --sender $MY_EOA ``` Arguments: diff --git a/book/src/tools/using-the-cli.md b/book/src/tools/using-the-cli.md index d492322..264ba96 100644 --- a/book/src/tools/using-the-cli.md +++ b/book/src/tools/using-the-cli.md @@ -25,25 +25,36 @@ ccip-cli --version ccip-cli --help ``` +## Variables + +The commands below use the variables from your `.env` (see [Environment Variables](../index.md#environment-variables)); load them with `set -a; source .env; set +a`. `send` also needs a signing key and a receiver, and the `show` commands need a transaction hash or message ID: + +```bash +export USER_KEY=0x... # private key of a funded test account (never commit it) +export RECEIVER=$MY_EOA # destination address (a deployed receiver for data messages) +export SOURCE_TX_HASH=0x... # from your send logs +export MESSAGE_ID=0x... # from your send logs +``` + ## Observability ### 1) Inspect by source transaction hash ```bash -ccip-cli show \ - --rpcs \ - --rpcs +ccip-cli show $SOURCE_TX_HASH \ + --rpcs "$ETHEREUM_SEPOLIA_RPC_URL" \ + --rpcs "$POLYGON_AMOY_RPC_URL" ``` -`` is the source-chain transaction hash. -`` and `` are RPC endpoints for the source and destination chains. +`$SOURCE_TX_HASH` is the source-chain transaction hash. +`$ETHEREUM_SEPOLIA_RPC_URL` and `$POLYGON_AMOY_RPC_URL` are the RPC endpoints for the source and destination chains. Wait for delivery from the same command: ```bash -ccip-cli show \ - --rpcs \ - --rpcs \ +ccip-cli show $SOURCE_TX_HASH \ + --rpcs "$ETHEREUM_SEPOLIA_RPC_URL" \ + --rpcs "$POLYGON_AMOY_RPC_URL" \ --wait ``` @@ -54,14 +65,14 @@ ccip-cli show \ `tx-hash` positional becomes `messageId` when `--id-from-source` is used: ```bash -ccip-cli show \ - --id-from-source \ - --rpcs \ - --rpcs +ccip-cli show $MESSAGE_ID \ + --id-from-source $SEPOLIA_CHAIN_SELECTOR \ + --rpcs "$ETHEREUM_SEPOLIA_RPC_URL" \ + --rpcs "$POLYGON_AMOY_RPC_URL" ``` -`` is the CCIP message ID. -`` is the source CCIP chain selector. +`$MESSAGE_ID` is the CCIP message ID. +`$SEPOLIA_CHAIN_SELECTOR` is the source CCIP chain selector. ## Send Parity (CLI) @@ -70,46 +81,46 @@ ccip-cli show \ ### 1) Data-only ```bash -ccip-cli send -s -d -r \ - --rpcs \ - --rpcs \ - --wallet \ - --receiver \ +ccip-cli send -s $SEPOLIA_CHAIN_SELECTOR -d $AMOY_CHAIN_SELECTOR -r $SEPOLIA_ROUTER \ + --rpcs "$ETHEREUM_SEPOLIA_RPC_URL" \ + --rpcs "$POLYGON_AMOY_RPC_URL" \ + --wallet "$USER_KEY" \ + --receiver $RECEIVER \ --data "hello from ccip-cli" \ --gas-limit 200000 \ --wait ``` -`` and `` can be chain ID, chain selector, or chain name. +`$SEPOLIA_CHAIN_SELECTOR` and `$AMOY_CHAIN_SELECTOR` can be chain ID, chain selector, or chain name. Chain ID examples: Ethereum Sepolia `11155111`, Polygon Amoy `80002`. -`` is the source-chain router for the selected lane. +`$SEPOLIA_ROUTER` is the source-chain router for the selected lane. ### 2) Token-only ```bash -ccip-cli send -s -d -r \ - --rpcs \ - --rpcs \ - --wallet \ - --receiver \ - --transfer-tokens = \ +ccip-cli send -s $SEPOLIA_CHAIN_SELECTOR -d $AMOY_CHAIN_SELECTOR -r $SEPOLIA_ROUTER \ + --rpcs "$ETHEREUM_SEPOLIA_RPC_URL" \ + --rpcs "$POLYGON_AMOY_RPC_URL" \ + --wallet "$USER_KEY" \ + --receiver $RECEIVER \ + --transfer-tokens $SEPOLIA_CCIP_BNM=1 \ --gas-limit 0 \ --wait ``` -`=` uses `token=amount` format. -`` is human-readable; CLI converts it using token decimals. +`$SEPOLIA_CCIP_BNM=1` uses `token=amount` format. +`1` is human-readable; CLI converts it using token decimals. ### 3) Token + data ```bash -ccip-cli send -s -d -r \ - --rpcs \ - --rpcs \ - --wallet \ - --receiver \ +ccip-cli send -s $SEPOLIA_CHAIN_SELECTOR -d $AMOY_CHAIN_SELECTOR -r $SEPOLIA_ROUTER \ + --rpcs "$ETHEREUM_SEPOLIA_RPC_URL" \ + --rpcs "$POLYGON_AMOY_RPC_URL" \ + --wallet "$USER_KEY" \ + --receiver $RECEIVER \ --data "hello + token" \ - --transfer-tokens = \ + --transfer-tokens $SEPOLIA_CCIP_BNM=1 \ --gas-limit 200000 \ --wait ``` @@ -123,5 +134,5 @@ Amount is human-readable and CLI converts it using token decimals. Examples: -- `--transfer-tokens =1` means 1 whole token. -- `--transfer-tokens =1.5` means 1.5 tokens. +- `--transfer-tokens $SEPOLIA_CCIP_BNM=1` means 1 whole token. +- `--transfer-tokens $SEPOLIA_CCIP_BNM=1.5` means 1.5 tokens.