Build
reference
Universal App Template

ZetaChain comes with a smart contract template (opens in a new tab) that makes it easy to get started building dapps.

git clone https://github.com/zeta-chain/template

The template uses Hardhat (opens in a new tab) to compile, test, and deploy contracts. It also imports @zetachain/toolkit (opens in a new tab) 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.

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.

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.

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

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.

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.

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

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