Skip to main content
Version: Endpoint V2

DVN and Executor Configuration

This guide explains how to configure Decentralized Verifier Networks (DVNs), Executors, and message libraries for your Sui OApp or OFT using the SDK.

Overview

Configuration is done through the OApp SDK instance. All examples use sdk.getOApp(packageId) to get the OApp instance, then call SDK methods for configuration.

Configuration flow:

  1. Set message libraries (optional)
  2. Configure DVNs for send/receive (optional but recommended)
  3. Set enforced options (optional)
  4. Set peer addresses (required - opens pathway, call last!)

SDK Setup

import {SDK} from '@layerzerolabs/lz-sui-sdk-v2';
import {Stage} from '@layerzerolabs/lz-definitions';

const sdk = new SDK({client, stage: Stage.MAINNET});
const oapp = sdk.getOApp(yourPackageId); // Always use SDK factory

Configuration Methods

Set Peer

// Configure peer for destination chain
await oapp.setPeerMoveCall(tx, dstEid, peerBytes32);

Address format: Use package ID for Sui peers, 32-byte address for other chains.

Set Message Libraries

// Set custom send library
await oapp.setSendLibraryMoveCall(tx, dstEid, libraryAddress);

// Set custom receive library
await oapp.setReceiveLibraryMoveCall(tx, srcEid, libraryAddress, gracePeriod);

Default: Uses Endpoint defaults if not configured.

DVN Configuration

Configure Receive DVN (Inbound)

import {
SDK,
OAppUlnConfigBcs,
PACKAGE_ULN_302_ADDRESS,
OBJECT_ULN_302_ADDRESS,
PACKAGE_DVN_LAYERZERO_ADDRESS,
} from '@layerzerolabs/lz-sui-sdk-v2';
import {Stage} from '@layerzerolabs/lz-definitions';

const sdk = new SDK({client, stage: Stage.MAINNET});
const oapp = sdk.getOApp(yourPackageId);

// Encode configuration
const config = OAppUlnConfigBcs.serialize({
use_default_confirmations: false,
use_default_required_dvns: false,
use_default_optional_dvns: true,
uln_config: {
confirmations: 15,
required_dvns: [PACKAGE_DVN_LAYERZERO_ADDRESS[Stage.MAINNET]],
optional_dvns: [],
optional_dvn_threshold: 0,
},
}).toBytes();

// Two-step Call pattern
const tx = new Transaction();
const configCall = await oapp.setConfigMoveCall(
tx,
PACKAGE_ULN_302_ADDRESS[Stage.MAINNET],
30184, // Remote EID
3, // CONFIG_TYPE_RECEIVE_ULN
config,
);

tx.moveCall({
target: `${PACKAGE_ULN_302_ADDRESS[Stage.MAINNET]}::uln_302::set_config`,
arguments: [tx.object(OBJECT_ULN_302_ADDRESS[Stage.MAINNET]), configCall],
});

await client.signAndExecuteTransaction({transaction: tx, signer: keypair});

Configure Send DVN (Outbound)

// Same pattern, use CONFIG_TYPE_SEND_ULN = 2
const configCall = await oapp.setConfigMoveCall(
tx,
PACKAGE_ULN_302_ADDRESS[Stage.MAINNET],
30184,
2, // CONFIG_TYPE_SEND_ULN
config,
);

Config types: 1 = Executor, 2 = Send ULN, 3 = Receive ULN

DVN addresses: Use PACKAGE_DVN_LAYERZERO_ADDRESS[Stage.MAINNET] or see Deployed Contracts.

Set Enforced Options

import {Options} from '@layerzerolabs/lz-v2-utilities';

const options = Options.newOptions()
.addExecutorLzReceiveOption(60000, 0) // Gas for destination
.toBytes();

await oapp.setEnforcedOptionsMoveCall(tx, dstEid, msgType, options);

Gas Limit Recommendations

Based on gas profiling:

OApp/OFT Operations

OperationGas Used (MIST)Recommended BudgetNotes
lz_receive2,000-4,1723,500-5,000For OApps and custom business logic, this needs independent profiling
oft_send4,728,6206,700,000Includes endpoint + ULN
dvn_verify5,684,1087,700,000Verification submission
dvn_commit517,2482,500,000Commit verification

Enforced Options Examples

For EVM destinations:

import {Options} from '@layerzerolabs/lz-v2-utilities';

// Standard OApp message
const options = Options.newOptions()
.addExecutorLzReceiveOption(60000, 0) // 60k gas, no msg.value
.toBytes();

// OFT with compose
const optionsCompose = Options.newOptions()
.addExecutorLzReceiveOption(200000, 0) // Higher for compose
.toBytes();

For Sui destinations:

const optionsForSui = Options.newOptions()
.addExecutorLzReceiveOption(5000, 0) // 5k gas units, no msg.value
.toBytes();

Note: Based on gas profiling, Sui lz_receive uses 2,000-5,000 gas units. No msg.value needed - Sui handles storage internally.

Common Issues

Errors:

  • InvalidBCSBytes → Use OAppUlnConfigBcs.serialize() for DVN config
  • oapp_registry::get_messaging_channel abort code: 1 → Used object ID instead of package ID as peer
  • Channel not initialized → Registration creates MessagingChannel automatically (no manual init needed)

Next Steps