# Bridging from Chiliz Chain to Solana

To bridge an existing token from Chiliz Chain to Solana, you need to write and deploy two separate smart contracts: an OFT Adapter on the chain where the token already exists (Chiliz Chain), and a Native OFT on the destination chain (Solana).

*Note that LayerZero provide their own QuickStart for OFT contracts:*

{% embed url="<https://docs.layerzero.network/v2/developers/evm/oft/quickstart>" %}

## Prerequisites

{% hint style="info" %}
Bridging from Chiliz Chain (EVM) to Solana (Non-EVM) requires dual-stack development.\
You will need environments and wallets set up for both ecosystems.

You will therefore need the following environments:

* For Chiliz Chain interactions: Node/npx and Hardhat.
* For Solana interactions: [Rustup](https://rustup.rs/) (Solana smart contracts use the Rust programming language), [Solana CLI and Anchor framework](https://solana.com/docs/intro/installation), and [LayerZero's Solana SDK](https://docs.layerzero.network/v2/tools/sdks/solana-sdk).
  {% endhint %}

This guide requires the following:

* A token contract address on Chiliz Chain. You do not need to own it.
* A Web3 wallet for each chain (MetaMask does not support non-EVM chains):
  * For Chiliz Chain: MetaMask wallet with [the Chiliz Chain RPC configuration](/develop/basics/connect-to-chiliz-chain/connect-using-rpc.md).
  * For Solana: [Solflare](https://www.solflare.com/) wallet with [Solana Mainnet configuration](https://solana.com/docs/references/clusters). Here is [their set-up guide](https://www.solflare.com/guides/how-to-set-up-your-first-crypto-wallet-with-solflare-step-by-step/).
* Enough gas tokens on each chain to pay for the contract deployments as well as the gas fees for sending messages.
  * On Chiliz Chain: CHZ tokens.
  * On Solana: SOL tokens.

## Step 1: Contract Development

{% hint style="info" %}
**The "Shared Decimals" Challenge**

Because Solana handles token mathematics differently than the Ethereum Virtual Machine (EVM), we must handle decimals correctly:

* Chiliz Chain (EVM): Standard ERC-20 tokens typically have 18 decimals of precision.
* Solana: Native SPL Tokens typically have 9 decimals of precision.

If you send $$ $1 \times 10^{18}$ $$ units from Chiliz to Solana, the Solana contract would misinterpret the amount, resulting in a massive inflation of the token on the destination chain.

To normalize the math, LayerZero uses a `sharedDecimals` configuration. By default, the LayerZero V2 OFT standard sets `sharedDecimals` to 6.

* When a user bridges 1.00 token from Chiliz, the Adapter drops the lowest 12 decimals (treating them as "dust") to scale the number down to 6 decimals.
* The message is sent across the bridge.
* The Solana program receives the 6-decimal number and scales it *up* to its local 9 decimals before minting.

[Learn more here](https://docs.layerzero.network/v2/faq#what-is-shareddecimals-can-i-override-default-shareddecimals-in-an-oft-contract).
{% endhint %}

### Preparing the `OFTAdapter` on Chiliz Chain

{% hint style="warning" %}
This is a preparatory step, do not deploy right away!\
You will deploy in Step 3.
{% endhint %}

The `OFTAdapter` contract acts as a lockbox for your existing token. When users bridge their tokens away from Chiliz Chain, this contract locks the original ERC20 tokens.

{% hint style="info" %}
Because LayerZero's `OFTAdapter` sets `sharedDecimals` to 6 by default, you can use the standard implementation. If you ever need to change this (e.g., to 8), you would override the `sharedDecimals()` function.
{% endhint %}

Create a new file named `ChilizTokenAdapter.sol` in your contracts folder:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import { OFTAdapter } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTAdapter.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

contract ChilizSolanaAdapter is OFTAdapter {
    constructor(
        address _token,      // The address of your EXISTING Token on Chiliz Chain (18 decimals)
        address _lzEndpoint, // The LayerZero V2 Endpoint address on Chiliz
        address _delegate    // The address capable of making configuration changes ( (usually your wallet)
    ) OFTAdapter(_token, _lzEndpoint, _delegate) Ownable(_delegate) {}
}
```

{% hint style="info" %}
As you can see this contract extends the [LayerZero OFT Adapter contract](https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/oapp/contracts/oft/OFTAdapter.sol), as well as a standard `Ownable.sol` contract to give the administrative keys. You need both so that you, and only you, can safely wire the chains together.
{% endhint %}

### Preparing and Deploying the `OFT` on Solana

Unlike Chiliz Chain, Solana does not use the Ethereum Virtual Machine (EVM) or Solidity language. Solana smart contracts (called "Programs") are written in [Rust](https://rust-lang.org/).

To bridge your token, you need to deploy an OFT program on Solana. When this program receives a verified message from your Chiliz-deployed OFTAdapter, it will mint the corresponding SPL token into the user's Solana wallet.

{% embed url="<https://docs.layerzero.network/v2/developers/solana/oft/overview>" %}

LayerZero provides a [ready-to-use Anchor example](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-solana) so you do not have to write the Rust bridge logic from scratch.

#### 1. Clone the LayerZero OFT Solana example:

```bash
git clone https://github.com/LayerZero-Labs/devtools.git
cd devtools/examples/oft-solana
npm install
```

#### 2. Build the Rust program

This will also generate your unique Solana Program ID (equivalent to a contract address in the EVM):

```bash
anchor build
```

After the build completes, Anchor will generate a new keypair in `target/deploy/oft_solana-keypair.json`.\
You can retrieve your new Program ID by running:

```bash
anchor keys list
```

#### 3. Deploy to Solana Mainnet

Make sure that your Solana CLI is configured for Mainnet and your local wallet has enough $SOL for the deployment and storage rent.\
Don't forget to update the `Anchor.toml` file and the `lib.rs` declare\_id! macro with this new Program ID before deploying.

```bash
solana config set --url mainnet-beta
anchor deploy
```

#### 4. Initialize the OFT and the SPL Mint

On Solana, a token's logic and its ledger are separated. You must initialize a new Mint Account (the SPL Token) and assign your newly deployed OFT Program as the Mint Authority. This ensures only the LayerZero bridge can mint new tokens on Solana.

The LayerZero SDK provides Hardhat/TypeScript tasks to handle this initialization directly from the command line. In your `oft-solana` project, configure your LayerZero Endpoint for Solana (`30168`) and run the initialization script:

{% code overflow="wrap" lineNumbers="true" %}

```bash
npx hardhat lz:oft-solana:init --program-id <YOUR_NEW_PROGRAM_ID> --mint-decimals 9 --shared-decimals 6
```

{% endcode %}

{% hint style="info" %}
Crucial Parameters:

* `--mint-decimals 9`: Sets the standard SPL token precision on Solana.
* `--shared-decimals 6`: Must match the shared decimals you configured (or the default) on your Chiliz Chain `OFTAdapter`. This is what guarantees 1 Chiliz token = 1 Solana token.
  {% endhint %}

Once this initialization transaction is confirmed on the Solana blockchain, your native OFT program is fully set up and ready to be wired to the Chiliz OFTAdapter!

## Step 2: LayerZero Configuration

With your Chiliz Adapter deployed and your Solana OFT program initialized, you must now configure their connection. This is where the difference between EVM and non-EVM networks becomes highly visible.

{% hint style="info" %}
Address Formatting:

* Chiliz Chain (EVM): Uses standard 20-byte hexadecimal addresses (e.g., `0x123...`).
* Solana: Uses Base58 encoded addresses (e.g., `YourProgramId111111111111111111111111111111`).
  {% endhint %}

LayerZero’s cross-chain messaging requires all [peer addresses](https://docs.layerzero.network/v2/concepts/glossary#peer) to be formatted as `bytes32`. Fortunately, the LayerZero V2 Hardhat tooling automatically handles the Base58-to-Bytes32 conversion for you, as long as you define the endpoints correctly in your config.

The [Simple Config Generator](https://docs.layerzero.network/v2/tools/simple-config) is the recommended way to generate wiring configuration, as it automates bidirectional wiring and applies recommended security configurations under the hood.

Create or update your `layerzero.config.ts` file in the root of your Hardhat project:

{% code lineNumbers="true" %}

```typescript
import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities';
import { OAppEnforcedOption, OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat';
import { EndpointId } from '@layerzerolabs/lz-definitions';
import { generateConnectionsConfig } from '@layerzerolabs/metadata-tools';

// Define the Contracts
const chilizContract: OmniPointHardhat = {
    eid: EndpointId.CHILIZ_V2_MAINNET,
    contractName: 'ChilizSolanaAdapter', // Your Hardhat deployment name on EVM
};

const solanaContract: OmniPointHardhat = {
    eid: EndpointId.SOLANA_V2_MAINNET,
    address: 'YourSolanaProgramIdHereInBase58', // Base58 address format for Solana
};

// Define Execution Options for Solana (Compute Units & Lamports)
const SOLANA_ENFORCED_OPTIONS: OAppEnforcedOption[] = [
    {
        msgType: 1,
        optionType: ExecutorOptionType.LZ_RECEIVE,
        gas: 200000,    // Solana Compute Units needed for destination execution
        value: 2500000, // Lamports to cover the potential ATA creation rent fee
    },
];

// Define Execution Options for the return trip to Chiliz (EVM Gas)
const EVM_ENFORCED_OPTIONS: OAppEnforcedOption[] = [
    {
        msgType: 1, 
        optionType: ExecutorOptionType.LZ_RECEIVE,
        gas: 200000, // Standard EVM gas units to unlock tokens on Chiliz
        value: 0,
    },
];

// Export the Generated Configuration
export default async function () {
    return {
        contracts: [
            { contract: chilizContract },
            { contract: solanaContract },
        ],
        connections: await generateConnectionsConfig([
            [
                chilizContract, 
                solanaContract,
                [['LayerZero Labs'], []], 
                [1, 1], 
                [SOLANA_ENFORCED_OPTIONS, EVM_ENFORCED_OPTIONS], // Options [To Solana SVM, To Chiliz EVM]
            ],
        ]),
    };
}
```

{% endcode %}

The LayerZero wire task will read this, decode the Base58 string, pad it to 32 bytes, and pass it securely into the Chiliz OFTAdapter's `setPeer` function.

## Step 3: Deployment Workflow

With your contracts written and your `layerzero.config.ts` prepared, it is time to deploy the Chiliz OFTAdapter. Since you already built and deployed the Solana native OFT program using Anchor in Step 1, this step focuses on deploying the EVM side of the bridge using Hardhat.

### **Deploying The Chiliz OFTAdapter contract**

In your Hardhat project, create a deployment script in your `deploy/` directory named `01_deploy_chiliz_solana_adapter.ts`. This script passes your existing token address and the Chiliz Endpoint V2 address (EID) into the constructor.

{% code overflow="wrap" lineNumbers="true" %}

```typescript
import { DeployFunction } from 'hardhat-deploy/types';

const deployAdapter: DeployFunction = async ({ getNamedAccounts, deployments }) => {
    const { deploy } = deployments;
    const { deployer } = await getNamedAccounts();

    // The address of your existing ERC-20 token on Chiliz (18 decimals)
    const TOKEN_ADDRESS = "0xYourTokenAddressHere"; 
    
    // The Chiliz Mainnet Endpoint V2 Address
    const CHILIZ_ENDPOINT_V2 = "0x6F475642a6e85809B1c36Fa62763669b1b48DD5B";

    console.log("Deploying OFTAdapter to Chiliz Mainnet...");

    await deploy('ChilizSolanaAdapter', {
        from: deployer,
        args: [
            TOKEN_ADDRESS,       // _token
            CHILIZ_ENDPOINT_V2,  // _lzEndpoint
            deployer             // _delegate (Owner)
        ],
        log: true,
        waitConfirmations: 2,
    });
};

export default deployAdapter;
deployAdapter.tags = ['ChilizSolanaAdapter'];
```

{% endcode %}

### **Deploying the Chiliz OFTAdapter**

{% hint style="info" %}
Before proceeding, make sure that:

* you have copied the resulting Base58 Program ID into your `layerzero.config.ts` file.
* your `hardhat.config.ts` has the RPC URL and private key properly configured for Chiliz Chain Mainnet.
  {% endhint %}

Run the following command in your terminal to deploy the EVM Adapter:

{% code overflow="wrap" lineNumbers="true" %}

```bash
npx hardhat deploy --network chiliz --tags ChilizSolanaAdapter
```

{% endcode %}

Once the deployment is complete, Hardhat will save the Chiliz contract address in the `deployments/` folder.

At this point, you have live contracts on both Chiliz Chain (EVM) and Solana (SVM), but they do not yet trust each other. Time to make them meet!

## Step 4: Wiring & Peering

To allow your OFTAdapter contract and OFT program to communicate, you must "wire" them together as trusted peers.

Because we are bridging across two entirely different Virtual Machines (EVM and SVM), configuring requires special attention.

{% hint style="info" %}
**EVM gas vs Solana compute units**

When a user bridges a token from Chiliz Chain to another EVM chain (like Base), the LayerZero Executor needs EVM gas to call `lzReceive`.

However, when bridging from Chiliz Chain to Solana, the target chain does not use EVM gas. [It uses Compute Units and Lamports (fractions of $SOL)](https://solana.com/docs/core/fees).\
Furthermore, if a user bridges tokens to a Solana wallet that does not yet hold your token, the Executor must pay Solana's "rent exemption" fee to create an Associated Token Account (ATA) for them. This requires dropping actual $SOL value on the destination.
{% endhint %}

To guarantee the Executor has enough Compute Units and Lamports to mint tokens and create ATAs on Solana, you must define these limits in your `layerzero.config.ts` file *before* wiring.

Run the automated wire command in your terminal:

{% code lineNumbers="true" %}

```bash
npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts
```

{% endcode %}

This will prepare the 6 required configuration transactions:

1. `setSendLibrary`: Assigns the MessageLib for outbound packets.
2. `setReceiveLibrary`: Assigns the MessageLib for inbound packets.
3. `setConfig`: Configures the DVNs and Executor.
4. `setConfig` : Configures the DVNs for inbound verification.
5. `setEnforcedOptions`: Ensures consistent execution parameters (crucial for ensuring the user pays enough upfront to cover Solana Compute Units and Lamport rent).
6. `setPeer`: Links the Solana EID to your destination Base58 Program ID.

The LayerZero V2 toolbox automates the heavy lifting: it will decode the Base58 Solana address, pad it to the required `bytes32` EVM format, and submit the `setPeer` and `setEnforcedOptions` transactions to both chains.

Once the wiring transactions confirm, your EVM-to-Solana bridge is live and securely permissioned.

Your token is officially ready to cross the EVM/SVM divide!

## Step 5: Operation & Testing

With your Chiliz Adapter deployed, your Solana Native OFT initialized, and the two properly wired together, your token is officially ready to cross the EVM/SVM divide. The final step is to execute and track a test transfer from Chiliz Chain to Solana.

### 1) Sending the Cross-Chain Message to Solana

The LayerZero V2 toolbox includes a Hardhat task for sending OFT transfers directly from the command line.

Unlike EVM-to-EVM transfers where your destination is a standard hexadecimal string, your destination here is a Base58 Solana wallet address. The LayerZero CLI handles the Base58-to-Bytes32 conversion for the message payload automatically.

Run the following command in your terminal:

{% code overflow="wrap" lineNumbers="true" %}

```bash
npx hardhat lz:oft:send --oapp-config layerzero.config.ts --from-eid 30409 --to-eid 30168 --to <YOUR_SOLANA_WALLET_ADDRESS_BASE58> --amount 10
```

{% endcode %}

{% hint style="info" %}
What happens here?

1. The script quotes the cross-chain fee in $CHZ (which covers the EVM gas, the verifier network fees, and the Solana destination fees).
2. It calls the `send()` function on your Chiliz Adapter.
3. The Adapter locks 10 tokens (18 decimals). It drops the lowest 12 decimals as "dust" (leaving them in your Chiliz wallet) to scale the payload down to the 6 `sharedDecimals`.
4. The LayerZero Endpoint emits the packet toward the Solana Mainnet.
   {% endhint %}

### 2) Tracking the Packet on LayerZero Scan

Because bridging to Solana involves translating between two entirely different consensus mechanisms and waiting for SVM finality, an asynchronous delay is normal.

To track this journey in real-time, click the LayerZero Scan link that appears in the CLI output.

Learn more about this tool here:

{% embed url="<https://docs.layerzero.network/v2/developers/evm/tooling/layerzeroscan>" %}

{% hint style="info" %}

#### Decimal Translation

The Solana Native OFT will have automatically scaled the 6-decimal payload coming from the bridge up to the standard SPL 9 decimals, so your Solana wallet receives exactly 10 full tokens.
{% endhint %}

**4) Troubleshooting Stuck Messages**

If your transaction is marked as confirmed on Chiliz but fails to execute on Solana, the most common culprit is an Insufficient Lamports, or Compute Units error.

* If the destination Solana wallet did not already have an Associated Token Account (ATA) for your specific token, the LayerZero Executor had to pay the Solana "rent exemption" fee to create it.
* If the `value` parameter (Lamports) in your `enforcedOptions` was set too low to cover this rent, or if the `gas` (Compute Units) was insufficient, the Executor will refuse to pay out of pocket, and the message will stall.
* Fix: You do not lose your tokens. You can manually push a stuck message through via the LayerZero Scan UI. Connect your Solana wallet, click the "Force Resume" or "Execute" button on the block explorer, and pay the local destination fee (Compute Units + ATA Rent in $SOL) yourself to finalize the minting.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.chiliz.com/develop/advanced/use-omnichain-tokens/bridging-from-chiliz-chain-to-solana.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
