Skip to main content
Version: Endpoint V2

Adding Networks

When working with a LayerZero project, it searches for the closest hardhat.config.ts and layerzero.config.ts files starting from the Current Working Directory. This file normally lives in the root of your project.

This guide shows how to add a new EVM network to your existing LayerZero project.

Example scenario: You have an OFT deployed on Optimism Sepolia and Base Sepolia, and want to add Arbitrum Sepolia to your mesh.

Existing networks in your mesh:

  • Optimism Sepolia (EID: 40232)
  • Base Sepolia (EID: 40245)

Network being added:

  • Arbitrum Sepolia (EID: 40231)

You will:

  • Update hardhat.config.ts with the new network's LayerZero Endpoint ID (EID) and RPC
  • Deploy your contract to the new network
  • Update layerzero.config.ts to declare the contract and connections
  • Wire peers and apply configuration across pathways

1) Add the network to hardhat.config.ts

Add an entry with the LayerZero Endpoint ID, RPC URL, and your deployer accounts. Here's the diff showing what to add:

// hardhat.config.ts
import { EndpointId } from '@layerzerolabs/lz-definitions'

export default {
networks: {
// Existing networks
'optimism-sepolia': {
eid: EndpointId.OPTSEP_V2_TESTNET,
url: process.env.RPC_URL_OPT_SEPOLIA || 'https://optimism-sepolia.gateway.tenderly.co',
accounts,
},
'base-sepolia': {
eid: EndpointId.BASSEP_V2_TESTNET,
url: process.env.RPC_URL_BASE_SEPOLIA || 'https://sepolia.base.org',
accounts,
},

// New network being added
+ 'arbitrum-sepolia': {
+ eid: EndpointId.ARBSEP_V2_TESTNET,
+ url: process.env.RPC_URL_ARB_SEPOLIA || 'https://sepolia-rollup.arbitrum.io/rpc',
+ accounts,
+ },
},
}
info

The only notable change from a standard hardhat.config.ts setup is the inclusion of a LayerZero Endpoint ID.

For hardhat specific questions, refer to the Hardhat Configuration documentation.

tip

The npx package uses @layerzerolabs/lz-definitions to enable you to reference both V1 and V2 Endpoints. Make sure if your project uses LayerZero V2 to select the V2 Endpoint (i.e., eid: EXAMPLE_V2_MAINNET).

2) Deploy your contract to the new network

Use the CLI to deploy your contract to the added network. You can deploy interactively or target a specific network.

# Interactive (select networks and tags when prompted)
pnpm hardhat lz:deploy

# Or target a specific network (example name from step 1)
# pnpm hardhat deploy --network arbitrum-sepolia --tags MyOFT

3) Add the new contract and connections to layerzero.config.ts

Specify which contracts should be connected on a per pathway basis:

// layerzero.config.ts
import {EndpointId} from '@layerzerolabs/lz-definitions';
import {ExecutorOptionType} from '@layerzerolabs/lz-v2-utilities';
import {TwoWayConfig, generateConnectionsConfig} from '@layerzerolabs/metadata-tools';
import {OAppEnforcedOption, OmniPointHardhat} from '@layerzerolabs/toolbox-hardhat';

+ const arbitrumSepoliaContract: OmniPointHardhat = {
+ eid: EndpointId.ARBSEP_V2_TESTNET,
+ contractName: 'MyOFT',
+ };

const optimismSepoliaContract: OmniPointHardhat = {
eid: EndpointId.OPTSEP_V2_TESTNET,
contractName: 'MyOFT',
};

const baseSepoliaContract: OmniPointHardhat = {
eid: EndpointId.BASSEP_V2_TESTNET,
contractName: 'MyOFT',
};

// For this example's simplicity, we will use the same enforced options values for sending to all chains
// For production, you should ensure `gas` is set to the correct value through profiling the gas usage of calling OApp._lzReceive(...) on the destination chain
// To learn more, read https://docs.layerzero.network/v2/concepts/applications/oapp-standard#execution-options-and-enforced-settings
const EVM_ENFORCED_OPTIONS: OAppEnforcedOption[] = [
{
msgType: 1,
optionType: ExecutorOptionType.LZ_RECEIVE,
gas: 80000,
value: 0,
},
];

// Add pathways to connect your new network with existing networks
+ const pathways: TwoWayConfig[] = [
+ [
+ arbitrumSepoliaContract, // New network contract
+ optimismSepoliaContract, // Existing network 1
+ [['LayerZero Labs'], []], // [ requiredDVN[], [ optionalDVN[], threshold ] ]
+ [1, 1], // [A to B confirmations, B to A confirmations]
+ [EVM_ENFORCED_OPTIONS, EVM_ENFORCED_OPTIONS], // Chain B enforcedOptions, Chain A enforcedOptions
+ ],
+ [
+ arbitrumSepoliaContract, // New network contract
+ baseSepoliaContract, // Existing network 2
+ [['LayerZero Labs'], []], // [ requiredDVN[], [ optionalDVN[], threshold ] ]
+ [1, 1], // [A to B confirmations, B to A confirmations]
+ [EVM_ENFORCED_OPTIONS, EVM_ENFORCED_OPTIONS], // Chain C enforcedOptions, Chain A enforcedOptions
+ ],
+ // ... existing pathways between your current networks
+ ];

