> ## Documentation Index
> Fetch the complete documentation index at: https://docs.melt.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Guide

> How to integrate with Melt Protocol — bridge in, bridge out, wrap, unwrap

## Overview

Melt is a cross-chain token bridge built on LayerZero V2. It enables:

1. **Bridge In** — Lock ERC-20 tokens on a source chain, receive wrapped tokens on HyperEVM.
2. **Bridge In to HyperCore** — Same as above, but tokens land directly in your HyperCore spot balance for immediate trading.
3. **Bridge Out** — Burn wrapped tokens on HyperEVM, receive original tokens on the source chain.
4. **Wrap / Unwrap** — Convert between native HyperEVM tokens and their Melt-wrapped equivalents (same-chain only).

```
Source Chain                         HyperEVM
┌──────────────┐    LayerZero V2    ┌──────────────┐
│  MeltBridge  │ ────────────────►  │   MeltHub    │
│  (lock/release) │ ◄──────────────── │  (mint/burn) │
└──────────────┘                    └──────┬───────┘
                                          │
                                          │ toCore = true
                                          ▼
                                   ┌──────────────┐
                                   │  HyperCore   │
                                   │ (spot balance)│
                                   └──────────────┘
```

See [Deployment Addresses](/developers/deployment-addresses) for all contract addresses.

***

## Core Concepts

### Config Key

Every token is identified by a `configKey` — a hash of the original token address and its source chain:

```solidity theme={null}
configKey = keccak256(abi.encodePacked(originalToken, sourceEid))
```

* `sourceEid` is the LayerZero Endpoint ID of the source chain (`0` for same-chain HyperEVM tokens).
* Use `MeltHub.getConfigKey(originalToken, sourceEid)` to compute it on-chain.

### LayerZero Endpoint IDs

| Chain    | EID     |
| -------- | ------- |
| Ethereum | `30101` |
| HyperEVM | `30367` |

### Recipient Encoding

Bridge functions accept recipients as `bytes32`. To convert an address:

```solidity theme={null}
bytes32 recipient = bytes32(uint256(uint160(recipientAddress)));
```

### Fee Directions

Melt fees are **directional**:

* **IN** — applied on `wrap()` and bridge-in (source → HyperEVM). Deducted from the amount received.
* **OUT** — applied on `unwrap()` and `bridgeOut()` (HyperEVM → source). Deducted from the amount sent.

***

## Flows

### Bridge In (Source → HyperEVM)

Bridge tokens from a source chain to receive wrapped tokens on HyperEVM.

<Steps>
  <Step title="Approve">
    Approve the `MeltBridge` contract to spend your tokens.
  </Step>

  <Step title="Quote LayerZero fee">
    ```solidity theme={null}
    MessagingFee memory fee = meltBridge.quoteBridge(token, amount, recipient, false);
    ```
  </Step>

  <Step title="Bridge">
    ```solidity theme={null}
    MessagingReceipt memory receipt = meltBridge.bridge{value: fee.nativeFee}(
        token,
        amount,
        recipient, // bytes32-encoded destination address on HyperEVM
        false      // toCore = false
    );
    ```
  </Step>

  <Step title="Wait for delivery">
    LayerZero delivery takes \~1–5 minutes. Track using the `guid` from the receipt.
  </Step>

  <Step title="Receive">
    Wrapped tokens arrive on HyperEVM. Amount received = `amount - fee` (IN direction fee).
  </Step>
</Steps>

**Events to monitor:**

| Chain    | Event                                                      | Meaning               |
| -------- | ---------------------------------------------------------- | --------------------- |
| Source   | `BridgeInitiated(guid, sender, token, amount, recipient)`  | Bridge tx submitted   |
| HyperEVM | `BridgedIn(guid, recipient, wrappedToken, amount, srcEid)` | Wrapped tokens minted |

***

### Bridge In to HyperCore

Bridge tokens directly into your HyperCore spot balance for immediate trading.

<Warning>
  Your recipient address **must be activated on HyperCore**. The transaction reverts with `CoreUserNotActivated` otherwise. The token must also have HyperCore configured (`coreLinked = true`).
</Warning>

<Steps>
  <Step title="Approve">
    Approve the `MeltBridge` contract to spend your tokens.
  </Step>

  <Step title="Quote LayerZero fee (2x gas for toCore)">
    ```solidity theme={null}
    MessagingFee memory fee = meltBridge.quoteBridge(token, amount, recipient, true);
    ```
  </Step>

  <Step title="Bridge with toCore = true">
    ```solidity theme={null}
    MessagingReceipt memory receipt = meltBridge.bridge{value: fee.nativeFee}(
        token,
        amount,
        recipient, // bytes32-encoded HyperEVM address (must be activated on Core)
        true       // toCore = true
    );
    ```
  </Step>

  <Step title="Receive on HyperCore">
    Tokens land in your HyperCore spot balance. The amount is converted from EVM decimals to Core decimals using the token's `decimalDiff`.
  </Step>
</Steps>

**Events to monitor:**

| Chain    | Event                                                                 | Meaning                       |
| -------- | --------------------------------------------------------------------- | ----------------------------- |
| Source   | `BridgeInitiated(guid, sender, token, amount, recipient)`             | Bridge tx submitted           |
| HyperEVM | `BridgedToCore(guid, recipient, wrappedToken, evmAmount, coreAmount)` | Tokens delivered to HyperCore |

***

### Bridge Out (HyperEVM → Source)

Burn wrapped tokens on HyperEVM to receive original tokens on the source chain.

<Steps>
  <Step title="Approve">
    Approve `MeltHub` to spend your wrapped tokens.
  </Step>

  <Step title="Quote LayerZero fee">
    ```solidity theme={null}
    MessagingFee memory fee = meltHub.quoteBridgeOut(wrappedToken, amount, recipient);
    ```
  </Step>

  <Step title="Bridge out">
    ```solidity theme={null}
    MessagingReceipt memory receipt = meltHub.bridgeOut{value: fee.nativeFee}(
        wrappedToken,
        amount,
        recipient // bytes32-encoded destination address on source chain
    );
    ```
  </Step>

  <Step title="Receive on source chain">
    Original tokens are released from the bridge. Amount received = `amount - fee` (OUT direction fee).
  </Step>
</Steps>

**Events to monitor:**

| Chain    | Event                                                               | Meaning                  |
| -------- | ------------------------------------------------------------------- | ------------------------ |
| HyperEVM | `BridgedOut(guid, sender, wrappedToken, amount, dstEid, recipient)` | Burn + LZ message sent   |
| Source   | `BridgeCompleted(recipient, token, amount)`                         | Original tokens released |

***

### Wrap / Unwrap (Same-Chain)

For tokens native to HyperEVM that have a Melt-wrapped version (identified by `sourceEid = 0`).

**Wrap (original → wrapped):**

1. Approve `MeltHub` to spend the original token.
2. Call:
   ```solidity theme={null}
   uint256 amountOut = meltHub.wrap(configKey, amount);
   ```
3. Receive `amountOut` = `amount - fee` (IN direction).

**Unwrap (wrapped → original):**

1. Approve `MeltHub` to spend the wrapped token.
2. Call:
   ```solidity theme={null}
   uint256 amountOut = meltHub.unwrap(configKey, amount);
   ```
3. Receive `amountOut` = `amount - fee` (OUT direction).

***

## Errors Reference

