Skip to main content
이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
지원 매트릭스: CPMM은 전송 수수료 민트를 포함하여 Token-2022를 완전히 지원합니다. CLMM은 명시적 SwapV2 계정을 통해 전송 수수료가 있는 Token-2022를 지원합니다. AMM v4는 Token-2022를 전혀 지원하지 않습니다. LaunchLab은 InitializeV2를 통해 클래식 SPL 기본 민트를 생성하지만, Token-2022 기본 민트를 생성하고 선택적으로 TransferFeeConfig를 첨부하는 전용 InitializeWithToken2022 엔드포인트가 있습니다. 인용 측은 두 토큰 프로그램을 모두 허용합니다. products/launchlab/platform-config를 참조하세요. Farm v6은 스테이킹 및 보상 민트 모두에서 Token-2022를 지원합니다.

전송 수수료란

Token-2022는 두 번째 SPL Token 프로그램입니다(TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA → TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb). 확장 기능 중에서 전송 수수료 확장은 토큰 민트에 대한 모든 TransferChecked에서 전송된 금액에서 수수료를 공제합니다. 수수료는 민트 권한자가 지정한 수신자에게 라우팅되며 권한자가 업데이트할 수 있습니다(범위 내에서). 전송 수수료가 있는 민트에는 두 가지 관련 매개변수가 있습니다:
  • transfer_fee_basis_points — 요율(예: 100 = 1%).
  • maximum_fee — 전송당 절대 상한(따라서 막대한 금액을 이동하는 고래도 무제한 수수료를 지불하지 않음).
민트는 동시에 두 개의 활성 전송 수수료 구성을 가질 수 있습니다: “최신” 구성(현재 적용 중)과 “이전” 구성(예정된 폐기). 이것이 “에포크 전환” 설계입니다 — 전송 수수료 변경은 에포크 경계를 넘어 적용되어 진행 중인 거래를 놀라게 하지 않습니다.

스왑에 중요한 이유

풀의 금고는 실제 잔액을 보유합니다. 사용자가 Raydium 스왑을 호출할 때:
  1. 사용자가 amount_in을 풀 금고로 보냅니다. 입금 민트에 전송 수수료가 있으면 금고는 amount_in − fee_in을 받습니다. amount_in이 아닙니다.
  2. 스왑 수학은 금고가 받은 금액에 대해 작동합니다.
  3. 풀이 amount_out을 사용자의 ATA로 보냅니다. 출금 민트에 전송 수수료가 있으면 사용자는 amount_out − fee_out을 받습니다. amount_out이 아닙니다.
스왑 프로그램이 순진하게 원본 amount_in 인수를 사용하면 금고가 프로그램이 생각하는 것보다 적게 받았기 때문에 불변성 검사가 실패합니다. 반대로 아웃바운드 전송 수수료를 빼지 않고 amount_out을 계산하면 사용자는 부족분을 보고 프로그램을 비난합니다. Raydium CPMM 및 CLMM(SwapV2를 통해)은 다음을 수행하여 이를 처리합니다:
  • 스왑 전: in_after_fee = amount_in − transfer_fee_on(amount_in, in_mint)을 계산하고 곡선 수학에서 in_after_fee를 사용합니다.
  • 스왑 후: out_gross = amount_out_from_curve를 계산하고 out_gross를 사용자에게 TransferChecked를 통해 보냅니다. Token-2022 프로그램이 자체적으로 전송 수수료로 감소시킵니다.
사용자의 minAmountOut 슬리피지 한계는 out_gross(풀이 보내는 것)에 대해 확인됩니다. 사용자가 받는 것에 대해서는 아닙니다. 이것이 모든 주요 Solana DEX가 Token-2022를 처리하는 방식이며 중요한 이유는:
  • 풀이 수수료 후를 확인했다면 견적과 실행 사이의 수수료 업데이트로 인해 거래가 되돌려질 것입니다.
  • 수수료 전을 확인하면 실패를 사용자의 대역 외 수수료 변경이 아닌 견적 자체의 품질에 고정합니다.
UI는 사용자에게 “받을 금액”을 표시할 때 예상 Token-2022 전송 수수료를 빼야 합니다.

Token-2022 수수료 계산

SPL Token-2022 프로그램은 결정론적 헬퍼를 노출합니다. Rust에서:
TypeScript에서(@solana/spl-token 사용):

