메인 콘텐츠로 건너뛰기

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 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
Solana 트랜잭션은 원자적으로 실행되는 명령어 목록입니다. 트랜잭션 구조(명령어, 계정, 서명자, 컴퓨트 예산)를 이해하는 것은 Raydium으로 무엇을 구축하든 디버깅하든 최적화하든 필수입니다. 이 페이지에서는 그 구조, 제약 조건, 그리고 두 가지 수수료 범주(Solana 네트워크 수수료, Raydium 프로토콜 수수료)가 실제 스왑에서 어떻게 적용되는지 다룹니다.

트랜잭션 구조

Solana 트랜잭션은 세 가지 핵심 구성요소로 이루어져 있습니다:
  • 메시지: 명령어의 순서 목록, 참조하는 계정, 최근 블록해시입니다.
  • 서명: 각 서명자마다 하나씩, 트랜잭션이 승인되었음을 증명합니다.
  • 최근 블록해시: 트랜잭션이 최근 것임을 증명합니다. 오래된 블록해시(150개 슬롯 이상 지난)를 가진 트랜잭션은 거부됩니다.

명령어

명령어는 다음을 지정합니다:
  • program_id — 호출할 프로그램입니다.
  • accounts — 프로그램이 접근할 수 있는 계정(그리고 쓰기 가능/서명자 플래그)입니다.
  • data — 프로그램이 해석하는 불투명한 바이트입니다.
단일 트랜잭션에는 여러 명령어가 포함될 수 있습니다. 순서대로 실행되며, 하나가 실패하면 이전의 모든 명령어는 롤백됩니다(원자적). 일반적인 Raydium 스왑 트랜잭션에는 다음이 포함됩니다:
  1. ComputeBudget::SetComputeUnitLimit — 기본 CU 한도를 높입니다.
  2. ComputeBudget::SetComputeUnitPrice — 우선순위 수수료를 설정합니다.
  3. 선택사항 CreateAssociatedTokenAccount — 사용자가 없으면 출력 ATA를 생성합니다.
  4. Raydium::SwapBaseInput — 스왑을 실행합니다.
  5. 선택사항 CloseAccount — 래핑된 SOL ATA를 닫습니다.
SDK는 raydium.trade.swap()을 통해 이를 자동으로 패킹합니다.

트랜잭션의 계정

트랜잭션의 모든 명령어가 터치하는 모든 계정은 트랜잭션의 계정 키 목록에 나열되어야 합니다. 각 계정에는 플래그가 지정됩니다:
  • 서명자 / 비서명자: 계정의 소유자가 트랜잭션에 서명해야 합니까?
  • 쓰기 가능 / 읽기 전용: 트랜잭션이 계정을 수정할 수 있습니까?
런타임은 이러한 플래그를 강제합니다. 프로그램이 쓰기 불가능한 계정에 쓰려고 하면 실패하고, 런타임은 필수 서명자가 없는 트랜잭션을 거부합니다. CPMM 스왑의 경우 계정 목록에는 약 13개의 항목이 있습니다(solana-fundamentals/account-model 참조). 여러 틱 어레이 크로싱이 있는 CLMM 스왑은 20개 이상일 수 있습니다.

트랜잭션 크기 제한

Solana는 트랜잭션을 1232바이트로 제한합니다(서명, 메시지, 헤더 포함). 이는 복잡한 트랜잭션의 가장 일반적인 장애물입니다. Raydium의 CLMM 멀티홉 라우팅은 이 한계에 자주 도달합니다. 일반적인 약 1000바이트 Raydium 스왑의 분석:
구성요소크기
서명64 B
서명 개수1 B
메시지 헤더3 B
블록해시32 B
계정 키 (13 × 32 B)416 B
명령어 (4 × ~100-150 B)400–600 B
합계~900–1100 B

주소 조회 테이블 (ALTs)

ALT를 사용하면 트랜잭션이 전체 32바이트 공개 키 대신 게시된 테이블의 1바이트 인덱스로 계정을 참조할 수 있습니다. 이는 트랜잭션을 크게 압축합니다:
  • 20개 계정을 직접 참조하는 트랜잭션: ~640 B의 공개 키.
  • ALT를 사용하는 동일한 트랜잭션: ~20 B의 인덱스 + ALT 참조.
Raydium은 메인넷의 CPMM/CLMM 스왑 경로에 대한 ALT를 유지합니다. SDK는 이를 자동으로 사용합니다. 멀티홉 경로를 구축하는 어그리게이터는 이에 크게 의존합니다.
import { VersionedTransaction } from "@solana/web3.js";

// SDK는 ALT 참조를 포함한 v0(버전화된) tx를 구축합니다
const { transaction } = await raydium.trade.swap({ /* ... */ });
// transaction은 VersionedTransaction이지, 레거시 Transaction이 아닙니다.

컴퓨트 예산

모든 트랜잭션에는 컴퓨트 유닛(CU) 예산이 있습니다. 초과하면 실행이 종료되고 트랜잭션이 실패합니다.
  • 기본값: 트랜잭션당 200,000 CU입니다.
  • 최대값: 트랜잭션당 1,400,000 CU입니다(ComputeBudget::SetComputeUnitLimit을 통해 상향 가능).
  • 블록당 상한: 블록당 48M CU(프로토콜 수준).
일반적인 Raydium CU 소비(integration-guides/priority-fee-tuning의 전체 표 참조):
명령어CU
CPMM 스왑~140,000
CLMM 스왑 (틱 크로싱 없음)~170,000
CLMM 스왑 (4 틱 크로싱)~320,000
Farm v6 스테이크~130,000
CPMM 풀 생성~250,000
항상 ComputeBudget을 통해 명시적 CU 한도를 설정하세요. 그렇지 않으면 기본값인 200k를 받게 되는데, 이는 대부분의 Raydium 명령어에는 너무 낮습니다.
import { ComputeBudgetProgram } from "@solana/web3.js";

tx.add(
  ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }),
);
CU 한도를 너무 낮게 설정하면 한도에 도달할 때 트랜잭션이 실패합니다. 너무 높게 설정하면 혼잡 상태에서 우선순위가 낮아질 수 있고(가격 책정 모델에 따라 사용하지 않은 컴퓨트에 대해 비용을 지불할 수 있습니다).

우선순위 수수료

기본 트랜잭션 수수료(서명당 5000 라모포트) 외에도, 검증자들은 점점 더 우선순위 수수료를 지불하는 트랜잭션을 우선순위화합니다: 마이크로라모포트 단위의 CU당 팁입니다.
priority_fee = compute_unit_price (micro-lamports) × compute_unit_limit
예: 10,000 µL/CU × 300,000 CU = 3,000,000 µL = 0.003 SOL. 우선순위 수수료는 로컬입니다. 블록 내 순서에만 영향을 미치며, 포함 가능성을 높이지는 않습니다. 혼잡 상태에서 합리적인 우선순위 수수료를 설정하는 것이 필수입니다.
tx.add(
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 10_000 }),
);
동적으로 이를 조정하는 방법은 integration-guides/priority-fee-tuning을 참조하세요.

명령어 개수 및 계정 개수 제한

1232바이트 총 한도 외에도:
  • 트랜잭션당 최대 계정: 128입니다.
  • 명령어당 최대 계정 (CPI): 64입니다.
  • 트랜잭션당 최대 명령어: 하드 한도는 없으며, 크기 한도로만 제한됩니다.
  • 최대 CPI 깊이: 4입니다(프로그램은 다른 프로그램을 호출할 수 있으며, 이는 4단계까지 중첩될 수 있습니다).
여러 틱 어레이를 크로싱하는 Raydium CLMM 스왑은 계정 한도에 강하게 도달할 수 있습니다. 단일 스왑은 풀, 입력/출력 보관소, 입력/출력 ATA, 여러 틱 어레이, 가능하면 전송 훅 프로그램의 추가 계정, 그리고 필수 컴퓨트 예산/시스템/토큰 프로그램 참조를 터치합니다. CPI를 통해 Raydium을 구성하는 설계(예: 자동 컴파운더)는 이를 고려해야 합니다.

Raydium 스왑의 수수료 범주

사용자 스왑 트랜잭션은 두 가지 범주의 수수료를 지불합니다:

Solana 네트워크 수수료

검증자에게 SOL로 지불됩니다.
  • 기본 서명 수수료: 서명당 5000 라모포트입니다. 거의 항상 1 서명 = 0.000005 SOL입니다.
  • 우선순위 수수료: CU 가격 × CU 한도(마이크로라모포트). 혼잡도에 따라 다릅니다. integration-guides/priority-fee-tuning을 참조하세요.
이 수수료는 검증자에게 지불되며, Raydium과 무관하며, 실패한 트랜잭션에도 부과됩니다(일부 우선순위 수수료 엣지 케이스 제외).

Raydium 프로토콜 수수료

