|
| 1 | +Interacting with ZetaChain universal apps directly from the Sui blockchain is |
| 2 | +straightforward and intuitive. You can deposit SUI tokens to ZetaChain |
| 3 | +addresses—both externally owned accounts (EOAs) and smart contracts. Universal |
| 4 | +apps deployed on ZetaChain can accept these token deposits and handle contract |
| 5 | +calls originating from Sui. |
| 6 | + |
| 7 | +In this tutorial, you'll: |
| 8 | + |
| 9 | +- Set up a local development environment using |
| 10 | + [localnet](/developers/tutorials/localnet). |
| 11 | +- Deploy a universal contract on ZetaChain. |
| 12 | +- Deposit SUI tokens from Sui to ZetaChain. |
| 13 | +- Execute deposit-and-call to deposit SUI tokens and call a universal app in a |
| 14 | + single transaction. |
| 15 | + |
| 16 | +By the end, you'll clearly understand how Sui-based applications and contracts |
| 17 | +can integrate seamlessly with the ZetaChain ecosystem. |
| 18 | + |
| 19 | +## Prerequisites |
| 20 | + |
| 21 | +Ensure you have installed and configured the following tools before starting: |
| 22 | + |
| 23 | +- [Sui CLI](https://docs.sui.io/references/cli): Required for starting a local |
| 24 | + Sui node and interacting with it. |
| 25 | +- [Foundry](https://getfoundry.sh/): Needed for encoding payload data using ABI. |
| 26 | + |
| 27 | +## Clone the Example Project |
| 28 | + |
| 29 | +Begin by cloning the example contracts repository and installing its |
| 30 | +dependencies: |
| 31 | + |
| 32 | +```bash |
| 33 | +git clone https://github.com/zeta-chain/example-contracts |
| 34 | +cd example-contracts/examples/call |
| 35 | +yarn |
| 36 | +``` |
| 37 | + |
| 38 | +## Launch Localnet |
| 39 | + |
| 40 | +Start your local development environment, which sets up instances of ZetaChain |
| 41 | +and Sui: |
| 42 | + |
| 43 | +```bash |
| 44 | +npx hardhat localnet |
| 45 | +``` |
| 46 | + |
| 47 | +Keep this terminal window open. You should see a table displaying the deployment |
| 48 | +details, including Gateway module and object IDs: |
| 49 | + |
| 50 | +``` |
| 51 | +SUI |
| 52 | +┌─────────────────┬────────────────────────────────────────────────────────────────────────────────┐ |
| 53 | +│ (index) │ Values │ |
| 54 | +├─────────────────┼────────────────────────────────────────────────────────────────────────────────┤ |
| 55 | +│ gatewayModuleID │ '0xc478ce1cbbeb090889a0e728af4fd25d80993a653b5f03090dbf77e5a9476bcd' │ |
| 56 | +│ gatewayObjectId │ '0x332483152b600f388b64adb4d98509ded379167df6047c49a564a4ed62f8bb71' │ |
| 57 | +│ userMnemonic │ 'grape subway rack mean march bubble carry avoid muffin consider thing street' │ |
| 58 | +│ userAddress │ '0x2fec3fafe08d2928a6b8d9a6a77590856c458d984ae090ccbd4177ac13729e65' │ |
| 59 | +└─────────────────┴────────────────────────────────────────────────────────────────────────────────┘ |
| 60 | +``` |
| 61 | + |
| 62 | +## Deploying a Universal Contract |
| 63 | + |
| 64 | +Open a new terminal window to compile and deploy your Universal Contract: |
| 65 | + |
| 66 | +```bash |
| 67 | +npx hardhat compile --force |
| 68 | +npx hardhat deploy --name Universal --network localhost --gateway 0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 |
| 69 | +``` |
| 70 | + |
| 71 | +A successful deployment will output: |
| 72 | + |
| 73 | +``` |
| 74 | +🚀 Successfully deployed "Universal" contract on localhost. |
| 75 | +📜 Contract address: 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7 |
| 76 | +``` |
| 77 | + |
| 78 | +## Deposit to ZetaChain |
| 79 | + |
| 80 | +To deposit tokens from your local Sui Gateway contract to ZetaChain, use: |
| 81 | + |
| 82 | +``` |
| 83 | +npx hardhat localnet:sui-deposit \ |
| 84 | + --mnemonic "grape subway rack mean march bubble carry avoid muffin consider thing street" \ |
| 85 | + --gateway 0x332483152b600f388b64adb4d98509ded379167df6047c49a564a4ed62f8bb71 \ |
| 86 | + --module 0xc478ce1cbbeb090889a0e728af4fd25d80993a653b5f03090dbf77e5a9476bcd \ |
| 87 | + --receiver 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7 \ |
| 88 | + --amount 100000000 |
| 89 | +``` |
| 90 | + |
| 91 | +In this example, a client makes a call on the Sui blockchain to the local |
| 92 | +Gateway contract. The local development environment (Localnet) observes this |
| 93 | +transaction similarly to how ZetaChain would in a live scenario, and as a |
| 94 | +result, deposits ZRC-20 SUI tokens to the specified receiver address on |
| 95 | +ZetaChain. |
| 96 | + |
| 97 | +## Deposit and Call |
| 98 | + |
| 99 | +Execute a deposit and simultaneously make a function call to a universal |
| 100 | +contract on ZetaChain: |
| 101 | + |
| 102 | +``` |
| 103 | +npx hardhat localnet:sui-deposit-and-call \ |
| 104 | + --mnemonic "grape subway rack mean march bubble carry avoid muffin consider thing street" \ |
| 105 | + --gateway 0x332483152b600f388b64adb4d98509ded379167df6047c49a564a4ed62f8bb71 \ |
| 106 | + --module 0xc478ce1cbbeb090889a0e728af4fd25d80993a653b5f03090dbf77e5a9476bcd \ |
| 107 | + --receiver 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7 \ |
| 108 | + --amount 1000000 \ |
| 109 | + --types '["string"]' alice |
| 110 | +``` |
| 111 | + |
| 112 | +In this example, a call is made from a client on the Sui blockchain to the local |
| 113 | +Gateway contract. The local development environment (Localnet) observes this |
| 114 | +call, deposits ZRC-20 SUI tokens to the specified receiver address on ZetaChain, |
| 115 | +and then triggers the receiver contract on ZetaChain with the provided payload |
| 116 | +(alice). |
| 117 | + |
| 118 | +## Build and Deploy a Sui Contract |
| 119 | + |
| 120 | +``` |
| 121 | +cd sui |
| 122 | +``` |
| 123 | + |
| 124 | +The example is already configured to import the Gateway from a local directory, |
| 125 | +from which it's published on localnet. On testnet and mainnet the Gateway will |
| 126 | +be imported from a public repo, instead. |
| 127 | + |
| 128 | +```toml filename="sui/Move.toml" |
| 129 | +[dependencies] |
| 130 | +gateway = { local = "/usr/local/share/localnet/protocol-contracts-sui"} |
| 131 | +``` |
| 132 | + |
| 133 | +Build: |
| 134 | + |
| 135 | +``` |
| 136 | +sui move build --force |
| 137 | +``` |
| 138 | + |
| 139 | +Deploy: |
| 140 | + |
| 141 | +``` |
| 142 | +sui client publish \ |
| 143 | + --skip-dependency-verification \ |
| 144 | + --json 2>/dev/null | jq -r '.objectChanges[] | select(.type == "published") | .packageId' |
| 145 | +``` |
| 146 | + |
| 147 | +``` |
| 148 | +0xdefdceb18b96981b3635688ec93838845eb3534991d312b7562e2c1c6e4367a0 |
| 149 | +``` |
| 150 | + |
| 151 | +We're using `jq` to get the published module ID, but you can skip this to see |
| 152 | +the whole output. |
| 153 | + |
| 154 | +## Get Coins |
| 155 | + |
| 156 | +Get a list of coins for the currently active address: |
| 157 | + |
| 158 | +``` |
| 159 | +sui client objects \ |
| 160 | + $(sui client active-address) \ |
| 161 | + --json | jq -r '.[] | select(.data.type == "0x2::coin::Coin<0x2::sui::SUI>") | .data.objectId' |
| 162 | +``` |
| 163 | + |
| 164 | +``` |
| 165 | +0x561e2c0f84601d7a97bf57ed3b4258bbd60741a3ebecb5865e6dd92833e33c58 |
| 166 | +0x7589bdfab5ccd5bc9ce40eefeb883c9fd817fbe74c89613e4d48fbcd90b12cf6 |
| 167 | +0x7b18cbdb427965e851e6a128e43744f3452898c82605d5c7a4db681c9a7ffb91 |
| 168 | +0xbd5270f4b2f90786cf9ab56b03baff734dad7e10a1288e9d0f4e188e37ed5209 |
| 169 | +0xe0736dace410531fe970f03e45bb2797be0bcce083091f6b774c2ccc3132921c |
| 170 | +``` |
| 171 | + |
| 172 | +## Deposit from a Sui Contract |
| 173 | + |
| 174 | +``` |
| 175 | +sui client call \ |
| 176 | + --package 0xdefdceb18b96981b3635688ec93838845eb3534991d312b7562e2c1c6e4367a0 \ |
| 177 | + --module connected \ |
| 178 | + --function deposit \ |
| 179 | + --type-args 0x2::sui::SUI \ |
| 180 | + --args 0x332483152b600f388b64adb4d98509ded379167df6047c49a564a4ed62f8bb71 \ |
| 181 | + 0x561e2c0f84601d7a97bf57ed3b4258bbd60741a3ebecb5865e6dd92833e33c58 \ |
| 182 | + 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7 |
| 183 | +``` |
| 184 | + |
| 185 | +- `--package`: package ID of the Sui contract deployed in the previous step |
| 186 | +- `--args`: |
| 187 | + - Gateway Object ID from the table in the output of localnet |
| 188 | + - One of the coins owned by the current address |
| 189 | + - Recipient address on ZetaChain |
| 190 | + |
| 191 | +## Deposit and Call a Universal Contract from Sui Contract |
| 192 | + |
| 193 | +``` |
| 194 | +sui client call \ |
| 195 | + --package 0xdefdceb18b96981b3635688ec93838845eb3534991d312b7562e2c1c6e4367a0 \ |
| 196 | + --module connected \ |
| 197 | + --function deposit_and_call \ |
| 198 | + --type-args 0x2::sui::SUI \ |
| 199 | + --args 0x332483152b600f388b64adb4d98509ded379167df6047c49a564a4ed62f8bb71 \ |
| 200 | + 0x7589bdfab5ccd5bc9ce40eefeb883c9fd817fbe74c89613e4d48fbcd90b12cf6\ |
| 201 | + 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7 \ |
| 202 | + $(cast abi-encode "function(string)" "alice") |
| 203 | +``` |
| 204 | + |
| 205 | +Note that in this example we're calling the `deposit_and_call` function and |
| 206 | +passing one more argument: the payload. ZetaChain does not impose any specific |
| 207 | +encoding on the payload, but since you're calling an EVM universal contract on |
| 208 | +ZetaChain, it's easier to use [ABI |
| 209 | +encoding](https://docs.soliditylang.org/en/develop/abi-spec.html). Call |
| 210 | +Foundry's `cast` (or any other tool) to encode a string. |
0 commit comments