Skip to main content
Version: Endpoint V2 Docs

Deployment Guide - OFT on Hyperliquid with LayerZero Composer

This guide provides a step-by-step process for deploying your Omnichain Fungible Token (OFT) on Hyperliquid (both HyperEVM and HyperCore) using the LayerZero Hyperliquid Composer and SDK.

Prerequisites

  • Understanding Core Concepts: Ensure you've reviewed Hyperliquid - Core Concepts.
  • Software:
    • Node.js, pnpm/npm/yarn.
    • @layerzerolabs/hyperliquid-composer SDK installed (npx @layerzerolabs/hyperliquid-composer -h to check).
    • Hardhat or Forge for contract deployment and scripting (examples use Hardhat and Forge).
  • Accounts & Funding:
    • An EVM-compatible wallet with a private key for deployments.
    • Crucially: Your deployer address must be activated on HyperCore. This typically means it needs to have received at least $1 in USDC or HYPE on HyperCore. This is required for operations like block switching or deploying Core Spot assets, as these involve L1 actions. If not funded, you might see errors like L1 error: User or API Wallet <public key> does not exist.
  • LayerZero Configuration: A layerzero.config.ts file for your OApp.

Hyperliquid Composer Deployment Checklist

This checklist is a kind of cheat sheet and "table of contents" for anyone deploying to HyperEVM and HyperCore. The full guide is below and the checklist is just a quick reference, with links to sections in the full guide.

Step 0: Deploy your OFT

ActionPerformed byActionable withRecommended for
Path 1OFT DeployerLZ_ENABLE_EXPERIMENTAL_HYPERLIQUID_EXAMPLE=1 npx create-lz-oapp@latestHyperCore deployments
Path 2OFT DeployerVanilla OFT repo + npx @layerzerolabs/hyperliquid-composerOnly HyperEVM deployments
  • Activate your deployer account on HyperCore without burning a nonce on HyperEVM. Get someone to send at least $1 in USDC or HYPE to your deployer account on HyperCore, or get funds on a burner wallet on HyperEVM, transfer it across, and then transfer it to the deployer account.

Path 1 - With a new repo

  • Create a new Hyperliquid example repo
LZ_ENABLE_EXPERIMENTAL_HYPERLIQUID_EXAMPLE=1 npx create-lz-oapp@latest
  • This comes with the composer and composer deploy script.
  • Deploy scripts perform block switching operations.
  • Composer can be deployed after the core spot is deployed (Step 4). It will not work until the two are linked.
  • Composer has default error handling mentioned in Modifying OFT/Composer Behavior & Error Handling.

Path 2 - Existing repo with OFT

Block switching is not present in the default OFT deploy script.

  • Switch to big block before deploying the OFT
npx @layerzerolabs/hyperliquid-composer set-block \
--size big \
--network <testnet/mainnet> \
--log-level verbose \
--private-key $PRIVATE_KEY
  • Deploy the OFT
  • Switch to small block after deploying the OFT
npx @layerzerolabs/hyperliquid-composer set-block \
--size small \
--network <testnet/mainnet> \
--log-level verbose \
--private-key $PRIVATE_KEY
info

If you are only doing HyperEVM deployment, you are done. The rest of the steps are only for HyperCore deployments.

Step 1 (Optional): Purchase your HyperCore Spot

ActionPerformed byActionable withRequired for
Purchase SpotCoreSpot Deployerhttps://app.hyperliquid.xyz/deploySpotHyperCore
Blocked byNoneNoneStep 2

Step 2: Deploy the Core Spot

ActionPerformed byActionable withRequired for
Deploy CoreSpotCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byOFT DeployerStep 0Step 3
Blocked byCoreSpot DeployerStep 1Step 3

Step 2.1: Create a HyperCore deployment file

ActionPerformed byActionable withRequired for
Create HyperCore Deployment FileCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byOFT DeployerStep 0Step 3
Blocked byCoreSpot DeployerStep 1Step 2.2

Step 2.2: Set the user genesis