| Error                            | Contract   | Cause                                                 |
| -------------------------------- | ---------- | ----------------------------------------------------- |
| `TokenNotSupported`              | MeltBridge | Token is not whitelisted on this bridge               |
| `InsufficientAmount`             | Both       | Amount is zero                                        |
| `InsufficientLiquidity`          | MeltBridge | Bridge doesn't hold enough locked tokens for release  |
| `TokenNotRegistered`             | MeltHub    | Token config key not found                            |
| `TokenPaused`                    | MeltHub    | Token or hub is paused                                |
| `InvalidSourceChain`             | MeltHub    | Source chain mismatch on bridge-out                   |
| `CoreNotConfigured`              | MeltHub    | `toCore=true` but HyperCore not linked for this token |
| `CoreUserNotActivated`           | MeltHub    | Recipient is not activated on HyperCore               |
| `InsufficientCoreBridgeCapacity` | MeltHub    | Asset bridge doesn't have enough capacity             |

***

## Fee Structure

* Fees are charged in **basis points** (1 bps = 0.01%). The current protocol fee is **30 bps (0.30%)** for all tokens.
* Fee calculation: `fee = amount * feeBps / 10_000`.
* Fees are directional — IN and OUT fees may differ.
* Designated Market Makers may have **discounted fee overrides** configured via `MeltFeeController`. If your address has an override, it takes precedence over the token's default fee.
* Fees are collected as wrapped tokens held by `MeltHub`.

### Checking Your Fee

```solidity theme={null}
// Get the token's default fee
(, , , uint256 feeBps, ,) = meltHub.tokenConfigs(configKey);

// If a fee controller is set, your actual fee may differ
IMeltFeeController controller = meltHub.feeController();
if (address(controller) != address(0)) {
    uint256 fee = controller.getFee(configKey, yourAddress, amount, feeBps, isOut);
}
```

***

## Function Signatures

### MeltBridge (Source Chain)

```solidity theme={null}
// Bridge tokens to HyperEVM. Set toCore=true to deliver to HyperCore spot balance.
function bridge(address token, uint256 amount, bytes32 recipient, bool toCore)
    external payable returns (MessagingReceipt memory);

// Quote the LayerZero fee for a bridge transaction.
function quoteBridge(address token, uint256 amount, bytes32 recipient, bool toCore)
    external view returns (MessagingFee memory);

// Check if a token is supported.
function isTokenSupported(address token) external view returns (bool);

// Get the locked balance for a token.
function getLockedBalance(address token) external view returns (uint256);
```

### MeltHub (HyperEVM)

```solidity theme={null}
// Wrap native HyperEVM tokens into Melt-wrapped tokens.
function wrap(bytes32 configKey, uint256 amount) external returns (uint256 amountOut);

// Unwrap Melt-wrapped tokens back to native HyperEVM tokens.
function unwrap(bytes32 configKey, uint256 amount) external returns (uint256 amountOut);

// Bridge wrapped tokens back to the source chain.
function bridgeOut(address wrappedToken, uint256 amount, bytes32 recipient)
    external payable returns (MessagingReceipt memory);

// Quote the LayerZero fee for a bridge-out transaction.
function quoteBridgeOut(address wrappedToken, uint256 amount, bytes32 recipient)
    external view returns (MessagingFee memory);

// Compute the config key for a token.
function getConfigKey(address originalToken, uint32 sourceEid)
    external pure returns (bytes32);

// Get full token config.
function getTokenConfig(bytes32 configKey)
    external view returns (TokenConfig memory);

// Get HyperCore config for a token.
function coreConfigs(bytes32 configKey)
    external view returns (uint64 coreIndexId, int8 decimalDiff, bool isConfigured);

// Get config key from wrapped token address.
function wrappedToConfigKey(address wrappedToken) external view returns (bytes32);

// Get the fee controller (address(0) if none set).
function feeController() external view returns (IMeltFeeController);
```

### LayerZero Types

```solidity theme={null}
struct MessagingFee {
    uint256 nativeFee;  // Gas fee in native token (ETH on Ethereum, HYPE on HyperEVM)
    uint256 lzTokenFee; // Optional fee in LZ token (usually 0)
}

struct MessagingReceipt {
    bytes32 guid;       // Unique message ID — use to track delivery
    uint64 nonce;
    MessagingFee fee;
}
```