조정된 스왑 공식(CPMM, 정확한 입력)

f_pool을 풀 수수료 요율, f_in을 입금 민트 전송 수수료 요율, max_in을 그 최대 상한, f_out을 출금 민트 전송 수수료 요율, max_out을 그 최대 상한이라고 하겠습니다.
슬리피지 확인: amount_out_gross ≥ min_amount_out(user_receives ≥ min_amount_out이 아님). 사용자의 minAmountOut은 SDK에 의해 expected_gross · (1 − slippage)로 설정됩니다 — “받은” 측이 아닌 “보낸” 측에서 한계를 유지합니다.

조정된 공식(CPMM, 정확한 출력)

SDK는 user_receives = amount_out_exact가 되도록 amount_in을 찾기 위해 반복합니다:
max_in / max_out 상한은 상한에 도달하면 수수료가 더 이상 증가하지 않기 때문에 계산을 비선형으로 만듭니다. SDK의 computeAmountIn / computeAmountOut은 순진한 공식이 상한을 넘을 경우 반복하여 이를 처리합니다.

엣지 케이스

비대칭 수수료(한쪽에만 수수료가 있음)

실제로 흔합니다. 위의 공식은 이미 이를 처리합니다 — 한쪽에 f_in = 0이 있으면 관련 항이 축소됩니다. 프로그램에 특별한 경우는 없습니다.

스왑 중 수수료 업데이트

민트의 전송 수수료가 견적 시간과 실행 시간 사이에 변경되면 스왑은 약간 더 나쁜 경제로 착지하거나(사용자가 슬리피지 허용 범위 내에서 차이를 부담) 되돌려질 것입니다(총 출력이 minAmountOut 아래로 떨어짐). 슬리피지 한계가 이를 흡수합니다. 추가 보호가 필요하지 않습니다.

최대 수수료 상한

거래가 maximum_fee에 도달할 만큼 충분히 크면 수수료가 포화되고 추가 성장은 0입니다. 이는 매우 큰 거래에 대해 유효 요율이 0에 점근하게 하며, 깊이 있는 유동성 부족 시장에서 이상한 가격 곡선을 유발할 수 있습니다. SDK의 computeAmountOut은 이를 고려합니다.

전송 불가능 확장

일부 Token-2022 민트는 NonTransferable 확장을 사용하며, 이는 민트 권한자와의 송수신을 제외한 모든 Transfer 호출을 거부합니다. 그러한 민트는 Raydium 풀에서 전혀 사용할 수 없습니다. CreatePool은 초기화 시 이를 거부합니다.

이자 부담 민트

Token-2022는 또한 시간이 지남에 따라 잔액이 증가하는 것처럼 보이게 하는 InterestBearingConfig 확장을 지원합니다. Raydium의 풀은 원본 금고 잔액을 읽습니다(이자 발생을 무시함). 따라서 이자 부담 민트가 있는 풀에서 LP는 상환할 때 누적된 이자를 순수한 선물로 포착합니다(금고 잔액이 LP 공급 표현보다 빠르게 증가함). 통합자는 이를 문제 없음으로 취급해야 하지만 LP 측을 위해 문서화해야 합니다.

전송 훅

Token-2022의 TransferHook 확장은 모든 전송에서 임의의 CPI를 허용합니다. Raydium CPMM은 이를 지원합니다 — 스왑 명령은 훅 계정을 전달합니다 — 하지만 CU 오버헤드를 추가하고 훅이 잘 작동해야 합니다. CLMM SwapV2도 훅을 지원합니다. AMM v4는 Token-2022를 전혀 지원하지 않으므로 이 질문은 발생하지 않습니다.

작동 예제

CPMM 풀, x = 1_000_000 USDY, y = 1_000_000 USDC, 풀 수수료 0.25%.
  • USDY는 1% 전송 수수료, max_fee = 10_000(6 소수점 자리로 0.01 USDY)을 가집니다.
  • USDC는 전송 수수료가 없습니다.
사용자가 amount_in = 1_000 USDY를 USDC로 스왑합니다(정확한 입력).
≈ 986.03 USDC. 아웃바운드 전송 수수료가 없으므로 사용자는 ≈ 986.03 USDC를 받습니다.

참고 자료

출처: