There are three deployment scenarios:
- devnet, used for localhost development, the example config file is
hardhat.config.example-devnet.js
. - testnet, such as
Rinkebby
,Mumbai
, used for public test, the example config file ishardhat.config.example-testnet.js
. - mainnet, such as
Ethereum
,Polygon
, used for official production, the example config file ishardhat.config.example-mainnet.js
.
Before deploy you should override the default config file with the example config file:
cp -f hardhat.config.example-devnet.js hardhat.config.js
There are multi chain configurations in the configure file, such as the polygonTestConfig
in hardhat.config.example-testnet.js
is used to configure Mumbai
( a polygon testnet).
const polygonTestConfig = {
macro: {
BLOCK_PERIOD: '2 seconds',
UPGRADE_NOTICE_PERIOD: 0,
PRIORITY_EXPIRATION: 0,
CHAIN_ID: 1,
ENABLE_COMMIT_COMPRESSED_BLOCK: true
},
url: "https://matic-mumbai.chainstacklabs.com",
scan: "YOUR_ETHERSCAN_KEY"
};
macro
is an object and define some macro variables consumed by @nomiclabs/hardhat-solpp
(a solidity preprocessor) to generate solidity code. CHAIN_ID
is the id defined in zkLink network(not the blockchain id). ENABLE_COMMIT_COMPRESSED_BLOCK
is switch to enable block committed with compressed mode. You need to set the CHAIN_ID
and ENABLE_COMMIT_COMPRESSED_BLOCK
according to the actual deployment situation. Mostly you SHOULD NOT modify the value of BLOCK_PERIOD
, UPGRADE_NOTICE_PERIOD
and PRIORITY_EXPIRATION
.
macro
also has three variables about constraints on CHAIN_ID
:
- MIN_CHAIN_ID, the min chain id of zkLink network , and SHOULD be 1.
- MAX_CHAIN_ID, the max chain id of zkLink network.
- ALL_CHAINS, the supported chain ids flag.
You should set MAX_CHAIN_ID
and ALL_CHAINS
according to the actual deployment situation. For example, the initially deployment we support two chains: 1 and 2, so MAX_CHAIN_ID
should be 2 and ALL_CHAINS
should be 3(1 << 0 | 1 << 2
). The secondly deployment we supprot another chain: 3, and MAX_CHAIN_ID
should be updated to 3 and ALL_CHAINS
should be updated to 7(1 << 0 | 1 << 1 | 1 << 2
).
url
is the blockchain rpc url that hardhat connected to. scan
is the key used by @nomiclabs/hardhat-etherscan
to verify contract code deployed to etherscan
explorer.
The NET
env variable determines the chain configurtion used for deploy commands. For example, deploy zkLink to Mubai
you should export NET=POLYGONTEST
before npx hardhat deployZkLink
or
NET=POLYGONTEST npx hardhat [global options] deployZkLink [command options]
deployerKey
is the private key of deploryer when deploying contracts. governorKey
is the private key of governor who has the management authority of the contract. You only need to set deployerKey
when delolying to mainnet, and governor should be different with the deployer. You may need to set governorKey
different with deployerKey
when deploying to testnet to do some authority tests. You don't need to set bot of them when deploying to devnet, beacuse of all keys are come from the default accounts generated by hardhat.
$ npx hardhat help deployZkLink
Hardhat version 2.10.1
Usage: hardhat [GLOBAL OPTIONS] deployZkLink [--block-number <INT>] [--commitment <STRING>] --fee-account <STRING> [--force <BOOLEAN>] --genesis-root <STRING> --governor <STRING> [--skip-verify <BOOLEAN>] [--sync-hash <STRING>] [--timestamp <INT>] --validator <STRING>
OPTIONS:
--block-number The block number (default: 0)
--commitment The block commitment (default: "0x0000000000000000000000000000000000000000000000000000000000000000")
--dummy Deploy dummy contracts for local development (default: false)
--fee-account The feeAccount address (default is same as deployer)
--force Fore redeploy all contracts (default: false)
--genesis-root The block root hash
--governor The governor address (default is same as deployer)
--skip-verify Skip verify, ignored when dummy is true (default: false)
--sync-hash The block syncHash (default: "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
--timestamp The block timestamp (default: 0)
--validator The validator address (default is same as deployer)
deployZkLink: Deploy zklink contracts
--block-number
,--commitment
,--genesis-root
,--sync-hash
,--timestamp
are used to produce genesie block. When deploying for the first time --block-number
,--commitment
,--sync-hash
and --timestamp
can be left unset. When deploying for appending a new chain all these options need to be set with the latest exectuted block properties.
--dummy
is used for local development, when set to true
, a VerifierMock
contract will be deployed instead of Verifier
. The mock verifier will always return true
when validator send prove to zkLink contract.
You could left--governor
and --validator
be unset when deploy to devnet or testnet, but DOT NOT use deployer address as network governor and validator on the mainnet.
After the deployment is complete, a log file with a name of deploy_${NET}.log
will be generated in the log
directory of the project root path.
{
"deployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"governor": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"verifierTarget": "0x29bE639a527a50c1F2E4E338f80B75f5e8b31963",
"verifierTargetVerified": true,
"peripheryTarget": "0xD974bF8CEFAc444DDB5A8F20745C21745C34A9f9",
"peripheryTargetVerified": true,
"zkLinkTarget": "0x3EA14a463a036ecccD3F0A737CAc730780D0d8f9",
"zkLinkTargetVerified": true,
"deployFactory": "0x96773dAA23E81f6D75c4F464D0da384183E35fD1",
"deployFactoryBlockHash": "0x99561476eaaedb8b70c3c45493989f453f406c5b4f63ac069c4a2993edd0c726",
"deployTxHash": "0x8e01bbf93999be4326a6bda08aad0b9fcd1a992e4b869d1b11dd938ef4b9cc69",
"zkLinkProxy": "0x73647ca572973DDB912B3D21Ff42d59ef7dF119B",
"verifierProxy": "0x3B6bAf1cd92ad8269A9c3bD844598e3ac8e87bEA",
"gatekeeper": "0x9352E8c8103ef2C6550B509Fd20394F4307DA0e1"
}
The zkLinkProxy
is the address we used to interacted with zkLink contract, such as: depositETH
, addToken
,addBridge
.
If there is a network error occurs during the execution of the command, you can execute it again and the command will start from place where it failed last time.
For example:
NET=ETH npx hardhat deployZkLink --governor GOVERNOR_ADDRESS --validator VALIDATOR_ADDRESS --feeAccount FEE_ACCOUNT_ADDRESS --genesis-root GENESIS_ROOT_HASH
$ npx hardhat help deployLZBridge
Hardhat version 2.10.1
Usage: hardhat [GLOBAL OPTIONS] deployLZBridge --force <BOOLEAN> --governor <STRING> --skip-verify <BOOLEAN>
OPTIONS:
--force Fore redeploy all contracts, default is false
--governor The governor address (default read from zkLink deploy log)
--skip-verify Skip verify, default is false
deployLZBridge: Deploy LayerZeroBridge
LayerZeroBridge is used to bridge cross chain verify message between different chains.This command is only available in mainnet and testnet, we couldn't use this bridge in devnet, but we can use a EOA address as a dummy bridge.
After the deployment is complete, a log file with a name of deploy_lz_bridge_${NET}.log
will be generated in the log
directory of the project root path.
{
"deployer": "0x7032F91C4734c3091289E153f23bf430b8bEBd8C",
"governor": "0x7032F91C4734c3091289E153f23bf430b8bEBd8C",
"lzBridgeProxy": "0xd3e0024e84BB9631C314AF0a20A96ae3Bc64abe9",
"lzBridgeTarget": "0x96CeaF288e289cDa49E457CAAB8976F10e263b10"
}
The lzBridgeProxy
is the address that used to addBridge
.
For example:
NET=ETH npx hardhat deployLZBridge
After completing the deployment of zkLink and lzBridge on all chains(eg. AVAXTEST and POLYGONTEST), the logs of the delopy log directory are as flows:
log/
deploy_AVAXTEST.log
deploy_POLYGONTEST.log
deploy_lz_bridge_AVAXTEST.log
deploy_lz_bridge_POLYGONTEST.log
No deploy_lz_bridge log exist in devnet.
We need to connect zkLink with lzBridge for cross chain block verify. Each chain will need to execute addBridge
, setDestinations
and setApp
, which means if we deploy on AVAXTEST and POLYGONTEST, the commands that need to be executed are:
NET=AVAXTEST npx hardhat addBridge [command options]
NET=AVAXTEST npx hardhat setDestinations [command options]
NET=AVAXTEST npx hardhat setApp [command options]
NET=POLYGONTEST npx hardhat addBridge [command options]
NET=POLYGONTEST npx hardhat setDestinations [command options]
NET=POLYGONTEST npx hardhat setApp [command options]
Only addBridge need to execute in devnet.
Warning all these commands require governorKey
to be set in configuration and SHOULD NOT be used in mainnet. In mainnet all manangement operations involving the governor will need to follow the rules of DAO
.
$ npx hardhat help addBridge
Hardhat version 2.10.1
Usage: hardhat [GLOBAL OPTIONS] addBridge [--bridge <STRING>]
OPTIONS:
--bridge The bridge address (default get from deploy log)
addBridge: Add bridge to zkLink
In devnet we could set the bridge to a EOA address as a dummy bridge, and then we could execute command syncProgress
to simulator receiving a cross chain verify message on zkLink contract side.
For example:
NET=AVAXTEST npx hardhat addBridge
or
NET=LOCAL1 npx hardhat addBridge --bridge EOA_ADDRESS
$ npx hardhat help setDestinations
Hardhat version 2.10.1
Usage: hardhat [GLOBAL OPTIONS] setDestinations
setDestinations: Set layerzero bridge destinations (only support testnet)
This command will search the deloy_lz_bridge
logs in the log directory, and set lzBridge gates of all other chains.
For example:
NET=AVAXTEST npx hardhat setDestinations
$ npx hardhat help setApp
Hardhat version 2.10.1
Usage: hardhat [GLOBAL OPTIONS] setApp
setApp: Set layerzero supported app
LayerZeroBridge support both zkl bridge and zkLink bridge, this command will read deploy_zkl
log and if ZKL
is deployed it will set support zkl to true. Also it will read deploy
log and if ZkLink
is deployed it will set support zkLink to true.
For example:
NET=AVAXTEST npx hardhat setApp