ActionPerformed byActionable withRequired for
Set User GenesisCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 2.1Step 2.4
  • Follow the instructions in Step 2.2: Set User Genesis
  • HyperCore balances are u64 - the max balance is 2^64 - 1 = 18446744073709551615
  • Make sure the total balances in the json does not exceed this value.
  • Re-runnable until the next step is executed.
  • UserGenesis transactions stack : If you set the balance of address X to 18446744073709551615 and then set the balance of address Y to 18446744073709551615 after removing X from the json, the net effect is that both X and Y will have 18446744073709551615 tokens.
  • You can either mint the entire amount to the asset bridge address (default) or the deployer address.
  • If you want to read more about the asset bridge address, see Modifying OFT/Composer Behavior & Error Handling

Step 2.3: Confirm the user genesis

ActionPerformed byActionable withRequired for
Confirm User GenesisCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 2.2Step 2.5

Step 2.4: Register the spot

ActionPerformed byActionable withRequired for
Register SpotCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 2.3Step 3
  • Follow the instructions in Step 2.4: Register the Spot
  • Only USDC is supported on HyperCore at the moment - the SDK defaults to USDC.
  • Make sure the asset bridge address on HyperCore has all the tokens minted in Step 2.2. Partial funding is not supported.

Step 2.5: Register Hyperliquidity

ActionPerformed byActionable withRequired for
Register HyperliquidityCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byOFT DeployerStep 0Step 6
Blocked byCoreSpot DeployerStep 2.1None
  • Follow the instructions in Step 2.5: Register Hyperliquidity
  • nOrders MUST be set to 0 as we are not engaging with hyperliquidity
  • The other values are token owner choice (is usually non 0)
  • Step MUST be run even though we set noHyperliquidity=true in genesis
  • This can be run even after deployment and linking

Step 2.6: Set deployer fee share

ActionPerformed byActionable withRequired for
Set Deployer Fee ShareCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byOFT DeployerStep 0Step 6
Blocked byCoreSpot DeployerStep 2.1None
  • Follow the instructions in Step 2.6: Set Deployer Trading Fee Share
  • Trading fee share is usually 100% (default value) - this allocates the trading fees to the token deployer instead of burning it.
  • Do not lose or burn your deployer address as it collects tokens.
  • Step can be re-run as long as the new fee% is lower than the current one.
  • Even though the default value is 100%, it is recommended that you set it
  • This can be run even after deployment and linking

Step 3: Connect the HyperCoreSpot to HyperEVM OFT

Step 3.1: Create a request to connect the HyperCoreSpot to HyperEVM OFT

ActionPerformed byActionable withRequired for
Create RequestCoreSpot Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 0, Step 2Step 3.2

Step 3.2: Accept the request to connect the HyperCoreSpot to HyperEVM OFT

ActionPerformed byActionable withRequired for
Accept RequestOFT Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 3.1Step 4

Step 4: Deploy the Composer

ActionPerformed byActionable withRequired for
Deploy ComposerOFT Deployernpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 3None
  • Follow the instructions in Step 4: Deploy the HyperLiquidComposer Contract
  • Deployer script in the OFT repo will deploy the composer - it also handles block switching.
  • Make sure the Composer's address is activated on HyperCore (sending it at least $1 worth of HYPE or USDC).
  • Composer is re-deployable and independent of the OFT and does not need to be linked with anything.

Step 5: Listing on spot order books

ActionPerformed byActionable withRequired for
Spot Book ListingAutomaticnpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 2none

This is automatically completed when all steps in Step 2 are completed.

Step 6: Listing on perp order books

ActionPerformed byActionable withRequired for
Perp Book ListingAutomaticnpx @layerzerolabs/hyperliquid-composerHyperCore
Blocked byCoreSpot DeployerStep 2none

This is controlled by the Hyperliquid community (source):

Hyperliquid currently supports trading of 100+ assets. Assets are added according to community input.

Full Hyperliquid OFT Deployment Guide

Step 0: Deploy Your OFT on HyperEVM

You have two main paths depending on your project setup: starting fresh or using an existing OFT project.

Path 1: New Project using LayerZero Hyperliquid Example

This path is recommended if you are starting fresh and intend to deploy to HyperCore.

  1. Create a new Hyperliquid example repository:
    LZ_ENABLE_EXPERIMENTAL_HYPERLIQUID_EXAMPLE=1 npx create-lz-oapp@latest
    • This template includes the HyperLiquidComposer contract and its deployment script.
    • The deploy scripts automatically handle HyperEVM block switching (to "big blocks" for deployment and back to "small blocks" after deployment is complete).
  2. Activate Deployer Account on HyperCore: Ensure your OFT deployer address has a balance (e.g., $1 USDC or HYPE) on HyperCore before deploying. This is needed for the deploy script to perform L1 actions like block switching.
  3. Deploy your OFT and (optionally) the Composer: The example repository will have hardhat-deploy scripts.
    npx hardhat lz:deploy --tags MyHyperLiquidOFT # Or your OFT's tag
    # The Composer can be deployed later (Step 4), after the Core Spot is set up.
    # npx hardhat lz:deploy --tags MyHyperLiquidComposer
    • The Composer comes with default error handling mechanisms (detailed in the "Modifying OFT/Composer Behavior" section below).

Path 2: Existing OFT Project

If you have an existing OFT project and want to add Hyperliquid support:

  1. Activate Deployer Account on HyperCore: As above, ensure your deployer address is funded on HyperCore for L1 actions.
  2. Manually Switch to Big Blocks on HyperEVM: Contract deployments on HyperEVM typically require "big blocks" due to gas limits.
    npx @layerzerolabs/hyperliquid-composer set-block \
    --size big \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY \
    [--log-level verbose]
    Replace {testnet | mainnet} and $PRIVATE_KEY accordingly.
  3. Deploy your OFT: Use your existing deployment scripts (e.g., npx hardhat deploy --network hyperliquid_testnet --tags YourOFTTag).
  4. Manually Switch back to Small Blocks on HyperEVM:
    npx @layerzerolabs/hyperliquid-composer set-block \
    --size small \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY \
    [--log-level verbose]

Post-Deployment (Both Paths):

  • Wire your OFTs: Connect your newly deployed OFT on Hyperliquid with its counterparts on other chains.
    npx hardhat lz:oapp:wire --oapp-config path/to/your/layerzero.config.ts
  • Test Basic OFT Transfers: Verify that standard OFT sends (without composition) work to and from Hyperliquid (HyperEVM).

⚠️ If you are only deploying to HyperEVM (i.e., your token will only exist as an ERC20 on HyperEVM and not be bridged to HyperCore), you are done with deployment steps related to Hyperliquid specifics beyond standard OFT deployment. The following steps are for HyperCore integration.

Step 1: (Optional) Purchase Your HyperCore Spot Index

This step is required if you want your token to exist natively on HyperCore (as a HIP-1 token) and be bridgeable with your HyperEVM OFT.

Step 2: Deploy the Core Spot (HIP-1 Token)

This process registers your token natively on HyperCore. Tool: @layerzerolabs/hyperliquid-composer SDK.

General Notes for CoreSpot Deployment:

REMINDER: HYPERLIQUIDITY IS NOT SUPPORTED BY LAYERZERO

When deploying a Core Spot, avoid using the "Hyperliquidity" feature often defaulted by the Hyperliquid UI. It is incompatible with the LayerZero asset bridge mechanism as it can lead to uncollateralized states. The SDK commands help you deploy without Hyperliquidity.

You can monitor the deployment progress using the Hyperliquid UI or by querying the API:

curl -X POST "https://api.hyperliquid.xyz/info" \
-H "Content-Type: application/json" \
-d '{
"type": "spotDeployState",
"user": "<YOUR_DEPLOYER_ADDRESS>"
}'

This will return a json object with the current state of the spot deployment.

Step 2.1: Create a HyperCore Deployment File (core-spot create)

This will create a new file under ./deployments/hypercore-{testnet | mainnet} with the name of the Core Spot token index. This is not a Hyperliquid step but rather something to make the deployment process easier.

