메인 콘텐츠로 건너뛰기

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
Raydium의 코드를 읽기 전에 이해해야 할 가장 중요한 것은 Solana의 계정 모델입니다. Ethereum과 달리 Solana는 상태가 계약 코드와 함께 존재하지 않습니다. 대신 Solana 프로그램은 완전히 상태 없는 구조를 가지고 있습니다: 모든 상태는 별도의 “계정”에 살며, 프로그램이 이 계정들에 작동합니다. Raydium의 모든 풀, 포지션, 그리고 보관소는 계정입니다 — 이러한 계정들이 어떻게 작동하는지 이해하면 나머지 문서를 이해할 수 있습니다.

기본 분리: 프로그램 vs 계정

프로그램

Solana의 프로그램은 실행 가능한 코드입니다 — 파일에서 로드되고 Pubkey에 배포되며 트랜잭션을 통해 호출될 수 있는 컴파일된 바이너리입니다. 프로그램에는 관련된 상태가 없습니다. 로직만 포함합니다. Raydium의 프로그램:
  • CPMM: CPMMoo8L3F4NbTegBCKVNunggL7H1Zpdmwpwh8KMoZ0F
  • CLMM: CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
  • AMM v4: 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8
각각은 고정된 바이너리입니다. 프로그램은 호출 사이에 아무것도 “기억하지” 않습니다.

계정

계정은 온체인의 데이터 행입니다. 모든 계정은 다음을 가집니다:
  • pubkey — 주소입니다.
  • owner — 계정을 소유한 프로그램입니다 (쓰기를 제어합니다).
  • data — 원본 바이트입니다.
  • lamports — SOL 잔액입니다 (1 SOL = 1,000,000,000 lamports).
  • rent_epoch — 레거시 렌트 수금 필드입니다 (렌트 면제가 필수가 된 이후로는 무시됩니다).
Raydium 풀을 조회할 때, 하나 이상의 계정을 읽고 있습니다. 스왑이 실행될 때, CPMM 프로그램은 여러 계정을 읽고 씁니다 — 풀 상태, 보관소, 관찰 상태, 그리고 사용자의 토큰 계정입니다.

소유권

모든 계정은 정확히 한 프로그램에 의해 소유됩니다. 오직 그 프로그램의 코드만 계정의 data 필드를 수정할 수 있습니다. 사용자는 서명할 수 있는 계정에서 lamports를 수정할 수 있습니다 (SOL 전송/수신), 하지만 data를 수정하려면 소유자 프로그램이 대신 해야 합니다. 예시:
  • 사용자 지갑: 시스템 프로그램에 의해 소유됩니다. Lamports가 여기에 있습니다. 서명하여 전송합니다.
  • USDC 토큰 계정: SPL 토큰 프로그램에 의해 소유됩니다. 토큰 프로그램의 transfer 명령이 잔액을 업데이트합니다.
  • Raydium 풀 상태 계정: CPMM 프로그램에 의해 소유됩니다. CPMM의 명령만 준비금, 수수료 등을 수정할 수 있습니다.
  • Raydium 포지션 NFT의 PersonalPositionState: CLMM 프로그램에 의해 소유됩니다.
“소유”는 엄격합니다: 프로그램 A가 프로그램 B가 소유한 계정에 쓰려고 하면, Solana 런타임이 트랜잭션을 거부합니다.

렌트 및 렌트 면제

계정을 만드는 것은 저장소 공간을 소비합니다. Solana는 그 공간에 렌트를 청구합니다. 하지만 2020년 이후 모든 새 계정은 렌트 면제 상태여야 합니다 — 즉, 2년에 걸쳐 지불해야 할 렌트가 미리 지불된 충분한 lamports를 보유해야 합니다. 실제로:
  • 렌트 면제 계정은 영구적으로 지속됩니다.
  • 계정을 닫으면 lamports가 종료 서명자에게 반환됩니다.
165바이트 계정(예: SPL 토큰 계정)의 경우, 렌트 면제는 약 0.00204 SOL입니다. 1,440바이트 Raydium CPMM 풀 상태의 경우, 약 0.011 SOL입니다.

Raydium 렌트 비용

계정크기렌트
CPMM PoolState~1,440 B~0.011 SOL
CLMM PoolState~1,500 B~0.012 SOL
CLMM TickArray~9,000 B~0.063 SOL
CLMM PersonalPositionState~280 B~0.003 SOL
ATA165 B~0.002 SOL
Vault (Token Account)165 B~0.002 SOL
풀 생성은 여러 계정의 렌트를 한 번에 필요로 합니다 — 이것이 CPMM 풀 생성이 총 약 0.15 SOL이 드는 이유입니다.

데이터 vs 실행 가능 계정

계정은 두 가지 유형으로 나뉩니다:

데이터 계정

상태를 보유합니다 (풀 준비금, 토큰 잔액, 사용자 포지션). executable = false. 대다수입니다.

실행 가능 계정

프로그램 바이트코드를 보유합니다. executable = true. 이들은 프로그램입니다 (CPMM, CLMM 등). 프로그램은 바이트코드 외에 데이터가 없습니다.

프로그램 파생 계정 (PDA)

PDA는 주소가 프로그램과 일부 시드에서 결정론적으로 파생된 데이터 계정입니다 — 이 주소에는 개인 키가 존재하지 않습니다. 오직 파생 프로그램만 invoke_signed를 통해 PDA를 대신하여 서명할 수 있습니다. Raydium은 PDA를 광범위하게 사용합니다:
  • 풀 상태 PDA: [poolTypeDiscriminator, mintA, mintB, ammConfig]에서 파생됩니다.
  • 보관소 PDA: [pool, mint]에서 파생됩니다.
  • 관찰 상태 PDA: [observationSeed, pool]에서 파생됩니다.
