From 1b63f72ef818050b5b1348be89cc33ce49e9c5bb Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 16:26:53 +0300 Subject: [PATCH 1/7] Cross-chain messaging tutorial --- src/pages/developers/tutorials/messaging.mdx | 56 ++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/pages/developers/tutorials/messaging.mdx diff --git a/src/pages/developers/tutorials/messaging.mdx b/src/pages/developers/tutorials/messaging.mdx new file mode 100644 index 000000000..984b497f8 --- /dev/null +++ b/src/pages/developers/tutorials/messaging.mdx @@ -0,0 +1,56 @@ +``` +npx zetachain new --project messaging +``` + +``` +cd messaging +yarn +forge soldeer update +``` + +``` +forge build +``` + +``` +PRIVATE_KEY=... +``` + +``` +MESSAGING_BASE=$(./commands/index.ts deploy --rpc https://sepolia.base.org --private-key $PRIVATE_KEY | jq -r .contractAddress) +``` + +``` +MESSAGING_ETHEREUM=$(./commands/index.ts deploy --rpc https://sepolia.drpc.org --private-key $PRIVATE_KEY | jq -r .contractAddress) +``` + +``` +./commands/index.ts connect \ + --contract $MESSAGING_BASE \ + --target-contract $MESSAGING_ETHEREUM \ + --rpc https://sepolia.base.org \ + --target-chain-id 11155111 \ + --private-key $PRIVATE_KEY +``` + + +``` +./commands/index.ts connect \ + --contract $MESSAGING_ETHEREUM \ + --target-contract $MESSAGING_BASE \ + --rpc https://sepolia.drpc.org \ + --target-chain-id 84532 \ + --private-key $PRIVATE_KEY +``` + +``` +./commands/index.ts message \ + --rpc https://sepolia.base.org \ + --private-key $PRIVATE_KEY \ + --contract $MESSAGING_BASE \ + --target-contract $MESSAGING_ETHEREUM \ + --types string \ + --values hello \ + --target-token 0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0 \ + --amount 0.005 +``` \ No newline at end of file From f93959ef1b329eb2d600611781eeabb48fd7bd9f Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 16:39:47 +0300 Subject: [PATCH 2/7] tx tracking --- src/pages/developers/tutorials/messaging.mdx | 32 +++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/pages/developers/tutorials/messaging.mdx b/src/pages/developers/tutorials/messaging.mdx index 984b497f8..b637b4260 100644 --- a/src/pages/developers/tutorials/messaging.mdx +++ b/src/pages/developers/tutorials/messaging.mdx @@ -53,4 +53,34 @@ MESSAGING_ETHEREUM=$(./commands/index.ts deploy --rpc https://sepolia.drpc.org - --values hello \ --target-token 0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0 \ --amount 0.005 -``` \ No newline at end of file +``` + +``` +{"contractAddress":"0xee2E8dfefd723e879CAa30A1DaD94046Fa3D24D4","targetContract":"0x7c9BbA0630c9452F726bc15D0a73cdF769438efE","targetToken":"0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0","message":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000","transactionHash":"0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3","amount":"0.005"} +``` + +``` +zetachain q cctx --hash 0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3 +``` + +``` +84532 → 7001 ✅ OutboundMined +CCTX: 0xd88d92d0b9b0a2fde416bf6383e430b51de48114b0b03e7cc34e7f8d8df15cb7 +Tx Hash: 0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3 (on chain 84532) +Tx Hash: 0x8c368f6a3cfc55950b5d2b0d98c63d1904a79300490ec7d1c258505f372054e3 (on chain 7001) +Sender: 0xee2E8dfefd723e879CAa30A1DaD94046Fa3D24D4 +Receiver: 0x5BD35697D4a62DE429247cbBDCc5c47F70477775 +Message: 00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000005ba149a7bd6dc1f937fa9046a9e05c05f3b18b000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000147c9bba0630c9452f726bc15d0a73cdf769438efe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000000000000000000000000000ee2e8dfefd723e879caa30a1dad94046fa3d24d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000000 +Amount: 5000000000000000 Gas tokens + +7001 → 11155111 ✅ OutboundMined +CCTX: 0x8952c9f95dfb5673a9fbfa2196842b750f5530f4931a55088b1276599328fd64 +Tx Hash: 0xd88d92d0b9b0a2fde416bf6383e430b51de48114b0b03e7cc34e7f8d8df15cb7 (on chain 7001) +Tx Hash: 0xf30e4414087e8b5c81e257e8a97ac9105dde37cbbd6bb33a1691c4a30585507e (on chain 11155111) +Sender: 0x5BD35697D4a62DE429247cbBDCc5c47F70477775 +Receiver: 0x7c9BbA0630c9452F726bc15D0a73cdF769438efE +Message: 00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000009ad718280b1cf00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000014a34000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014ee2e8dfefd723e879caa30a1dad94046fa3d24d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Amount: 1074034700777807 Gas tokens +``` + +https://sepolia.etherscan.io/tx/0xf30e4414087e8b5c81e257e8a97ac9105dde37cbbd6bb33a1691c4a30585507e \ No newline at end of file From a4002db8eb5b1ff48714c106ad64964c2bd98021 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 17:31:53 +0300 Subject: [PATCH 3/7] tutorial --- src/pages/developers/tutorials/messaging.mdx | 62 +++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/pages/developers/tutorials/messaging.mdx b/src/pages/developers/tutorials/messaging.mdx index b637b4260..83b289d35 100644 --- a/src/pages/developers/tutorials/messaging.mdx +++ b/src/pages/developers/tutorials/messaging.mdx @@ -1,3 +1,32 @@ +This tutorial shows how to send cross-chain messages between contracts on two +EVM chains using ZetaChain’s messaging infrastructure. + +Unlike universal apps deployed directly on ZetaChain, this approach allows you +to keep all contract logic on connected EVM chains. Messages are automatically +routed between them through ZetaChain, without requiring any contracts to be +deployed on ZetaChain itself. + +By the end of this tutorial, you will: + +* Deploy a messaging contract to two EVM testnets (Base and Ethereum Sepolia) +* Link them for cross-chain communication +* Send a message and token value from one to the other +* Track the cross-chain transaction from source to destination + +## Prerequisites + +Make sure you have the following installed: + +* [Node.js](https://nodejs.org/en) v18+ +* [Yarn](https://yarnpkg.com/) +* [Foundry](https://getfoundry.sh/) +* [jq](https://jqlang.org/) for parsing JSON in shell scripts +* A funded private key for both Base Sepolia (84532) and Ethereum Sepolia + (11155111) + + +## Create a Project + ``` npx zetachain new --project messaging ``` @@ -16,14 +45,25 @@ forge build PRIVATE_KEY=... ``` +## Deploy Messaging Contracts + +Deploy to Base Sepolia: + ``` MESSAGING_BASE=$(./commands/index.ts deploy --rpc https://sepolia.base.org --private-key $PRIVATE_KEY | jq -r .contractAddress) ``` +Deploy to Ethereum Sepolia: + ``` MESSAGING_ETHEREUM=$(./commands/index.ts deploy --rpc https://sepolia.drpc.org --private-key $PRIVATE_KEY | jq -r .contractAddress) ``` +## Connect Two Contracts + +Establish a trusted connection between deployed contracts: + + ``` ./commands/index.ts connect \ --contract $MESSAGING_BASE \ @@ -43,6 +83,8 @@ MESSAGING_ETHEREUM=$(./commands/index.ts deploy --rpc https://sepolia.drpc.org - --private-key $PRIVATE_KEY ``` +## Send a Cross-Chain Message + ``` ./commands/index.ts message \ --rpc https://sepolia.base.org \ @@ -55,9 +97,20 @@ MESSAGING_ETHEREUM=$(./commands/index.ts deploy --rpc https://sepolia.drpc.org - --amount 0.005 ``` +```json +{ + "contractAddress": "0xee2E8dfefd723e879CAa30A1DaD94046Fa3D24D4", + "targetContract": "0x7c9BbA0630c9452F726bc15D0a73cdF769438efE", + "targetToken": "0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0", + "message": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000", + "transactionHash": "0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3", + "amount": "0.005" +} ``` -{"contractAddress":"0xee2E8dfefd723e879CAa30A1DaD94046Fa3D24D4","targetContract":"0x7c9BbA0630c9452F726bc15D0a73cdF769438efE","targetToken":"0x05BA149A7bd6dC1F937fA9046A9e05C05f3b18b0","message":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000","transactionHash":"0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3","amount":"0.005"} -``` + +## Track the Cross-Chain Transaction + +Use the transaction hash from the previous step to query its cross-chain status: ``` zetachain q cctx --hash 0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3 @@ -83,4 +136,9 @@ Message: 00000000000000000000000000000000000000000000000000000000000000c0000000 Amount: 1074034700777807 Gas tokens ``` +This confirms that the message has successfully moved from Base Sepolia through +ZetaChain to Ethereum Sepolia. + +You can verify the destination chain transaction on Etherscan: + https://sepolia.etherscan.io/tx/0xf30e4414087e8b5c81e257e8a97ac9105dde37cbbd6bb33a1691c4a30585507e \ No newline at end of file From cafe4f3117546804d2dd668a2f5eedb1af43abd3 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 18:09:13 +0300 Subject: [PATCH 4/7] tutorial --- src/pages/developers/tutorials/messaging.mdx | 249 ++++++++++++++++++- 1 file changed, 236 insertions(+), 13 deletions(-) diff --git a/src/pages/developers/tutorials/messaging.mdx b/src/pages/developers/tutorials/messaging.mdx index 83b289d35..81023eb21 100644 --- a/src/pages/developers/tutorials/messaging.mdx +++ b/src/pages/developers/tutorials/messaging.mdx @@ -6,45 +6,213 @@ to keep all contract logic on connected EVM chains. Messages are automatically routed between them through ZetaChain, without requiring any contracts to be deployed on ZetaChain itself. +> Why use this pattern? Unlike universal apps deployed directly on ZetaChain, +> here all business logic stays on the connected EVM chains you already know. +> ZetaChain merely transports the payload—no contract code is deployed on +> ZetaChain itself. + By the end of this tutorial, you will: -* Deploy a messaging contract to two EVM testnets (Base and Ethereum Sepolia) -* Link them for cross-chain communication -* Send a message and token value from one to the other -* Track the cross-chain transaction from source to destination +- Deploy a messaging contract to two EVM testnets (Base and Ethereum Sepolia) +- Link them for cross-chain communication +- Send a message and token value from one to the other +- Track the cross-chain transaction from source to destination ## Prerequisites Make sure you have the following installed: -* [Node.js](https://nodejs.org/en) v18+ -* [Yarn](https://yarnpkg.com/) -* [Foundry](https://getfoundry.sh/) -* [jq](https://jqlang.org/) for parsing JSON in shell scripts -* A funded private key for both Base Sepolia (84532) and Ethereum Sepolia +- [Node.js](https://nodejs.org/en) v18+ +- [Yarn](https://yarnpkg.com/) +- [Foundry](https://getfoundry.sh/) +- [jq](https://jqlang.org/) for parsing JSON in shell scripts +- A funded private key for both Base Sepolia (84532) and Ethereum Sepolia (11155111) - ## Create a Project +Create a new project using the `messaging` template: + ``` npx zetachain new --project messaging ``` +Install TypeSCcipt and Foundry dependencies: + ``` cd messaging yarn forge soldeer update ``` +Compile contracts: + ``` forge build ``` +Save your private key in an environment variable so shell scripts can read it: + ``` PRIVATE_KEY=... ``` +## Messaging Contract + +To enable cross-chain messaging, your contract must inherit from ZetaChain’s +Messaging base contract and implement a few required functions. + +Import the `Messaging.sol` contract from the ZetaChain standard contracts +package: + +```solidity +import "@zetachain/standard-contracts/contracts/messaging/contracts/Messaging.sol"; +``` + +Inherit from `Messaging` in your contract: + +```solidity +contract Example is Messaging { ... } +``` + +Initialize the contract with the required parameters in the constructor: + +```solidity +constructor( + address payable _gateway, + address owner, + address _router +) Messaging(_gateway, owner, _router) {} +``` + +The Messa`ging base contract provides built-in access to Gateway and Router, and +ensures your contract is correctly wired into ZetaChain’s cross-chain messaging +system. + +You must implement three core internal functions for handling message delivery +and fallback: + +#### onMessageReceive + +This is called automatically on the destination chain when a cross-chain message +arrives successfully. + +```solidity +function onMessageReceive( + bytes memory data, + bytes memory sender, + uint256 amount, + bytes memory asset +) internal override { + //... +} +``` + +Use this function to decode the message and execute logic like updating state, +triggering downstream calls, or transferring the received token value. + +### onMessageRevert + +This is triggered if the destination contract’s onMessageReceive fails (e.g., +due to invalid calldata or logic errors). + +```solidity +function onMessageRevert( + bytes memory data, + bytes memory sender, + uint256 amount, + bytes memory asset +) internal override { + //... +} +``` + +### onRevert + +This is called when a message fails during routing before reaching the +destination chain. It executes on the source chain. + +```solidity +function onRevert(RevertContext calldata context) + external + payable + override + onlyGateway +{ + if (context.sender != router) revert Unauthorized(); + //... +} +``` + +You can use this to refund the user, trigger compensation logic, or emit a +notification. + +### Sending a Message + +To initiate a cross-chain message, your contract must call the `depositAndCall` +function on the EVM Gateway. This function is what hands off your message and +optional token value to ZetaChain’s messaging layer for routing. + +Depending on whether you're sending native gas (like ETH) or ERC-20 tokens, +you’ll use one of the following two forms of `depositAndCall`. + +If you want to send a message with ETH as the value: + +```solidity +gateway.depositAndCall{value: msg.value}( + router, + message, + revertOptions +); +``` + +If you're sending supported ERC-20 tokens: + +```solidity +gateway.depositAndCall( + router, + amount, + asset, + message, + revertOptions +); +``` + +`asset` is the ERC-20 token address being sent (must be supported by ZetaChain). + +### What’s Inside the Message Payload? + +The `message` argument is a single `bytes` field. It is ABI-encoded and must +follow a structure that the Universal Router on ZetaChain understands. + +```solidity +abi.encode( + receiver, // bytes: destination contract address on the target chain + targetToken, // address: ZRC-20 address of the token to transfer to the destination contract + data, // bytes: message payload (e.g., ABI-encoded "hello") + gasLimit, // uint256: gas to forward for execution on the target chain + revertOptions // struct: defines what to do on failure +) +``` + +If you're sending the string `"hello"` to a contract on Ethereum Sepolia, you +might encode: + +```solidity +bytes memory data = abi.encode("hello"); +bytes memory message = abi.encode( + abi.encodePacked(receiver), // Destination contract address (as bytes) + targetToken, // Token to transfer on destination chain + data, // ABI-encoded message + 300_000, // Gas limit + revertOptions // Struct specifying fallback behavior +); +``` + +This message is then passed to `depositAndCall()` and routed through ZetaChain +to the destination chain, where it is decoded and passed into the destination +contract’s `onMessageReceive()`. + ## Deploy Messaging Contracts Deploy to Base Sepolia: @@ -61,8 +229,22 @@ MESSAGING_ETHEREUM=$(./commands/index.ts deploy --rpc https://sepolia.drpc.org - ## Connect Two Contracts -Establish a trusted connection between deployed contracts: +Before two contracts can communicate across chains, they need to explicitly +trust each other. This prevents malicious contracts from spoofing cross-chain +messages. In this step, you’ll establish a bidirectional link between the two +deployed messaging contracts. + +Each contract needs to know: +- The address of the counterpart contract on the remote chain +- The chain ID of that remote chain + +This is done using the `setConnected()` function in the messaging contract. +ZetaChain’s cross-chain infrastructure will only deliver messages to a contract +if it has registered the sender as trusted. + +⚠️ If you skip this step or set the wrong address/chain ID, messages will be +rejected on the destination chain. ``` ./commands/index.ts connect \ @@ -73,7 +255,6 @@ Establish a trusted connection between deployed contracts: --private-key $PRIVATE_KEY ``` - ``` ./commands/index.ts connect \ --contract $MESSAGING_ETHEREUM \ @@ -83,8 +264,16 @@ Establish a trusted connection between deployed contracts: --private-key $PRIVATE_KEY ``` +Once both directions are linked, the contracts can send and receive messages. + ## Send a Cross-Chain Message +Now that your contracts are deployed and connected, you can send a message from +one to the other. + +This example sends the string "hello" from the contract on Base Sepolia to the +contract on Ethereum Sepolia, + ``` ./commands/index.ts message \ --rpc https://sepolia.base.org \ @@ -97,6 +286,40 @@ Establish a trusted connection between deployed contracts: --amount 0.005 ``` +| Flag | Description | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--rpc https://sepolia.base.org` | The RPC endpoint for the **source chain** (Base Sepolia). This is where the transaction will be sent. | +| `--private-key $PRIVATE_KEY` | The account that signs and funds the transaction on the source chain. It must hold the token being sent. | +| `--contract $MESSAGING_BASE` | Address of the messaging contract deployed on the source chain. This contract initiates the cross-chain call. | +| `--target-contract $MESSAGING_ETHEREUM` | The address of the contract on the **destination chain**. This is the final recipient of the message. | +| `--types string` | The ABI type of the message you’re sending. This can be a single type (like `string`) or a tuple (e.g., `string,uint256`). | +| `--values hello` | The actual value to encode and send across chains—in this case, just the string `"hello"`. | +| `--target-token 0x...` | The ZRC20 token address on ZetaChain that represents the destination chain’s token. This tells ZetaChain what asset to transfer to the target contract. | +| `--amount 0.005` | The total amount of tokens sent. A portion of this covers gas fees on the destination chain; the remainder is transferred to the destination contract. | + +### How Amount is Handled + +When you send a cross-chain message using `--amount`, you're not just +transferring tokens—you’re also prepaying for gas on the destination chain. +Here's what happens behind the scenes: + +1. You **supply tokens** on the source chain (e.g., Base ETH). This can be + native gas (like ETH) or any supported ERC-20. +2. You specify a **target token** via `--target-token`, which points to the + ZRC-20 representing the token you want to deliver on the destination chain + (e.g., Ethereum ETH). +3. On ZetaChain: + + - A **portion of the supplied amount** is automatically swapped into the + ZRC-20 version of the **gas token** for the destination chain (Ethereum ETH + in this example). This is used to cover the **execution cost** of the + message on the destination chain. + - The **remaining amount** is swapped into the **target token** (which might + be the same token) and forwarded to the destination contract. + +This makes the system fully automated: you don’t need to hold or acquire the +destination chain’s native token to interact with it. + ```json { "contractAddress": "0xee2E8dfefd723e879CAa30A1DaD94046Fa3D24D4", @@ -141,4 +364,4 @@ ZetaChain to Ethereum Sepolia. You can verify the destination chain transaction on Etherscan: -https://sepolia.etherscan.io/tx/0xf30e4414087e8b5c81e257e8a97ac9105dde37cbbd6bb33a1691c4a30585507e \ No newline at end of file +https://sepolia.etherscan.io/tx/0xf30e4414087e8b5c81e257e8a97ac9105dde37cbbd6bb33a1691c4a30585507e From 2fb210e2d30305d6b0cad9eb74bdb7b88bb3ef7b Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 18:16:59 +0300 Subject: [PATCH 5/7] tutorial --- src/pages/developers/tutorials/messaging.mdx | 42 ++++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/pages/developers/tutorials/messaging.mdx b/src/pages/developers/tutorials/messaging.mdx index 81023eb21..d45d209ad 100644 --- a/src/pages/developers/tutorials/messaging.mdx +++ b/src/pages/developers/tutorials/messaging.mdx @@ -8,7 +8,7 @@ deployed on ZetaChain itself. > Why use this pattern? Unlike universal apps deployed directly on ZetaChain, > here all business logic stays on the connected EVM chains you already know. -> ZetaChain merely transports the payload—no contract code is deployed on +> ZetaChain merely transports the payload, no contract code is deployed on > ZetaChain itself. By the end of this tutorial, you will: @@ -60,7 +60,7 @@ PRIVATE_KEY=... ## Messaging Contract To enable cross-chain messaging, your contract must inherit from ZetaChain’s -Messaging base contract and implement a few required functions. +`Messaging` base contract and implement a few required functions. Import the `Messaging.sol` contract from the ZetaChain standard contracts package: @@ -213,6 +213,40 @@ This message is then passed to `depositAndCall()` and routed through ZetaChain to the destination chain, where it is decoded and passed into the destination contract’s `onMessageReceive()`. +### What Is the Universal Router? + +When you send a cross-chain message via `gateway.depositAndCall(...)`, the +actual logic that handles routing and execution on ZetaChain is implemented +inside a contract called the **Universal Router**. + +This contract runs on ZetaChain and acts as the **entry point for all +cross-chain messaging logic**. It is responsible for: + +- **Parsing the message payload** sent from the source chain +- **Swapping tokens** (if necessary) into: + + - The destination chain's **gas token** to cover execution fees + - The destination contract's **target token** to be delivered + +- **Forwarding the message** and token to the destination contract +- **Handling fallback logic** in case the destination call fails + +All contracts that use the Messaging base contract share the same Universal +Router. This shared router simplifies development, ensuring consistent behavior +across all messaging-based apps. + +The Universal Router ensures that your contract only needs to focus on sending +an encoded payload, everything else, from gas handling to token transfer to +delivery mechanics, is managed for you. + +You don’t need to interact with the Universal Router directly. Just encode your +message, call the Gateway, and ZetaChain will handle the rest. + +> 🔧 Advanced: If you need more control, for example, to customize how tokens +> are swapped, route to different contracts, or handle messages differently, you +> can deploy your own instance of a router and point your contracts to it by +> passing its address to the Messaging constructor. + ## Deploy Messaging Contracts Deploy to Base Sepolia: @@ -293,14 +327,14 @@ contract on Ethereum Sepolia, | `--contract $MESSAGING_BASE` | Address of the messaging contract deployed on the source chain. This contract initiates the cross-chain call. | | `--target-contract $MESSAGING_ETHEREUM` | The address of the contract on the **destination chain**. This is the final recipient of the message. | | `--types string` | The ABI type of the message you’re sending. This can be a single type (like `string`) or a tuple (e.g., `string,uint256`). | -| `--values hello` | The actual value to encode and send across chains—in this case, just the string `"hello"`. | +| `--values hello` | The actual value to encode and send across chains, in this case, just the string `"hello"`. | | `--target-token 0x...` | The ZRC20 token address on ZetaChain that represents the destination chain’s token. This tells ZetaChain what asset to transfer to the target contract. | | `--amount 0.005` | The total amount of tokens sent. A portion of this covers gas fees on the destination chain; the remainder is transferred to the destination contract. | ### How Amount is Handled When you send a cross-chain message using `--amount`, you're not just -transferring tokens—you’re also prepaying for gas on the destination chain. +transferring tokens, you’re also prepaying for gas on the destination chain. Here's what happens behind the scenes: 1. You **supply tokens** on the source chain (e.g., Base ETH). This can be From 318086983debd46210e345382cd2e93c817bce22 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 18:17:40 +0300 Subject: [PATCH 6/7] meta --- src/pages/developers/tutorials/_meta.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/developers/tutorials/_meta.json b/src/pages/developers/tutorials/_meta.json index 339f600da..e02c01847 100644 --- a/src/pages/developers/tutorials/_meta.json +++ b/src/pages/developers/tutorials/_meta.json @@ -19,6 +19,11 @@ "readTime": "30 min", "description": "Implement a universal swap app compatible with chains like Ethereum, Solana and Bitcoin" }, + "messaging": { + "title": "Messaging", + "readTime": "30 min", + "description": "Learn how to make cross-chain calls between contracts on EVM chains" + }, "solana": { "title": "Solana", "readTime": "60 min", From 44816819db1dfdce014c495332111799124c3120 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 31 Jul 2025 18:46:45 +0300 Subject: [PATCH 7/7] npx zetachain query --- src/pages/developers/tutorials/messaging.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/developers/tutorials/messaging.mdx b/src/pages/developers/tutorials/messaging.mdx index d45d209ad..7bd06ef91 100644 --- a/src/pages/developers/tutorials/messaging.mdx +++ b/src/pages/developers/tutorials/messaging.mdx @@ -370,7 +370,7 @@ destination chain’s native token to interact with it. Use the transaction hash from the previous step to query its cross-chain status: ``` -zetachain q cctx --hash 0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3 +npx zetachain query cctx --hash 0x939e230dd504efdf1fce31202a5980b4d0376430ddf535d080666256353c02c3 ``` ```