스왑 금액에서 공제됩니다.
  • 스왑 수수료: 입력의 백분율입니다(CPMM 일반적으로 0.25%, CLMM 등급당 0.01%–1%). LP와 프로토콜 목적지 사이에 분할됩니다. ray/protocol-fees를 참조하세요.
이 수수료는 Raydium 회계의 내부입니다. 사용자는 이를 무수수료 풀이 생성할 출력 금액보다 작은 출력 금액으로 봅니다.

예: CPMM 0.25% 등급을 통해 $1000 USDC → SOL

수수료 범주금액수취 대상
기본 서명 수수료0.000005 SOL (~$0.0007)검증자
우선순위 수수료 (10k µL × 300k CU)0.003 SOL (~$0.45)검증자
CPMM 스왑 수수료 (0.25%)$2.50LP + 프로토콜
총 사용자 비용~$2.95
슬리피지(가격 영향 + 시장 변동)는 수수료가 아니지만 동일한 하단선에 영향을 미칩니다.

버전화된 트랜잭션

Solana에는 두 가지 트랜잭션 형식이 있습니다:
  • 레거시: 원본 형식, ALT 지원 없음.
  • v0 (버전화됨): ALT 지원, 향후 버전으로 확장 가능.
모든 최신 Solana 도구는 v0를 사용합니다. Raydium SDK는 기본적으로 v0 트랜잭션을 내보냅니다.
// v0 tx를 직접 구축합니다
import { VersionedTransaction, TransactionMessage } from "@solana/web3.js";

const msg = new TransactionMessage({
  payerKey:        owner.publicKey,
  recentBlockhash: blockhash,
  instructions:    [ /* ... */ ],
}).compileToV0Message([lookupTableAccount]);

const tx = new VersionedTransaction(msg);
tx.sign([owner]);

블록해시 신선도

트랜잭션에는 최근 약 150개 슬롯(약 60초) 이내의 블록해시가 포함되어야 합니다. 그 범위를 넘어서면 검증자가 거부합니다. 재시도 루프의 경우 각 재시도마다 새 블록해시를 가져옵니다:
async function sendWithRetry(tx, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
    tx.message.recentBlockhash = blockhash;
    tx.sign([owner]);
    try {
      return await connection.sendRawTransaction(tx.serialize());
    } catch (e) {
      if (i === maxRetries - 1) throw e;
    }
  }
}
우선순위 수수료 에스컬레이션 패턴을 사용한 완전한 재시도는 integration-guides/priority-fee-tuning을 참조하세요.

병렬 실행

Solana는 멀티코어 검증자에서 충돌하지 않는 트랜잭션을 병렬로 실행합니다. 두 트랜잭션이 동일한 계정에 쓰면 충돌합니다. Raydium에 대한 함의:
  • 동일한 풀의 두 스왑은 병렬로 실행될 수 없습니다. 둘 다 풀 상태에 씁니다.
  • 풀 A의 스왑과 풀 B의 스왑은 계정 목록이 겹치지 않으면 병렬로 실행됩니다.
  • 읽기 전용 트랜잭션은 동일한 계정에서 쓰기 프로그램을 절대 차단하지 않습니다(읽기 전용은 자신과 동시에 실행되지만 쓰기와는 동시에 실행되지 않음).
이것이 Solana가 단일 풀 직렬화에도 불구하고 높은 DEX 처리량을 유지할 수 있는 이유입니다.

트랜잭션 확인 수준

트랜잭션을 제출할 때 확인 수준을 선택합니다:
수준대기최종성
processed~400 ms최종화되지 않음. 롤백될 수 있음
confirmed~1 s과반 투표됨
finalized~13 s과반 루트됨
스왑 UX의 경우 confirmed가 표준입니다. 큰 가치를 처리하는 작업(풀 생성, 보상 충전)의 경우 finalized가 더 안전합니다.
await connection.sendAndConfirmTransaction(tx, [owner], {
  commitment: "confirmed",
});

시뮬레이션

Solana는 제출하기 전에 트랜잭션을 시뮬레이션할 수 있습니다:
const sim = await connection.simulateTransaction(tx);
console.log(sim.value.logs);
console.log(sim.value.unitsConsumed);
Raydium SDK는 getBestSwapInfo를 계산할 때 내부적으로 시뮬레이션을 사용하여 선택된 경로가 실제로 성공하는지 확인합니다. 시뮬레이션은 무료가 아닙니다. RPC 용량을 소비하지만 비용을 지불하기 전에 오류를 포착합니다.

참고 자료

출처: