Cross-Chain Transfers & Accounting

Configuring a Bridge

Adapters and composers are the operational plumbing that make omnichain transfers and accounting work.

  • Adapters (e.g., LzAdapter) handle message transmission across chains.

  • Composers (e.g., MoreVaultsComposer) handle local user deposits and refunds.

Curators verify their configuration before accepting deposits.

Verify Trusted OFTs

Each OFT of available assets including shares of another vault that you wish to bridge to another chain must be trusted by the local adapter.

LzAdapter.isTrustedOFT(oftAddress)

If false, contact protocol ops to whitelist. Only the core team can administer the list of verified OFTs.

LzAdapter.setTrustedOFTs(address[] ofts, bool[] trusted)

Verify Composer Linkage

Ensure each vault has an assigned composer:

VaultsFactory.getVaultComposer(vaultAddress)

Confirm LayerZero Parameters

LzAdapter.setGasLimit(uint256 newLimit);
LzAdapter.setSlippage(uint256 newSlippageBps);

Use conservative values early on. Slippage should reflect your strategy’s tolerance.

Executing Cross‑Chain Transfers

Curators initiate these transfers to rebalance liquidity or fulfill cross‑chain allocations.

Quote the Fee

uint256 fee = LzAdapter.quoteBridgeFee(
    abi.encode(
        address oftToken,
        uint32 dstEid,
        uint256 amount,
        address dstVault
    )
);

This determines the native fee required for the LayerZero message.

Before transferring assets between chains, curators should pause the vault in order to pause deposits and withdrawals so that the NAV is not affected throughout the transfer.

Execute the Transfer

BridgeFacet.executeBridging(
    address adapter,
    address token,
    uint256 amount,
    bytes bridgeSpecificParams
) payable
  • adapter: address of the LzAdapter.

  • token: asset to transfer.

  • amount: amount in asset units.

  • bridgeSpecificParams: the same encoded blob from fee quoting.

bytes bridgeSpecificParams = 
    abi.encode(
        address oftTokenAddress,
        uint32 lzEid,
        uint256 amount,
        address dstVaultAddress,
        address refundAddress
    );
  • msg.value: must equal or exceed the quoted fee.

Behind the scenes:

  • The adapter packages and sends an OFT message.

  • The destination chain receives the message, performs checks and finalizes the token transfer.

  • If the transfer fails, the composer triggers a refund to refundAddress.

Confirm Execution

Monitor BridgeExecuted (source) event. When successful, the destination vault’s balance and accounting increase.

After all cross-chain transfers are complete, the curator should then unpause the vault.

Running Cross‑Chain Accounting and NAV Updates

Cross‑chain accounting keeps the hub’s NAV accurate. Deposits and withdrawals triggers a read cycle. Spokes calculate their total assets and report back to the hub.

Quote Accounting Fee

uint256 navFee = BridgeFacet.quoteAccountingFee(extraOptions);

extraOptions = executor settings (gas, refund address).

Initiate the Request

bytes32 guid = BridgeFacet.initVaultActionRequest(
    MoreVaultsLib.ActionType.ACCOUNTING,
    abi.encode(hubVault),
    extraOptions
);

The call broadcasts a read request to all connected spokes.

Wait for Responses

Each spoke sends its USD‑valued totalAssets back via LayerZero read channel. The hub aggregates these responses into one composite view.

Finalize and Update NAV

BridgeFacet.finalizeRequest(guid);

For each deposit or withdrawal, this consolidates all values and emits AccountingInfoUpdated. The hub’s VaultFacet.totalAssetsUsd() now reflects the unified NAV for a particular user action. The user can then finalize the deposit or withdrawal request to complete the action.

Verify

BridgeFacet.getRequestInfo(guid);

This function returns info about if a deposit request was fulfilled and with which values such as totalNAV. Check for readSuccess = true to confirm a complete accounting cycle.

Operational Controls and Maintenance

Curators maintain vault stability by controlling adapter parameters, gas costs, and slippage, and by pausing operations if conditions degrade.

Pause/Resume per Chain

VaultFacet.pause();
VaultFacet.unpause();

When a cross-chain transfer is initiated, the vault will be automatically paused and deposits will be paused. This ensures that share price manipulation cannot occur due to misreported NAV during the transfer. The curator must unpause the vault when the cross-chain transfer finalizes in order to reopen deposits.

Adjust Execution Settings

LzAdapter.setGasLimit(uint256 newLimit);
LzAdapter.setSlippage(uint256 newSlippageBps);

Tune gas based on current LayerZero relayer costs. Update slippage if your strategy changes risk tolerance.

Inspect Mesh Health

VaultsFactory.hubToSpokes(hubEid, hubVault);
LzAdapter.getTrustedOFTs();

Ensure every spoke is connected and each OFT remains trusted.

Last updated