This directory contains script to deploy the protocol contracts on ZetaChain and connected chains.
To execute a deployment script, the general format is:
forge script scripts/deploy/<Script>.s.sol --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --broadcast
A .env
file should be set up and updated during deployments according to expected env variables in scripts, check .env.sample
for example on how it should look like.
Currently, .env.sample
is set with test env variables that can be used to test scripts locally with anvil
using first account private key.
The GatewayEVM and ERC20Custody contracts must be deployed to setup a new environment on a connected chain.
GatewayEVM
The following environment variables must be set in the .env
file:
TSS_ADDRESS
: address of the TSS used on the networkGATEWAY_ADMIN_ADDRESS_EVM
: address of the adminZETA_ERC20_EVM
: address of the ZETA token on the network
Once setup, the contract can be deployed:
forge script scripts/deploy/deterministic/DeployGatewayEVM.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--etherscan-api-key <ETHERSCAN_API_KEY> \
--chain-id <CHAIN_ID> \
--broadcast
Note: verify
and etherscan-api-key
options are optional for the contract deployment itself. Some other explorers require different options, for example Blockscout:
--verify \
--verifier blockscout \
--verifier-url <VERIFIER_URL> \
ERC20Custody
In addition to the previous environment variables, the following environment variables must be set:
ERC20_CUSTODY_ADMIN_ADDRESS_EVM
: address of the adminGATEWAY_PROXY_EVM
: address of the proxy gateway contract deployed in previous step
Once setup, the contract can be deployed:
forge script scripts/deploy/deterministic/DeployERC20Custody.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--etherscan-api-key <ETHERSCAN_API_KEY> \
--chain-id <CHAIN_ID> \
--broadcast
Since ZRC20s are deployed by the protocol, only the GatewayZEVM
contract needs to be deployed manually on ZetaChain.
The following environment variables must be set in the .env
file:
GATEWAY_ADMIN_ADDRESS_ZEVM
: address of the adminWZETA
: wrapped ZETA contract address
Once setup, the contract can be deployed:
forge script scripts/deploy/deterministic/DeployGatewayZEVM.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--verifier blockscout \
--verifier-url <VERIFIER_URL> \
--chain-id <CHAIN_ID> \
--broadcast
Protocol contracts (Gateway and ERC20Custody) follow ERC1967 standard. The contracts can be upgraded by deploying a new implementation and upgrading to this new implementation.
The implementation contracts don't require environment variables or paramters to be deployed.
GatewayEVM
Deploy a wew implementation of the GatewayEVM:
forge script scripts/deploy/deterministic/DeployGatewayEVMImplementation.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--etherscan-api-key <ETHERSCAN_API_KEY> \
--chain-id <CHAIN_ID> \
--broadcast
ERC20Custody
Deploy a wew implementation of the ERC20Custody:
forge script scripts/deploy/deterministic/DeployERC20CustodyImplementation.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--etherscan-api-key <ETHERSCAN_API_KEY> \
--chain-id <CHAIN_ID> \
--broadcast
GatewayZEVM
Deploy a wew implementation of the GatewayZEVM:
forge script scripts/deploy/deterministic/DeployGatewayZEVMImplementation.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--verifier blockscout \
--verifier-url <VERIFIER_URL> \
--chain-id <CHAIN_ID> \
--broadcast
After the implementation is deployed, the contract can be upgraded by calling the following function from the admin:
upgradeToAndCall(0, <implementation_address>, "")
The scripts in upgrade
allow to locally simulate the upgrade process with the protocol contract and verify the state is not corrupted.
First a forked localnet must be started in a separate terminal. The RPC will be the connected EVM chain for testing GatewayEVM
or ERC20Custody
, or ZetaChain for GatewayZEVM
anvil --fork-url <rpc>
Example:
anvil --fork-url https://ethereum-sepolia.rpc.subquery.network/public
anvil --fork-url https://zetachain-athens.g.allthatnode.com/archive/evm
The following environment variable must be set:
export PROXY_ADDRESS=<proxy address of the contract to test>
export ADMIN_ADDRESS=<address of the admin that upgrade the contract>
Then the script can be run.
GatewayEVM
:
forge script scripts/upgrade/SimulateGatewayEVMUpgrade.s.sol --rpc-url http://localhost:8545
ERC20Custody
:
forge script scripts/upgrade/SimulateERC20CustodyUpgrade.s.sol --rpc-url http://localhost:8545
GatewayZEVM
:
forge script scripts/upgrade/SimulateGatewayZEVMUpgrade.s.sol --rpc-url http://localhost:8545
The scripts will log the different state variables of the contract. There is no automatic assertion, the values must be manually checked against the current values of the proxy contract.
These scripts must be maintained in the future to log all eventual new variables.
Example output:
Script ran successfully.
== Logs ==
Upgraded contract state:
custody address: 0xD80BE3710F08D280F51115e072e5d2a778946cd7
tss address: 0x8531a5aB847ff5B22D855633C25ED1DA3255247e
zetaConnector address: 0x0000000000000000000000000000000000000000
zetaToken address: 0x1432612E60cad487C857E7D38AFf57134916c902
ZRC20 contract is upgradable by the protocol but doesn't follow the ERC1967Proxy
standard.
The process requires to:
- Deploy a reference for the ZRC20 to upgrade
- Use the
MsgUpdateContractBytecode
message of the blockchain to upgrade the contract using the reference bytecode
The reference must be deployed using the same constructor argument as the base contract. To obtain the arguments, the following utility script can be used:
./scripts/utils/get_zrc20_info.sh <zrc20_address> <rpc>
Note: the script requires cast
CLI (Foundry suite) to be installed.
The command prints the environment variable to put in the .env
file to deploy the new contract.
Example:
SYSTEM_CONTRACT=0xEdf1c3275d13489aCdC6cD6eD246E72458B8795B
ZRC20_NAME=ZetaChain ZRC20 SOL on Solana Devnet
ZRC20_SYMBOL=SOL.SOLANA
ZRC20_DECIMALS=9
ZRC20_CHAIN_ID=901
ZRC20_COIN_TYPE=1
ZRC20_GAS_LIMIT=5000
Once the environment variables are set, the ZRC20 can be deployed:
forge script scripts/deploy/DeployZRC20.s.sol \
--private-key <PRIVATE_KEY> \
--rpc-url <RPC_URL> \
--verify \
--verifier blockscout \
--verifier-url <VERIFIER_URL> \
--chain-id <CHAIN_ID> \
--broadcast
After deployment, the following utility script allows to verify the ZRC20 has been deployed with the correct constructor arguments:
./scripts/utils/compare_zrc20_info.sh <base_contract> <reference_contract> <rpc>
Deployment scripts in deterministic
uses create2 with Foundry (https://book.getfoundry.sh/tutorials/create2-tutorial) to perform deterministic deployment of contracts.
This ensures that the GatewayEVM contract will have the same address on every EVM chain.
Since UUPS proxy is used for the contracts, both implementation and ERC1967Proxy
are deployed using above technique:
- calculate expected address
- adding a salt to deployment
- basic assertions to verify that deployed address is same as expected
The contract can be upgraded with the following documentation: https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades. It requires:
- deploy new implementation (doesn't need to be deterministic since proxy address doesn't change)
- use plugin to upgrade proxy
deterministic/DeployERC20Custody.s.sol
: deploy the ERC20 custody contract on a connected chaindeterministic/DeployERC20CustodyImplementation.s.sol
: deploy the ERC20 custody contract implementation on a connected chain for a contract upgradedeterministic/DeployGatewayEVM.s.sol
: deploy the gateway contract on a connected chaindeterministic/DeployGatewayEVMImplementation.s.sol
: deploy the gateway contract implementation on a connected chain for a contract upgradedeterministic/DeployGatewayZEVM.s.sol
: deploy the gateway contract on ZetaChaindeterministic/DeployGatewayZEVMImplementation.s.sol
: deploy the gateway contract implementation on ZetaChain for a contract upgradedeterministic/TestERC20.s.sol
: deploy a ERC20 for test purposedeterministic/ZetaConnectorNonNative.s.sol
: deploy the ZETA connector contract on a connected chain, currently not useddeterministic/UpgradeGatewayEVM.s.sol
: upgrade the GatewayEVM contract to a test contract implementation, used for test purposes onlyDeployZRC20.s.sol
: deploy a ZRC20 for test purpose or for the ZRC20 upgrade process