> For the complete documentation index, see [llms.txt](https://docs.chiliz.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chiliz.com/ko/gaebal/goseup/omnicheun-token/chiliz-solana-beuriji.md).

# Chiliz Chain에서 Solana로 브리지

Chiliz Chain에서 Solana로 기존 토큰을 브릿징하려면 두 개의 별도 스마트 컨트랙트를 작성하고 배포해야 합니다: 토큰이 이미 존재하는 체인(Chiliz Chain)에 OFT 어댑터를, 대상 체인(Solana)에 네이티브 OFT를 배포합니다.

*LayerZero는 OFT 컨트랙트에 대한 자체 QuickStart를 제공합니다:*

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

## 사전 요구사항

{% hint style="info" %}
Chiliz Chain(EVM)에서 Solana(비EVM)로의 브릿징은 이중 스택 개발이 필요합니다.\
두 생태계 모두에 대한 환경과 지갑이 설정되어 있어야 합니다.

따라서 다음 환경이 필요합니다:

* Chiliz Chain 상호작용의 경우: Node/npx 및 Hardhat.
* Solana 상호작용의 경우: [Rustup](https://rustup.rs/)(Solana 스마트 컨트랙트는 Rust 프로그래밍 언어 사용), [Solana CLI 및 Anchor 프레임워크](https://solana.com/docs/intro/installation), [LayerZero의 Solana SDK](https://docs.layerzero.network/v2/tools/sdks/solana-sdk).
  {% endhint %}

이 가이드에는 다음이 필요합니다:

* Chiliz Chain의 토큰 컨트랙트 주소. 소유할 필요는 없습니다.
* 각 체인에 대한 Web3 지갑(MetaMask는 비EVM 체인을 지원하지 않습니다):
  * Chiliz Chain용: [Chiliz Chain RPC 구성](/ko/gaebal/gibon/chiliz-chain-yeongyeol/rpc-yeongyeol.md)이 설정된 MetaMask 지갑.
  * Solana용: [Solana Mainnet 구성](https://solana.com/docs/references/clusters)이 설정된 [Solflare](https://www.solflare.com/) 지갑. [설정 가이드는 여기](https://www.solflare.com/guides/how-to-set-up-your-first-crypto-wallet-with-solflare-step-by-step/)를 참조하세요.
* 컨트랙트 배포 및 메시지 전송을 위한 가스 요금을 지불할 충분한 각 체인의 가스 토큰.
  * Chiliz Chain: CHZ 토큰.
  * Solana: SOL 토큰.

## 1단계: 컨트랙트 개발

{% hint style="info" %}
**"공유 소수점" 과제**

Solana는 EVM과 다른 방식으로 토큰 수학을 처리하므로, 소수점을 올바르게 처리해야 합니다:

* Chiliz Chain(EVM): 표준 ERC-20 토큰은 일반적으로 18자리 소수점 정밀도를 가집니다.
* Solana: 네이티브 SPL 토큰은 일반적으로 9자리 소수점 정밀도를 가집니다.

Chiliz에서 Solana로 $$ $1 \times 10^{18}$ $$ 단위를 보내면, Solana 컨트랙트가 금액을 잘못 해석하여 목적지 체인에서 토큰이 대규모로 인플레이션됩니다.

이 수학을 정규화하기 위해, LayerZero는 `sharedDecimals` 구성을 사용합니다. 기본적으로 LayerZero V2 OFT 표준은 `sharedDecimals`를 6으로 설정합니다.

* 사용자가 Chiliz에서 1.00 토큰을 브릿징하면, 어댑터가 가장 낮은 12자리 소수점을 "먼지"로 처리하여 제거하고 숫자를 6자리 소수점으로 축소합니다.
* 메시지가 브릿지를 통해 전송됩니다.
* Solana 프로그램이 6자리 소수점 숫자를 받아 민팅하기 전에 로컬 9자리 소수점으로 확장합니다.

[자세히 알아보기](https://docs.layerzero.network/v2/faq#what-is-shareddecimals-can-i-override-default-shareddecimals-in-an-oft-contract).
{% endhint %}

### Chiliz Chain에서 `OFTAdapter` 준비하기

{% hint style="warning" %}
이것은 준비 단계입니다. 지금 바로 배포하지 마세요!\
3단계에서 배포합니다.
{% endhint %}

`OFTAdapter` 컨트랙트는 기존 토큰의 잠금 상자 역할을 합니다. 사용자가 Chiliz Chain에서 토큰을 브릿징할 때, 이 컨트랙트가 원래 ERC20 토큰을 잠급니다.

{% hint style="info" %}
LayerZero의 `OFTAdapter`는 기본적으로 `sharedDecimals`를 6으로 설정하므로 표준 구현을 사용할 수 있습니다. 이를 변경해야 하는 경우(예: 8로), `sharedDecimals()` 함수를 재정의하면 됩니다.
{% endhint %}

contracts 폴더에 `ChilizTokenAdapter.sol` 파일을 새로 만드세요:

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

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" %}
이 컨트랙트는 [LayerZero OFT 어댑터 컨트랙트](https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/oapp/contracts/oft/OFTAdapter.sol)와 관리 키를 제공하기 위한 표준 `Ownable.sol` 컨트랙트를 확장합니다. 체인을 안전하게 연결하려면 두 가지 모두 필요합니다.
{% endhint %}

### Solana에서 `OFT` 준비 및 배포하기

Chiliz Chain과 달리, Solana는 EVM 또는 Solidity 언어를 사용하지 않습니다. Solana 스마트 컨트랙트("프로그램")는 [Rust](https://rust-lang.org/)로 작성됩니다.

토큰을 브릿징하려면 Solana에 OFT 프로그램을 배포해야 합니다. 이 프로그램은 Chiliz에 배포된 OFTAdapter로부터 검증된 메시지를 받으면 해당 SPL 토큰을 사용자의 Solana 지갑에 민팅합니다.

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

LayerZero는 처음부터 Rust 브릿지 로직을 작성하지 않아도 되도록 [바로 사용 가능한 Anchor 예제](https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-solana)를 제공합니다.

#### 1. LayerZero OFT Solana 예제 클론:

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

#### 2. Rust 프로그램 빌드

이것은 또한 고유한 Solana 프로그램 ID(EVM의 컨트랙트 주소에 해당)를 생성합니다:

```bash
anchor build
```

빌드가 완료되면, Anchor가 `target/deploy/oft_solana-keypair.json`에 새 키페어를 생성합니다.\
다음을 실행하여 새 프로그램 ID를 검색할 수 있습니다:

```bash
anchor keys list
```

#### 3. Solana Mainnet에 배포

Solana CLI가 Mainnet용으로 구성되어 있고, 로컬 지갑에 배포와 저장 임대료를 위한 충분한 $SOL이 있는지 확인하세요.\
배포 전에 이 새 프로그램 ID로 `Anchor.toml` 파일과 `lib.rs`의 declare\_id! 매크로를 업데이트하세요.

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

#### 4. OFT와 SPL 민트 초기화

Solana에서 토큰의 로직과 원장은 분리되어 있습니다. 새 민트 계정(SPL 토큰)을 초기화하고 새로 배포된 OFT 프로그램을 민트 권한으로 할당해야 합니다. 이렇게 하면 LayerZero 브릿지만이 Solana에서 새 토큰을 민팅할 수 있습니다.

LayerZero SDK는 이 초기화를 명령줄에서 직접 처리하기 위한 Hardhat/TypeScript 태스크를 제공합니다. `oft-solana` 프로젝트에서 Solana에 대한 LayerZero Endpoint(`30168`)를 구성하고 초기화 스크립트를 실행합니다:

{% 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" %}
중요한 파라미터:

* `--mint-decimals 9`: Solana의 표준 SPL 토큰 정밀도를 설정합니다.
* `--shared-decimals 6`: Chiliz Chain `OFTAdapter`에서 구성한(또는 기본값) 공유 소수점과 일치해야 합니다. 이것이 1 Chiliz 토큰 = 1 Solana 토큰을 보장하는 것입니다.
  {% endhint %}

이 초기화 트랜잭션이 Solana 블록체인에서 확인되면, 네이티브 OFT 프로그램이 완전히 설정되어 Chiliz OFTAdapter와 배선할 준비가 됩니다!

## 2단계: LayerZero 구성

Chiliz 어댑터가 배포되고 Solana OFT 프로그램이 초기화되었다면, 이제 연결을 구성해야 합니다. 여기서 EVM과 비EVM 네트워크의 차이가 매우 뚜렷하게 나타납니다.

{% hint style="info" %}
주소 형식:

* Chiliz Chain(EVM): 표준 20바이트 16진수 주소 사용(예: `0x123...`).
* Solana: Base58 인코딩 주소 사용(예: `YourProgramId111111111111111111111111111111`).
  {% endhint %}

LayerZero의 교차 체인 메시징은 모든 [피어 주소](https://docs.layerzero.network/v2/concepts/glossary#peer)가 `bytes32`로 형식화되어야 합니다. 다행히 LayerZero V2 Hardhat 도구는 구성에서 엔드포인트를 올바르게 정의하는 한 Base58에서 Bytes32로의 변환을 자동으로 처리합니다.

[Simple Config Generator](https://docs.layerzero.network/v2/tools/simple-config)는 양방향 배선을 자동화하고 권장 보안 구성을 자동으로 적용하므로 권장되는 배선 구성 생성 방법입니다.

Hardhat 프로젝트 루트에서 `layerzero.config.ts` 파일을 생성하거나 업데이트하세요:

{% 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 %}

LayerZero wire 태스크는 이것을 읽고, Base58 문자열을 디코딩하고, 32바이트로 패딩하여 Chiliz OFTAdapter의 `setPeer` 함수에 안전하게 전달합니다.

## 3단계: 배포 워크플로우

컨트랙트를 작성하고 `layerzero.config.ts`를 준비했다면, 이제 Chiliz OFTAdapter를 배포할 차례입니다. 1단계에서 Anchor를 사용하여 Solana 네이티브 OFT 프로그램을 이미 빌드하고 배포했으므로, 이 단계는 Hardhat을 사용한 브릿지의 EVM 측 배포에 집중합니다.

### **Chiliz OFTAdapter 컨트랙트 배포**

Hardhat 프로젝트의 `deploy/` 디렉토리에 `01_deploy_chiliz_solana_adapter.ts` 배포 스크립트를 생성합니다. 이 스크립트는 기존 토큰 주소와 Chiliz Endpoint V2 주소(EID)를 생성자에 전달합니다.

{% 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 %}

### **Chiliz OFTAdapter 배포**

{% hint style="info" %}
진행하기 전에 다음을 확인하세요:

* 결과 Base58 프로그램 ID를 `layerzero.config.ts` 파일에 복사했습니다.
* `hardhat.config.ts`에 Chiliz Chain Mainnet에 대한 RPC URL과 개인 키가 올바르게 구성되어 있습니다.
  {% endhint %}

터미널에서 다음 명령을 실행하여 EVM 어댑터를 배포합니다:

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

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

{% endcode %}

배포가 완료되면, Hardhat이 Chiliz 컨트랙트 주소를 `deployments/` 폴더에 저장합니다.

이 시점에서 Chiliz Chain(EVM)과 Solana(SVM) 모두에 라이브 컨트랙트가 있지만, 아직 서로를 신뢰하지 않습니다. 이제 만나게 할 시간입니다!

## 4단계: 배선 및 피어링

OFTAdapter 컨트랙트와 OFT 프로그램이 통신할 수 있도록 신뢰할 수 있는 피어로 "배선"해야 합니다.

두 가지 완전히 다른 가상 머신(EVM 및 SVM)에 걸쳐 브릿징하므로 구성에 특별한 주의가 필요합니다.

{% hint style="info" %}
**EVM 가스 vs Solana 컴퓨팅 유닛**

사용자가 Chiliz Chain에서 Base와 같은 다른 EVM 체인으로 토큰을 브릿징할 때, LayerZero Executor는 `lzReceive`를 호출하기 위해 EVM 가스가 필요합니다.

그러나 Chiliz Chain에서 Solana로 브릿징할 때, 목적지 체인은 EVM 가스를 사용하지 않습니다. [컴퓨팅 유닛과 Lamport($SOL의 분율)를 사용합니다](https://solana.com/docs/core/fees).\
또한, 사용자가 아직 귀하의 토큰을 보유하지 않은 Solana 지갑으로 토큰을 브릿징하면, Executor가 그들을 위한 ATA(Associated Token Account)를 생성하기 위해 Solana의 "임대 면제" 수수료를 지불해야 합니다. 이는 목적지에 실제 $SOL 가치를 드롭해야 합니다.
{% endhint %}

Executor가 Solana에서 토큰을 민팅하고 ATA를 생성하기에 충분한 컴퓨팅 유닛과 Lamport를 보장하려면, 배선 전에 `layerzero.config.ts` 파일에서 이러한 한도를 정의해야 합니다.

터미널에서 자동화된 배선 명령을 실행합니다:

{% code lineNumbers="true" %}

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

{% endcode %}

이것은 6개의 필요한 구성 트랜잭션을 준비합니다:

1. `setSendLibrary`: 아웃바운드 패킷을 위한 MessageLib를 할당합니다.
2. `setReceiveLibrary`: 인바운드 패킷을 위한 MessageLib를 할당합니다.
3. `setConfig`: DVN과 Executor를 구성합니다.
4. `setConfig`: 인바운드 검증을 위한 DVN을 구성합니다.
5. `setEnforcedOptions`: 일관된 실행 파라미터를 보장합니다(사용자가 Solana 컴퓨팅 유닛과 Lamport 임대료를 충당하기에 충분히 선불로 지불하도록 보장하는 데 매우 중요합니다).
6. `setPeer`: Solana EID를 목적지 Base58 프로그램 ID에 연결합니다.

LayerZero V2 도구는 무거운 작업을 자동화합니다: Base58 Solana 주소를 디코딩하고, 필요한 `bytes32` EVM 형식으로 패딩하고, `setPeer` 및 `setEnforcedOptions` 트랜잭션을 두 체인 모두에 제출합니다.

배선 트랜잭션이 확인되면, EVM-Solana 브릿지가 활성화되고 안전하게 권한 설정됩니다.

귀하의 토큰이 공식적으로 EVM/SVM 경계를 넘을 준비가 되었습니다!

## 5단계: 운영 및 테스트

Chiliz 어댑터가 배포되고, Solana 네이티브 OFT가 초기화되고, 둘이 올바르게 배선되었다면, 토큰이 공식적으로 EVM/SVM 경계를 넘을 준비가 되었습니다. 마지막 단계는 Chiliz Chain에서 Solana로의 테스트 전송을 실행하고 추적하는 것입니다.

### 1) Solana로 교차 체인 메시지 전송

LayerZero V2 도구는 명령줄에서 직접 OFT 전송을 전송하기 위한 내장 Hardhat 태스크를 포함합니다.

EVM-EVM 전송에서 목적지가 표준 16진수 문자열인 것과 달리, 여기서 목적지는 Base58 Solana 지갑 주소입니다. LayerZero CLI는 메시지 페이로드에 대한 Base58에서 Bytes32로의 변환을 자동으로 처리합니다.

터미널에서 다음 명령을 실행합니다:

{% 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" %}
여기서 일어나는 일:

1. 스크립트가 $CHZ로 교차 체인 수수료를 견적합니다(EVM 가스, 검증 네트워크 수수료, Solana 목적지 수수료 포함).
2. Chiliz 어댑터에서 `send()` 함수를 호출합니다.
3. 어댑터가 10개의 토큰(18자리 소수점)을 잠급니다. 가장 낮은 12자리 소수점을 "먼지"로 제거하여(Chiliz 지갑에 남겨두어) 페이로드를 6개의 `sharedDecimals`로 축소합니다.
4. LayerZero Endpoint가 Solana Mainnet을 향해 패킷을 전송합니다.
   {% endhint %}

### 2) LayerZero Scan에서 패킷 추적

Solana로의 브릿징은 두 가지 완전히 다른 합의 메커니즘 간의 번역과 SVM 파이널리티를 기다리는 것을 포함하므로, 비동기적 지연이 정상입니다.

이 과정을 실시간으로 추적하려면, CLI 출력에 나타나는 LayerZero Scan 링크를 클릭하세요.

이 도구에 대해 자세히 알아보세요:

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

{% hint style="info" %}

#### 소수점 변환

Solana 네이티브 OFT는 브릿지에서 들어오는 6자리 소수점 페이로드를 표준 SPL 9자리 소수점으로 자동 확장하므로, Solana 지갑은 정확히 10개의 전체 토큰을 받습니다.
{% endhint %}

**4) 중단된 메시지 문제 해결**

Chiliz에서 확인되었지만 Solana에서 실행에 실패한 경우, 가장 일반적인 원인은 Lamport 부족 또는 컴퓨팅 유닛 오류입니다.

* 목적지 Solana 지갑에 이미 귀하의 특정 토큰에 대한 ATA가 없었다면, LayerZero Executor가 이를 생성하기 위해 Solana "임대 면제" 수수료를 지불해야 했습니다.
* `enforcedOptions`의 `value` 파라미터(Lamport)가 이 임대료를 충당하기에 너무 낮거나, `gas`(컴퓨팅 유닛)가 부족했다면, Executor가 자비로 지불하기를 거부하여 메시지가 중단됩니다.
* 해결 방법: 토큰을 잃지 않습니다. LayerZero Scan UI를 통해 중단된 메시지를 수동으로 밀어낼 수 있습니다. Solana 지갑을 연결하고, 블록 탐색기에서 "Force Resume" 또는 "Execute" 버튼을 클릭하여 민팅을 완료하기 위해 로컬 목적지 수수료(컴퓨팅 유닛 + ATA 임대료($SOL))를 직접 지불합니다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.chiliz.com/ko/gaebal/goseup/omnicheun-token/chiliz-solana-beuriji.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
