Deploy Hyperlane with Local Agents
This guide is for advanced users who have some understanding of configuring and deploying Hyperlane.
If not done so already, beginners should get started by deploying Hyperlane with Kurtosis agents.
Terminology
The "local chain" is your new chain that you want to deploy Hyperlane onto.
A "remote chain" is a chain with an existing Hyperlane deployment that you want your local chain to send & receive messages to & from.
Overview
There are six steps in this guide:
- Set up keys that you will use to deploy contracts and run validators and relayers.
- Deploy contracts to the local chain and to every remote chain with which the local chain will be able to send and receive messages.
- Run a validator to provide the signatures needed for the Interchain Security Modules you deployed.
- Run a relayer to send and receive messages between the chains you deployed contracts to.
- Send a test message to confirm that your relayer is able to deliver messages to and from each pair of chains.
- Deploy a Warp Route to send token value, not just messages, across chains.
Getting Started
1. Set up keys
There are three keys you must set up and fund.
To get started, you can simplify by using the same hexadecimal key for all three roles.
Key Role | Description | Funding Needs |
---|---|---|
Contract Deployer | 32 byte hexadecimal private key | Funded on all the chains on which we need to deploy contracts. |
Validator Accounts | A list of validator addresses that will sign outbound messages from your local chain. Just one validator works to get started quickly. | A small amount so validators can announce the location of their signatures onchain with a one-time transaction |
Relayer Accounts | The single relayer you will operate requires an account on each chain it will deliver messages to & from | The relayer must have a balance on all chains it's relaying between. |
For instructions on how to generate keys, see the agent keys section. Your deployer key must be a hexadecimal key, while validator and relayer keys can be hexadecimal or AWS KMS.
If deploying on a local network using Foundry's Anvil, use the following command to fund your newly-generated account. It uses one of the pre-funded private keys to transfer 1 ETH to the address in the $YOUR_TARGET_ADDRESS
environment variable.
cast send $YOUR_TARGET_ADDRESS \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--value $(cast tw 1)
2. Deploy contracts
Once you have set up deployer, validator, and relayer keys it's time to use the Hyperlane CLI to deploy smart contracts to the local and remote chains.
On the local chain, we will deploy:
- The core contracts, including a Mailbox that can be used to send and receive messages.
On all chains, we will deploy:
- A Multisig ISM that can be used to verify inbound messages from the other local & remote chains.
- An
InterchainGasPaymaster
, which can be used to pay our relayer for delivering interchain messages. - A
TestRecipient
, which we will send messages to, in order to test that everything is working correctly.
Setup
First, install the Hyperlane CLI from NPM. Node 16 or newer is required. The following command will install it globally on your machine. See the package page for alternatives such as temporary install or building from source.
npm install -g @hyperlane-xyz/cli
Next, determine what custom chain configs you will need for your local and remote chains. Any chains that are already included in the Hyperlane SDK won't need a chain config (but can optionally have one if you want to override default settings). Run the following to see the default SDK chains:
hyperlane chains list
You can press space to select your chains. For any chains that need custom configs, you can define them manually using JSON or YAML (see example config), or create them with the following command:
hyperlane config create chain
Now the CLI will know how to interact with all your chains, but it will also need to know how to configure your Interchain Security Module (ISM).
To create a multisig ISM configs, you can define it manually using JSON or YAML (see example config here), or create it with the following command:
hyperlane config create ism
When asked about the multisig type, choose message id ism
. In the context of this guide, we will be using a 1/1 multisig, so choose a threshold of 1
and enter the address of your key.
Deploy
We're now ready to use the deploy core
command to deploy the Hyperlane contracts. To pay for transactions, the command will need the contract deployer key from step 1, which can be provided via the HYP_KEY
env variable or as a command argument.
hyperlane deploy core \
--targets chain1,chain2,... \ # all the chains you want to bridge between
--chains $CHAIN_CONFIG_FILE \ # path to chains.yaml config e.g. ./configs/chains.yaml
--ism $MULTISIG_CONFIG_FILE \ # path to ism.yaml config e.g. ./configs/ism.yaml
--artifacts $PREDEPLOYED_ARTIFACT_FILE \ # (optional) in case you want to reuse contracts you've already predeployed
--out $OUT_DIR \ # (optional) deployment contract artifacts
--key $YOUR_DEPLOYER_PRIVATE_KEY
Verify
Deployment contract artifacts will be written to to the artifacts/
folder by default. The deployer will create two timestamped files, agent-config-{timestamp}.json
and core-deployment-{timestamp}.json
The core-deployment
file contains the addresses of core contracts, organized by chain.
The agent-config
file contains the data needed to run Hyperlane agents for the next step.
3. Run a validator
Validators provide the security for messages sent from your chain to remote chains.
Setup directories
First, set the CONFIG_FILES
environment variable to the path of the agent config generated in the deploy contracts step. For example:
export CONFIG_FILES=/full/path/to/configs/agent-config-{timestamp}.json
Next, create a local directory for your validator to write its signatures to. Remember the path, as you will need this when configuring your validator.
# Pick an informative name specific to the chain you're validating
export VALIDATOR_SIGNATURES_DIR=/tmp/hyperlane-validator-signatures-<your_chain_name>
# Create the directory
mkdir -p $VALIDATOR_SIGNATURES_DIR
You will not be able to mount anything in /tmp
when running the agent via Docker on Mac. To counter this, create a local tmp
directory to mount instead.
# Create a local tmp directory that can be accessed by docker
mkdir tmp
# Pick an informative name specific to the chain you're validating
export VALIDATOR_SIGNATURES_DIR=tmp/hyperlane-validator-signatures-<your_chain_name>
# Create the directory
mkdir -p $VALIDATOR_SIGNATURES_DIR
Configure
There are numerous parameters that validators can be configured with. For this guide, we are concerned with just a handful:
Parameter | Description |
---|---|
--db | Path for writing persistent data to disk. |
--originChainName | Name of the chain being validated (e.g. ethereum ). |
--checkpointSyncer.type | Set to localStorage for this guide. |
--checkpointSyncer.path | Path to local directory where validator signatures will be written. |
--validator.key | Your validator's hexadecimal private key. |
Make sure the validator key corresponds to the address provided when setting up your MultisigIsmConfig. Otherwise, the Multisig ISM you deployed in the previous step will not be able to verify messages sent from your chain.
- Using Docker
- Building from source
Update agent config
Unless you are running Docker on Linux, you will also need to update the agent configuration for your network. This is because Docker does not support the host
network mode on Mac, Windows or Windows Server.
To do this, navigate to the agent-configuration at $CONFIG_FILES
and replace all instances of "localhost" or "127.0.0.1" in to host.docker.internal
. For example:
...
"localnet1": {
...
"rpcUrls": [
{
// "http": "http://localhost:8545"
// "http": "http://127.0.0.1:8545"
"http": "http://host.docker.internal:8545"
}
],
...
},
...
Mounting directories
Running with Docker adds an extra layer of complexity because config files need to be accessible from within the Docker container, and validator signatures need to be accessible from outside of the container. This can be solved by mounting directories on your file system into the container.
In the arguments below, we:
- Set the
$CONFIG_FILES
environment variable to a fixed path within the container. - Mount the agent config file to this fixed path and making it readonly.
- Mount the persistent data directory at a fixed path within the container.
- Mount the validator signatures directory to a fixed path within the container.
...
-e CONFIG_FILES=/config/agent-config.json \
--mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \
--mount type=bind,source="$(pwd)"/hyperlane_db_validator_<your_chain_name>,target=/hyperlane_db \
--mount type=bind,source="$(pwd)"/$VALIDATOR_SIGNATURES_DIR,target=/tmp/validator-signatures \
...
Hardcoding these paths deduplucates the configuration, making it easier to pass the right arguments when running the container. See the example below, where that's left is for you to configure the chain name and validator key.
...
./validator \
--db /hyperlane_db \
--originChainName <your_chain_name> \
--checkpointSyncer.type localStorage \
--checkpointSyncer.path /tmp/validator-signatures \
--validator.key <your_validator_key>
...
Clone and setup
First, clone the Hyperlane monorepo:
git clone git@github.com:hyperlane-xyz/hyperlane-monorepo.git
Then follow the setup instructions in the rust
directory. This should setup rustup
as well as Rosetta 2 if you are on Apple Silicon.
# install rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# (apple silicon only) install rosetta 2
softwareupdate --install-rosetta --agree-to-license
Run
- Using Docker
- Building from source
Now that you understand more about configuring validator arguments, pull the latest docker image:
docker pull gcr.io/abacus-labs-dev/hyperlane-agent:main
Finally, run the validator:
docker run \
-it \
-e CONFIG_FILES=/config/agent-config.json \
--mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \
--mount type=bind,source="$(pwd)"/hyperlane_db_validator_<your_chain_name>,target=/hyperlane_db \
--mount type=bind,source="$(pwd)"/$VALIDATOR_SIGNATURES_DIR,target=/tmp/validator-signatures \
gcr.io/abacus-labs-dev/hyperlane-agent:main \
./validator \
--db /hyperlane_db \
--originChainName <your_chain_name> \
--checkpointSyncer.type localStorage \
--checkpointSyncer.path /tmp/validator-signatures \
--validator.key <your_validator_key>
After following the setup instructions, you should now be able to use cargo
to run the Validator:
cargo run --bin validator -- \
--db ./hyperlane_db_validator_<your_chain_name> \
--originChainName <your_chain_name> \
--checkpointSyncer.type localStorage \
--checkpointSyncer.path $VALIDATOR_SIGNATURES_DIR \
--validator.key <your_validator_key>
You can alternatively build out the agent:
cargo build --release bin validator
And run the binary directly:
./target/release/validator \
--db ./hyperlane_db_validator_<your_chain_name> \
--originChainName <your_chain_name> \
--checkpointSyncer.type localStorage \
--checkpointSyncer.path $VALIDATOR_SIGNATURES_DIR \
--validator.key <your_validator_key>
For further information, check out the Validators guide.