export default async function () {
// Generate the connections config based on the pathways
+ const connections = await generateConnectionsConfig(pathways);
return {
contracts: [
+ {contract: arbitrumSepoliaContract},
{contract: optimismSepoliaContract},
{contract: baseSepoliaContract},
],
+ connections,
};
}

4) Wire peers and apply configuration

Set peers, libraries, DVN/Executor settings, and enforced options per your layerzero.config.ts.

pnpm hardhat lz:oapp:wire --oapp-config layerzero.config.ts

You can refer to defaults with the Defaults Checker before wiring in production.

5) Verify connections and configuration

# Check peers
pnpm hardhat lz:oapp:peers:get --oapp-config layerzero.config.ts

# Check pathway config
pnpm hardhat lz:oapp:config:get --oapp-config layerzero.config.ts

Checking Pathway Configurations

To check your OApp's current configuration, you can run:

npx hardhat lz:oapp:config:get --oapp-config layerzero.config.ts

This command will output a table with 3 columns:

  1. Custom OApp Config: your layerzero.config.ts configuration changes, with null values for unchanged parameters.

  2. Default OApp Config: the default LayerZero configuration for the pathway.

  3. Active OApp Config: the combination of your customized and default parameters, i.e., the active configuration.

┌────────────────────┬─────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ │ Custom OApp Config │ Default OApp Config │ Active OApp Config │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ localNetworkName │ bsc_testnet │ bsc_testnet │ bsc_testnet │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ remoteNetworkName │ sepolia │ sepolia │ sepolia │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ sendLibrary │ 0x0000000000000000000000000000000000000000 │ 0x55f16c442907e86D764AFdc2a07C2de3BdAc8BB7 │ 0x55f16c442907e86D764AFdc2a07C2de3BdAc8BB7 │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ receiveLibrary │ 0x0000000000000000000000000000000000000000 │ 0x188d4bbCeD671A7aA2b5055937F79510A32e9683 │ 0x188d4bbCeD671A7aA2b5055937F79510A32e9683 │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ sendUlnConfig │ ┌──────────────────────┬───┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │
│ │ │ confirmations │ 0 │ │ │ confirmations │ 5 │ │ │ confirmations │ 5 │ │
│ │ ├──────────────────────┼───┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │
│ │ │ requiredDVNs │ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │
│ │ ├──────────────────────┼───┤ │ │ │ │ 0 │ 0x0eE552262f7B562eFcED6DD4A7e2878AB897d405 │ │ │ │ │ │ 0 │ 0x0eE552262f7B562eFcED6DD4A7e2878AB897d405 │ │ │
│ │ │ optionalDVNs │ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │
│ │ ├──────────────────────┼───┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │
│ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │
│ │ └──────────────────────┴───┘ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │
│ │ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │
│ │ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ sendExecutorConfig │ ┌────────────────┬────────────────────────────────────────────┐ │ ┌────────────────┬────────────────────────────────────────────┐ │ ┌────────────────┬────────────────────────────────────────────┐ │
│ │ │ executor │ 0x0000000000000000000000000000000000000000 │ │ │ executor │ 0x31894b190a8bAbd9A067Ce59fde0BfCFD2B18470 │ │ │ executor │ 0x31894b190a8bAbd9A067Ce59fde0BfCFD2B18470 │ │
│ │ ├────────────────┼────────────────────────────────────────────┤ │ ├────────────────┼────────────────────────────────────────────┤ │ ├────────────────┼────────────────────────────────────────────┤ │
│ │ │ maxMessageSize │ 0 │ │ │ maxMessageSize │ 10000 │ │ │ maxMessageSize │ 10000 │ │
│ │ └────────────────┴────────────────────────────────────────────┘ │ └────────────────┴────────────────────────────────────────────────────┘ │ └────────────────┴────────────────────────────────────────────────────┘ │
├────────────────────┼─────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ receiveUlnConfig │ ┌──────────────────────┬───┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │
│ │ │ confirmations │ 0 │ │ │ confirmations │ 2 │ │ │ confirmations │ 2 │ │
│ │ ├──────────────────────┼───┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │
│ │ │ requiredDVNs │ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │
│ │ ├──────────────────────┼───┤ │ │ │ │ 0 │ 0x0eE552262f7B562eFcED6DD4A7e2878AB897d405 │ │ │ │ │ 0 │ 0x0eE552262f7B562eFcED6DD4A7e2878AB897d405 │ │ │
│ │ │ optionalDVNs │ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │
│ │ ├──────────────────────┼───┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │
│ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │
│ │ └──────────────────────┴───┘ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │
│ │ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │
│ │ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │
└────────────────────┴─────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘

Specifying Pathway Configurations

For more specific configurations on a per pathway basis, review the Configuring Pathways page.