This file stores configuration for your Core Spot token and is used by subsequent SDK commands. It is crucial to the functioning of the token deployment after which it really is not needed.

  • Action: Create HyperCore Deployment File.
  • Command:
    npx @layerzerolabs/hyperliquid-composer core-spot \
    --action create \
    [--oapp-config <layerzero.config.ts> \
    --token-index <coreIndex> \
    --network {testnet | mainnet} \
    [--log-level { info | verbose }]
    • <coreIndex>: The index you obtained in Step 1 (or intend to use if the auction allows direct index specification).
    • If --oapp-config is provided and your OFT is defined, it can pre-fill some details. Otherwise, the SDK might prompt for OFT address and deployment transaction hash later, especially during the linking phase.
  • Output: Creates a JSON file at ./deployments/hypercore-{testnet | mainnet}/<coreIndex>.json.

Step 2.2: Set User Genesis (userGenesis)

Define the initial supply and distribution of your HIP-1 token on HyperCore.

  • Action: Set the genesis balances for the deployer and the users.
  • Preparation:
    1. Edit the JSON file created in Step 2.1 (./deployments/hypercore-{testnet | mainnet}/<coreIndex>.json).
    2. Populate the userAndWei or existingTokenAndWei sections. The file should initially contain entries for the deployer and the asset bridge address (e.g., 0x2000...<coreIndexInHex>), typically with 0 wei.
    3. Crucially for the asset bridge: To enable bridging the entire supply, mint the total supply (e.g., 18446744073709551615 for u64.max) to the asset bridge address corresponding to your token. You can find how to compute this address using npx @layerzerolabs/hyperliquid-composer to-bridge --token-index <coreIndex>. Example snippet for the JSON:
      "userAndWei": [
      {
      "user": "0xAssetBridgeAddressForYourToken", // Replace with actual bridge address
      "wei": "18446744073709551615" // Max u64 or your total supply
      }
      ],
      "existingTokenAndWei": [], // Ensure this is empty if not used
      "blacklistUsers": []
    4. If not using existingTokenAndWei or userAndWei for other users, ensure their arrays are empty ([]) to avoid errors like Error deploying spot: missing token max_supply.
      // Change this:
      "existingTokenAndWei": [
      {
      "token": 0,
      "wei": ""
      }
      ]
      // To this:
      "existingTokenAndWei": []
  • Command:
    npx @layerzerolabs/hyperliquid-composer user-genesis \
    --token-index <coreIndex> \
    [--action {* | userAndWei | existingTokenAndWei | blacklistUsers}] \ # Default is * (all)
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \
    [--log-level { info | verbose }]
  • Details:
    • HyperCore HIP-1 tokens use u64 for balances (max: 18,446,744,073,709,551,615). Ensure total balances don't exceed this.
    • This step is re-runnable until Step 2.3 (Confirm User Genesis) is executed. There is no limit to the number of times you can re-run this command.
    • For in-depth understanding of why full funding of the asset bridge is critical, refer to The Asset Bridge Mechanics in Core Concepts.

Step 2.3: Confirm User Genesis (setGenesis)

This step finalizes the genesis balances set in Step 2.2, making them immutable on HyperCore.

Warning: This action is irreversible.
  • Action: Confirm User Genesis.
  • Command:
    npx @layerzerolabs/hyperliquid-composer set-genesis \
    --token-index <coreIndex> \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \
    [--log-level {info | verbose }]

Step 2.4: Register the Spot (registerSpot)

This registers your Core Spot token on HyperCore and typically creates a trading pair against USDC, which is the only supported quote token as of now.

  • Action: Register Spot.
  • Command:
    npx @layerzerolabs/hyperliquid-composer register-spot \
    --token-index <CoreIndex> \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \
    [--log-level { info | verbose }]
  • Details:
    • Currently, USDC is the primary quote token on HyperCore; the SDK defaults to this.
    • Ensure the asset bridge address on HyperCore holds the full token supply intended for bridging (as minted in Step 2.2). Partial funding of the bridge is not supported and can lead to permanently locked tokens.
  • Verification: You can check your deployed Core Spot token details:
    curl -X POST "https://api.hyperliquid-testnet.xyz/info" \ # or mainnet URL
    -H "Content-Type: application/json" \
    -d '{"type": "tokenDetails", "tokenId": "<YOUR_TOKEN_ID>"}'
    • <YOUR_TOKEN_ID> is the on-chain identifier for your HIP-1 token (can be found via explorers or API responses).

Step 2.5: Register Hyperliquidity (createSpotDeployment)

This step creates a spot deployment without hyperliquidity, which is required for LayerZero integration.

  • Action: Create Spot Deployment.

  • Command:

    npx @layerzerolabs/hyperliquid-composer create-spot-deployment \
    --token-index <coreIndex> \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \
    [--log-level {info | verbose}]
  • Prompts: You will be prompted for the following values:

    • startPx: The starting price for the token.
    • orderSz: The size of each order (as a float, not wei).
    • nSeededLevels: The number of levels the deployer wishes to seed with USDC instead of tokens.
    info

    You will NOT be prompted for nOrders as it is automatically set to 0 because LayerZero does not support Hyperliquidity. See Hyperliquid Python SDK example for reference.

  • Details:

    • There are tight range bounds on the input values that can be viewed at Hyperliquid's frontend checks.
    • This step can be executed after the Core Spot is fully deployed and even after linking with the EVM contract.
    • After completing this step, spot-deploy-state queries will fail, which is expected behavior.
warning

The SDK does not currently enforce the frontend checks for input validation. Ensure your values comply with Hyperliquid's requirements to avoid deployment issues.

Step 2.6: Set Deployer Trading Fee Share (setDeployerTradingFeeShare)

Configure the trading fee share for the deployer of the Core Spot token.

  • Action: Set Deployer Fee Share.
  • Command:
    npx @layerzerolabs/hyperliquid-composer trading-fee \
    --token-index <coreIndex> \
    --share <percentage> \ # e.g., "100%" or "0%"
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \
    [--log-level { info | verbose }]
  • Details:
    • A deployer fee share is claimed per transaction on HyperCore
    • Share can be [0%, 100%]. A 100% share allocates the deployer's portion of trading fees to the token deployer. 0% burns it.
    • The deployer address collects these fees; ensure it's secure.
warning

This step can be re-run to lower the fee share but NOT to increase it. It can also be run after the Core Spot is fully deployed, so it might be a good idea to set the fee to 100% and be able to lower it later.

Step 3: Connect the HyperCoreSpot (HIP-1) to HyperEVM OFT (ERC20)

This two-step process establishes the link that allows tokens to be bridged between HyperCore and HyperEVM via the asset bridge precompile.

  • Preparation: If you haven't used --oapp-config in previous steps, the SDK might prompt for your OFT contract address (on HyperEVM) and its deployment transaction hash (to get the nonce). Ensure the CoreSpot deployer has access to the OFT address.

The Core Spot deployer initiates a request on HyperCore to link the HIP-1 token to a specific ERC20 contract on HyperEVM.

  • Action: Create Link Request.
  • Performed by: CoreSpot Deployer.
  • Command:
    npx @layerzerolabs/hyperliquid-composer request-evm-contract \
    [--oapp-config path/to/your/layerzero.config.ts] \
    --token-index <coreIndex> \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \
    [--log-level verbose]
  • Note: This step can be re-issued multiple times (e.g., if the ERC20 address was initially incorrect) until finalizeEvmContract (Step 3.2) is completed.

The OFT (ERC20) deployer on HyperEVM confirms and finalizes the link.

  • Action: Accept/Finalize Link Request.
  • Performed by: OFT Deployer (the EOA that deployed the ERC20 contract on HyperEVM).
  • Command:
    npx @layerzerolabs/hyperliquid-composer finalize-evm-contract \
    [--oapp-config path/to/your/layerzero.config.ts] \
    --token-index <coreIndex> \
    --network {testnet | mainnet} \
    --private-key $PRIVATE_KEY_HYPERLIQUID \ # This should be the private key of the OFT deployer on HyperEVM
    [--log-level verbose]
This step is final and irreversible for the given token pair.

Step 4: Deploy the HyperLiquidComposer Contract

The Composer contract facilitates the actual bridging of tokens from HyperEVM to HyperCore when receiving LayerZero messages.

  • Action: Deploy Composer.
  • Performed by: OFT Deployer.
  • Command (if using the Hyperliquid example repo):
    npx hardhat lz:deploy --tags MyHyperLiquidComposer --network hyperliquid_testnet # or your target network
    • The deployment script in the example repository handles block switching (to "big blocks" and back) automatically. If deploying manually, ensure you are on a "big block".
  • Funding Requirement:
    • Crucial: The deployed HyperLiquidComposer contract address must be activated on HyperCore by sending it at least $1 worth of USDC or HYPE on HyperCore. This is because the Composer needs to perform L1WritePrecompile actions on HyperCore to transfer tokens to the final recipient.
  • Notes:
    • The Composer is stateless regarding individual user balances (it doesn't hold tokens long-term).
    • It can be deployed at any point, but it's functionally useful only after the OFT and Core Spot are deployed and linked.
    • It's re-deployable. If re-deployed, ensure any systems pointing to it are updated.

Step 5: Sending Tokens (from other chains to HyperEVM/Core)

After all deployments and linking are complete, you can send tokens from another network through LayerZero to a recipient on Hyperliquid. The Composer will handle the final hop to HyperCore if specified.

  • Forge Script Example (from LayerZero devtools): Ensure your .env is populated with PRIVATE_KEY, RPC_URL_BSC_TESTNET (or your source chain RPC).
    forge script script/SendScript.s.sol \
    --private-key $PRIVATE_KEY \
    --rpc-url $RPC_URL_SOURCE_CHAIN \
    --sig "exec(uint256,uint128,uint128)" \
    <oft-amount-ld> \ # Amount of OFT to send in local decimals
    <composer-gas-for-core> \ # Gas to forward for HyperCore L1 action (e.g., 100000). If > 0, attempts to send to HyperCore.
    <composer-value-for-hype> \ # Value (in HYPE) to send to fund user on HyperCore (e.g., 0).
    --broadcast
    • The SendScript.s.sol (or your custom sending logic) would prepare a SendParam where:
      • SendParam.dstEid points to Hyperliquid.
      • SendParam.to is the OFT address on Hyperliquid.
      • SendParam.composeMsg is abi.encodePacked(actualReceiverAddressOnHyperliquid).
      • SendParam.extraOptions might be used to specify gas for the lzCompose call and the subsequent L1 action.

Modifying OFT/Composer Behavior & Error Handling

The HyperLiquidComposer contract has built-in checks and error handling because Hyperliquid's native bridge mechanics do not prevent certain fund-locking scenarios.

  • Transfer Exceeding u64.max on HyperCore: HyperCore's spotSend (L1 action) supports a max of u64 tokens. If an EVM amount translates to more than u64.max HIP-1 tokens, the Composer will bridge u64.max equivalent and refund the excess (dust) to the receiver on HyperEVM.
  • Transfer Exceeding HyperCore Asset Bridge Capacity: If the HyperCore side of the asset bridge doesn't have enough tokens to fulfill the requested bridge amount (e.g., X tokens requested, but only Y < X available on Core bridge), the Composer will:
    1. Bridge the maximum possible amount (Y tokens).
    2. Convert the unbridged EVM portion back to EVM tokens.
    3. Refund this "dust" amount to the receiver on HyperEVM.
  • Malformed composeMsg - Unable to decode receiver address: If SendParam.composeMsg cannot be decoded into a valid HyperEVM-style address, the Composer cannot determine the final recipient on HyperCore.
    • EVM Sender: If the original LayerZero transaction msg.sender (on the source chain) was an EVM address, the Composer attempts to refund the tokens to this msg.sender on HyperEVM.
    • Non-EVM Sender (e.g., Solana, Aptos):

      ⚠️ This is a potential token lock scenario. If the composeMsg is malformed AND the original msg.sender is from a non-EVM chain, the Composer cannot easily refund to a compatible HyperEVM address. The tokens may become locked in the Composer contract. Ideally, a cross-chain refund mechanism would be used, but this adds complexity and gas costs.

You can customize the HyperLiquidComposer.sol contract if you need different error-handling behaviors, but be extremely cautious due to the risks involved with the Hyperliquid asset bridge.