PDA를 사용하면 Raydium은 키를 관리하지 않고도 예측 가능한 주소에서 계정을 만들 수 있습니다. 누구나 알려진 풀의 시드가 주어지면 PDA 주소를 계산할 수 있습니다. solana-fundamentals/pdas-and-cpis를 참조하세요.

트랜잭션 및 계정 참조

모든 Solana 트랜잭션은 읽거나 쓸 계정의 명시적 목록을 포함합니다. 런타임은 다음을 강제합니다:
  • 나열된 계정은 읽거나 쓸 수 있습니다 (is_writable 플래그에 따라).
  • 나열되지 않은 계정은 건드릴 수 없습니다.
Raydium 스왑의 경우, 트랜잭션의 계정 목록은 다음을 포함합니다:
[readonly] CPMM program
[writable] pool state
[readonly] amm config
[readonly] pool authority (PDA)
[writable] input vault
[writable] output vault
[writable] user input ATA
[writable] user output ATA
[readonly] input mint
[readonly] output mint
[readonly] input token program
[readonly] output token program
[writable] observation state
[signer,writable] user
이 명시적 열거는 Solana 트랜잭션이 빠르고 병렬화 가능한 이유입니다 — 런타임이 미리 상충하지 않는 트랜잭션을 결정할 수 있습니다.

계정 크기 및 데이터 레이아웃

모든 Raydium 계정은 고정되거나 제한된 크기를 가집니다. 레이아웃은 코드에서 정의되며 (Rust 구조체와 #[repr(C)]), sdk-api/anchor-idl에서 문서화됩니다. Anchor 프로그램은 생성하는 모든 계정에 8바이트 판별자를 앞에 붙입니다. 이는 hash("account:<StructName>")[0..8]에서 파생됩니다. 이를 통해 클라이언트가 처음 8바이트를 읽는 것만으로 계정의 유형을 식별할 수 있습니다 — getProgramAccounts 스캔에서 한 유형의 모든 계정을 열거할 때 중요합니다.

Raydium 풀 상태 읽기

SDK를 통해:
const pool = await raydium.cpmm.getPoolInfoFromRpc({ poolId });
console.log(pool.poolInfo);
원본 RPC + 레이아웃을 통해:
const accountInfo = await connection.getAccountInfo(poolId);
const data = accountInfo.data;
// 처음 8바이트(판별자)를 건너뛴 후, 구조체 레이아웃에 따라 파싱합니다.
const poolState = CpmmPoolStateLayout.decode(data.slice(8));
레이아웃은 SDK 소스의 src/raydium/cpmm/layout.ts에 있습니다.

작동 예시: 토큰 계정 읽기

사용자의 USDC 잔액을 읽어봅시다.
import { Connection, PublicKey } from "@solana/web3.js";
import { getAssociatedTokenAddressSync, AccountLayout } from "@solana/spl-token";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const user       = new PublicKey("YourUserWallet...");
const usdcMint   = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");

// 1. ATA 주소를 계산합니다 (PDA 스타일 파생).
const ata = getAssociatedTokenAddressSync(usdcMint, user);

// 2. 계정을 읽습니다.
const accountInfo = await connection.getAccountInfo(ata);
if (!accountInfo) {
  console.log("ATA는 아직 존재하지 않습니다 (사용자가 USDC를 보유한 적이 없습니다).");
  return;
}

// 3. 소유자가 SPL 토큰 프로그램인지 확인합니다.
console.assert(accountInfo.owner.toBase58() === "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");

// 4. 데이터를 디코딩합니다.
const parsed = AccountLayout.decode(accountInfo.data);
console.log("Balance (smallest units):", parsed.amount.toString());
console.log("Mint:",                     new PublicKey(parsed.mint).toBase58());
console.log("Owner:",                    new PublicKey(parsed.owner).toBase58());
이 패턴 — 주소 파생, 계정 가져오기, 소유자 확인, 디코딩 — Raydium 풀을 포함한 모든 온체인 읽기에 적용됩니다.

Raydium에 이것이 중요한 이유

계정 모델은 Raydium의 설계를 형성합니다:
  • 풀 상태는 단일 계정입니다 — 풀에 대한 모든 것 (민트, 준비금, 수수료, 관리자)이 풀 프로그램이 소유한 하나의 계정에 살고 있습니다.
  • LP 토큰은 표준 SPL 토큰 계정입니다 — Raydium은 토큰화를 SPL 토큰 프로그램에 위임합니다.
  • 틱 배열은 청크로 나뉩니다 — CLMM은 계정이 고정 할당 크기를 가지기 때문에 확장 가능한 단일 틱 배열을 가질 수 없습니다. 대신, 청크된 TickArray PDA를 사용합니다.
  • 포지션 NFT는 Metaplex NFT입니다 — CLMM 포지션은 Metaplex에 따른 표준 NFT입니다. 포지션 상태는 별도 PDA입니다.
이를 이해하면 “X는 어디에 있는가?”라는 질문을 올바르게 답할 수 있습니다:
  • “풀 준비금은 어디에 있는가?” → 두 개의 보관소 계정 (토큰 계정)은 SPL 토큰 프로그램이 소유하며, 권한은 풀 프로그램의 PDA에 위임됩니다.
  • “CLMM의 틱 데이터는 어디에 있는가?” → 일련의 TickArray PDA, 각각 60개의 연속 틱을 다룹니다.
  • “내 팜 스테이크는 어디에 있는가?” → [user, farmId]에서 파생된 UserLedger PDA, 팜 프로그램이 소유합니다.

포인터

출처: