Solana Token-2022와 스테이블코인
도입
Token-2022를 ERC-20의 "새 버전" 정도로 이해하면 stablecoin 제품 설계가 부족해진다. Solana Token Extensions Program은 mint나 token account에 extension state를 붙여 Transfer Fee, Transfer Hook, Confidential Transfer, Default Account State, Permanent Delegate, Pausable 같은 기능을 제공한다. 기능이 표준 program 안에 들어온 만큼, 결제 제품은 token별 custom contract를 읽는 대신 extension 호환성과 account decoding을 먼저 확인해야 한다.
스테이블코인 팀에게 Token-2022는 양면적이다. compliance, fee, privacy, recovery 같은 요구를 표준화된 방식으로 다룰 수 있지만, wallet, custody, indexer, checkout amount 표시가 extension별로 달라질 수 있다. 이 레슨은 "무슨 extension이 있는가"보다 "결제 제품에서 어떤 extension을 product dependency로 둬도 되는가"를 판단하는 데 초점을 둔다.
학습 목표
- Token-2022 extension이 결제 자산 설계에 주는 선택지를 이해한다.
- transfer fee, confidential transfer, metadata 등 extension 위험을 평가한다.
개념 설명
개념 읽기
Token-2022 extension이 결제 자산 설계에 주는 선택지를 이해한다.
실패 상태 확인
숨길 데이터와 공개할 데이터가 분리되는가
실습 산출물 작성
Solana Token-2022와 스테이블코인 이해 점검
완료 기준 대조
Token extension 위험을 설명했다.
extension은 mint/account state의 일부다
Solana 공식 문서는 Token Extensions Program이 token mint 또는 token account에 optional extension을 추가하는 방식이라고 설명한다. extension은 대부분 account 초기화 시점에 계획해야 하며, 일부 extension은 서로 동시에 사용할 수 없다. 즉 제품팀은 launch 후 "필요하면 나중에 붙이면 된다"라고 가정하면 안 된다.
| Extension | stablecoin/RWA 연결 | 제품 설계에서 확인할 것 |
|---|---|---|
| Transfer Hook | KYC, allowlist, compliance rule | hook program, extra account list, hook failure UX |
| Confidential Transfer | 금액 privacy, 기관 결제 | auditor key, proof flow, availability, reconciliation |
| Permanent Delegate | freeze, seize, recovery, compliance | governance, disclosure, emergency procedure |
| Default Account State | 새 token account를 기본 frozen으로 생성 | onboarding, thaw authority, merchant setup |
| Transfer Fee | issuer fee, settlement fee | invoice amount와 net received amount 분리 |
| Pausable | emergency stop | pause 권한, pause 범위, user-facing notice |
| Interest Bearing | yield-bearing display | 회계 처리, UI amount, 세무/약관 검토 |
ERC-20과 비교하면 어디가 바뀌는가
| 항목 | EVM ERC-20 | Solana Token Extensions |
|---|---|---|
| 기능 추가 | token contract 코드에 직접 구현 | mint/account extension으로 구성 |
| compliance hook | custom _beforeTokenTransfer 또는 policy contract | Transfer Hook extension과 external program |
| 계정 모델 | balanceOf(address) mapping | mint, token account, owner, program 분리 |
| 권한 | role/admin mapping | mint authority, freeze authority, extension authority |
| integration risk | token별 구현 차이 | extension 지원 여부와 TLV/account decoding |
이 비교에서 핵심은 integration risk의 위치다. EVM에서는 token contract별 구현 차이를 읽고 audit한다. Token-2022에서는 어떤 extension이 활성화되어 있는지, 해당 extension을 SDK와 indexer가 decoding할 수 있는지, wallet이 사용자에게 제대로 표시하는지를 확인한다.
extension compatibility matrix
결제 자산 후보가 Token-2022 mint라면 다음 표를 채운 뒤에만 production 지원 여부를 결정한다.
| 체크 항목 | 질문 | Go 기준 |
|---|---|---|
| Program ID | legacy SPL Token인가 Token-2022인가 | allowlist와 decoder가 program ID를 분리한다. |
| Extension list | mint/account에 어떤 extension이 있는가 | unsupported extension은 block 또는 manual review로 보낸다. |
| Transfer Fee | 송금액과 수령액이 달라지는가 | invoice amount, fee amount, net received amount를 모두 저장한다. |
| Transfer Hook | extra account list가 필요한가 | SDK가 hook accounts를 구성하고 simulation failure를 표시한다. |
| Default State | 새 account가 frozen으로 시작하는가 | onboarding에서 thaw 권한과 실패 메시지를 제공한다. |
| Confidential Transfer | 금액 privacy가 필요한가 | availability, auditor model, reconciliation plan이 문서화되어 있다. |
| Permanent Delegate | 강제 이전/회수 권한이 있는가 | 사용자 disclosure와 admin runbook이 있다. |
Confidential Transfer는 product dependency로 두기 전에 분리해서 본다
2026-05-15에 확인한 Solana 공식 문서는 ZK ElGamal Program이 보안 감사 중이라 mainnet/devnet에서 일시적으로 disabled 상태이며, confidential transfer extension은 현재 사용할 수 없다고 안내한다. 따라서 강의에서는 개념 자체와 production dependency를 분리한다.
Confidential Transfer 개념에서 배울 점은 여전히 중요하다. 전송 금액과 balance만 비공개이고 token account address는 공개라는 점, auditor disclosure가 필요할 수 있다는 점, deposit/apply/transfer/apply/withdraw처럼 일반 transfer보다 긴 상태 흐름이 있다는 점은 privacy stablecoin 설계에 직접 연결된다. 다만 캡스톤에서는 이 기능을 "roadmap-only" 또는 "research dependency"로 표시하고, 지금 결제 시스템의 필수 조건으로 두지 않는다.
코드로 확인하기
Token-2022는 mint에 extension을 붙여 token 동작을 확장한다. stablecoin 설계에서는 transfer hook, confidential transfer, metadata pointer 같은 extension이 운영과 UX에 어떤 조건을 추가하는지 읽어야 한다.
클라이언트mint extension 계획을 명시적으로 구성
type Token2022ExtensionPlan = { transferHookProgram?: string; metadataPointer?: string; confidentialTransfer: boolean; defaultAccountState: "initialized" | "frozen";};function assertSupportedExtensions(plan: Token2022ExtensionPlan) { if (plan.confidentialTransfer && !plan.transferHookProgram) { throw new Error("confidential transfer needs a reviewable transfer hook policy"); } if (plan.defaultAccountState === "frozen" && !plan.metadataPointer) { throw new Error("frozen-by-default mint needs account onboarding metadata"); }}extension은 기능 토글이 아니다. 각 extension은 wallet 지원, indexer 파싱, 고객지원 시나리오를 바꾼다.
컨트랙트transfer hook에서 merchant policy 확인
pub fn execute_transfer_hook(ctx: Context<TransferHook>, amount: u64) -> Result<()> { let merchant_policy = &ctx.accounts.merchant_policy; require!(merchant_policy.enabled, HookError::MerchantDisabled); require!(amount <= merchant_policy.max_transfer_amount, HookError::AmountTooLarge); require_keys_eq!(merchant_policy.accepted_mint, ctx.accounts.mint.key()); emit!(TransferPolicyChecked { merchant: merchant_policy.merchant, amount }); Ok(())}transfer hook은 token 전송마다 호출될 수 있으므로 가벼워야 한다. 복잡한 KYC 판정은 사전에 account state로 반영하고, hook은 이미 계산된 정책을 확인하는 편이 안전하다.
강의 포인트
Token-2022 학습은 extension 이름 암기가 아니라 운영 영향 분류다. 다음 네 가지 질문에 답할 수 있어야 한다.
| 질문 | 놓치면 생기는 문제 |
|---|---|
| 송금액과 merchant 수령액이 같은가 | Transfer Fee 때문에 invoice reconciliation이 틀어진다. |
| transfer에 추가 account가 필요한가 | Transfer Hook에서 transaction assembly가 실패한다. |
| token account가 frozen 또는 paused 상태일 수 있는가 | 사용자는 잔고가 있어도 결제를 못 한다. |
| privacy extension을 지금 쓸 수 있는가 | roadmap 기능을 production 의존성으로 잡아 일정과 리스크가 왜곡된다. |
실무 예시
100 USDC invoice를 Transfer Fee extension이 있는 Token-2022 자산으로 받는다고 가정한다. 결제 DB에는 단일 amount만 두면 부족하다.
| 필드 | 예시 | 이유 |
|---|---|---|
invoiceAmount | 100.00 | 사용자가 결제해야 한다고 본 금액 |
transferAmount | 100.00 | transaction에 들어간 token amount |
withheldFeeAmount | 0.20 | extension이 보류하거나 징수한 fee |
netReceivedAmount | 99.80 | merchant가 실제 정산 받을 금액 |
feePolicyVersion | token2022-fee-v1 | 수수료 표시와 분쟁 처리를 위한 근거 |
이 예시는 UI에도 영향을 준다. 결제 화면에서 "100 USDC 결제"만 보여줄지, "merchant 수령액 99.80 USDC"까지 보여줄지 정책이 필요하다. 회계 시스템은 user-facing amount와 settlement amount를 분리해야 한다.
흔한 오해와 실패 시나리오
| 오해 | 실패 장면 | 바로잡는 기준 |
|---|---|---|
| Token-2022 mint는 SPL Token처럼 전송하면 된다. | extension state를 decoding하지 못해 fee, hook, frozen state를 놓친다. | mint/account extension list를 결제 전 검증한다. |
| Transfer Hook은 compliance만 추가하므로 제품 영향이 작다. | extra account list 누락으로 checkout transaction assembly가 실패한다. | hook program과 required accounts를 adapter contract처럼 관리한다. |
| Confidential Transfer를 쓰면 모든 것이 비공개가 된다. | account address는 공개인데 amount만 숨겨져 privacy claim이 과장된다. | 공개/비공개 데이터 범위를 threat model에 적는다. |
| Permanent Delegate는 issuer 운영 기능일 뿐이다. | 강제 이전 권한이 사용자 disclosure와 governance review 없이 production에 들어간다. | admin 권한, audit log, emergency approval을 문서화한다. |
실습 과제
- Solana Token-2022와 스테이블코인 이해 점검: 후보 mint 하나를 고르고 extension list, wallet/indexer/custody 지원, Transfer Fee 표시 정책을 compatibility matrix로 정리한다.
- Solana Token-2022와 스테이블코인 적용 과제: Transfer Hook, Transfer Fee, Confidential Transfer를 각각
production-ready,manual-review,roadmap-only중 하나로 분류하고 근거를 적는다. Confidential Transfer는 2026-05-15 기준 availability warning을 반영한다.
완료 기준
- Token extension 위험을 account decoding, wallet/custody 지원, 운영 권한 관점에서 설명했다.
- extension compatibility matrix를 작성했다.
- Transfer Fee가 있는 결제의 invoice amount, fee amount, net received amount 표시 정책을 정의했다.
근거 자료
- Solana Token2022 스테이블코인: 07-비EVM/04-Solana-Token2022-스테이블코인.md
- Solana Token Extensions Documentation: https://solana.com/docs/tokens/extensions
- Solana Confidential Transfer Documentation: https://solana.com/docs/tokens/extensions/confidential-transfer