Smart Contract Template
ZetaChain comes with a smart contract template that makes it easy to get started building dapps.
git clone https://github.com/zeta-chain/template
Both omnichain tutorials and cross-chain messaging tutorials use this template.
The template uses Hardhat to compile, test, and deploy
contracts. It also imports
@zetachain/toolkit
that provides a
useful set of utilities for creating contracts, querying balances, tracking
cross-chain transactions, accessing the faucet, and more. The template exposes
most of the features available in the toolkit through Hardhat tasks.
Generating a Random Wallet
To generate a random wallet:
npx hardhat account --save
This command generates a random wallet, prints information about the wallet to
the terminal, and saves the private key to a .env
file to make it accessible
to Hardhat. If you don't want to save the wallet (for example, if you just need
an address to send tokens to for testing purposes), you can run the command
without the --save
flag.
If you already have a private key or a mnemonic you want to import, you can use
the --recover
flag:
npx hardhat account --save --recover
The account
command will prompt you for a private key or a mnemonic, print the
derived addresses and save the private key into the .env
file.
The account
command shows derived addresses in hexacecimal (for EVM-based
chains), bech32 with zeta
prefix for ZetaChain, and bech32 for Bitcoin.
Querying for Token Balances
To query for token balances:
npx hardhat balances
This command queries token balances for the account address derived from the
private key specified in the .env
.
If you need to query for balances as part of a script, you can also use a
--json
flag to output the balances in JSON format:
npx hardhat balances --json
If you want to query for token balances for a different account, you can use the
--address
flag:
npx hardhat balances --address ADDRESS
The balances
command supports querying for native gas tokens, wrapped ZETA on
all connected chains as well as ZetaChain, ZRC-20 tokens, and BTC on Bitcoin.
Requesting Tokens from the Faucet
To request ZETA tokens from the faucet:
npx hardhat faucet
This command requests tokens from the faucet for the account address derived
from the private key specified in the .env
. Tokens sent to the address on
ZetaChain.
You can specify a different address to send the tokens to:
npx hardhat faucet --address ADDRESS
Alternatively, you can install a standalone faucet CLI:
yarn global add @zetachain/faucet-cli
You can then use it with the following command:
zetafaucet -h
Creating an Omnichain Contract
The template includes a set of commands for generating code for smart contracts and helper tasks.
To create a new omnichain contract:
npx hardhat omnichain MyContract
This command creates a new omnichain contract in contracts/MyContract.sol
, a
task to deploy the contract in tasks/deploy.ts
, and a task to interact with
the contract in tasks/interact.ts
.
When an omnichain contract is called, it can receive data in the data
field of
a transaction. This data is passed to the message
parameter of the contract's
onCrossChainCall
function. To specify the fields of the message
parameter,
use positional arguments:
npx hardhat omnichain MyContract recepient:address description quantity:uint256
A field may have a type specified after the field name, separated by a colon. If
no type is specified, the type defaults to string
.
Supported types are: address
, bool
, bytes32
, string
,
int
,int8
,int16
,int128
,int256
,uint
,uint8
,uint16
,uint128
,uint256
.
Learn more about omnichain contracts by following the tutorials.
Creating a Cross-Chain Messaging Contract
To create a new cross-chain messaging contract:
npx hardhat messaging MyContract
This command creates a new cross-chain messaging contract in
contracts/MyContract.sol
, a task to deploy the contract in tasks/deploy.ts
,
and a task to interact with the contract in tasks/interact.ts
.
You can pass additional optional arguments to the messaging
command to specify
the data that will be sent in the message.
npx hardhat messaging MyContract token:uint256 sender:address to:address description
A field may have a type specified after the field name, separated by a colon. If
no type is specified, the type defaults to string
.
The list of supported types is the same as for omnichain contracts.
Learn more about cross-chain messaging by following the tutorials.
Tracking a Cross-Chain Transaction
After broadcasting a cross-chain transaction on a connected chain either to a cross-chain messaging contract or to trigger an omnichain contract, you can track its status:
npx hardhat cctx TX_HASH
Verifying a Contract
To verify a contract deployed on ZetaChain:
npx hardhat verify:zeta --contract ADDRESS
Select the contract to verify:
? Select a contract to verify: (Use arrow keys)
@zetachain/zevm-protocol-contracts/contracts/interfaces/IZRC20.sol:IZRC20
@zetachain/zevm-protocol-contracts/contracts/interfaces/zContract.sol:zContract
❯ contracts/Withdraw.sol:Withdraw
After the confirmation the contract will be verified.
Sending Tokens
Sending ZETA from ZetaChain to Goerli:
npx hardhat send-zeta --amount 1 --network zeta_testnet --destination goerli_testnet
Sending ZETA from Goerli to ZetaChain:
npx hardhat send-zeta --amount 1 --network goerli_testnet --destination zeta_testnet
Depositing gETH to ZetaChain as ZRC-20:
npx hardhat send-zrc20 --amount 1 --network goerli_testnet --destination zeta_testnet
Withdrawing ZRC-20 from ZetaChain go Goerli as gETH:
npx hardhat send-zrc20 --amount 1 --network zeta_testnet --destination goerli_testnet
Depositing tBTC from the Bitcoin testnet to ZetaChain:
npx hardhat send-btc --amount 1 --recipient TSS_ADDRESS --memo RECIPIENT_ADDRESS_WITHOUT_0x
Querying Cross-Chain Fees
To query cross-chain fees:
npx hardhat fees
This command will query the latest omnichain withdrawal fees as well as cross-chain messaging fees.
To calculate the fees for a different gas limit use the --gas
flag:
npx hardhat fees --gas 300000