ERC-3643 허가형 토큰과 identity
도입
ERC-3643은 regulated asset과 RWA를 위한 permissioned token 모델이다. 일반 ERC-20은 주소와 balance만 있으면 전송이 가능하지만, RWA token은 누가 보유할 수 있는지, 어떤 조건에서 전송할 수 있는지, 자격이 만료되면 어떻게 막을지를 함께 설계해야 한다.
이 수업의 핵심은 token transfer를 compliance decision으로 읽는 것이다. 사용자가 token을 갖고 싶어도 identity registry와 compliance contract가 허용하지 않으면 mint, transfer, secondary sale이 실패해야 한다. 개발자는 실패 이유를 사용자에게 설명하면서도 KYC 정보와 개인정보를 과도하게 온체인에 노출하지 않아야 한다.
학습 목표
- 허가형 토큰의 identity, compliance, transfer restriction을 설명한다.
- KYC/eligibility 상태를 온체인 전송 정책과 연결한다.
개념 설명
IdentityIssued
허가형 토큰의 identity, compliance, transfer restriction을 설명한다.
TransferPreflight
share와 asset 권리가 분리되는가
ClaimExpiring
비동기 상환 상태가 보이는가
RestrictionEvidence
ERC-3643 허가형 토큰과 identity 이해 점검
ERC-3643 구조는 token contract 하나로 끝나지 않는다. identity registry, trusted issuer, claim, compliance rule, agent 권한이 함께 작동한다.
| 구성 요소 | 역할 | 설계 질문 |
|---|---|---|
| Token | permissioned balance와 transfer entry point | 모든 이동 경로에서 compliance check가 호출되는가 |
| Identity Registry | 주소와 investor identity 연결 | identity 등록, 갱신, revoke 절차가 있는가 |
| Claim Issuer | KYC, accreditation, jurisdiction claim 발급 | issuer trust와 claim 만료를 어떻게 검증하는가 |
| Compliance Contract | transfer 가능 조건 검사 | country cap, holder cap, lockup, sanction rule을 어떻게 표현하는가 |
| Agent | issuer 대리 운영 권한 | forced transfer, recovery, freeze 권한이 통제되는가 |
ERC-20과 비교하면 차이가 분명하다.
| 항목 | ERC-20 | ERC-3643 |
|---|---|---|
| 전송 조건 | balance와 allowance 중심 | sender/receiver identity와 compliance 중심 |
| 보유자 자격 | 주소만 있으면 가능 | verified identity와 valid claim 필요 |
| 유동성 | permissionless market에 적합 | allowlisted market 또는 broker/dealer flow 필요 |
| DeFi 조합성 | 높음 | contract holder도 eligibility를 받아야 함 |
| 실패 설명 | allowance, balance, pause 정도 | KYC, jurisdiction, cap, claim expiry 등 |
코드로 확인하기
permissioned token은 transfer 함수 하나에 법적·운영적 조건이 모인다. 강의에서는 이 조건을 "허용 목록" 정도로 이해하지 말고, identity 상태와 token 상태가 함께 통과해야 하는 정책으로 본다.
컨트랙트ERC-3643식 전송 전 compliance gate
function _beforeTokenTransfer(address from, address to, uint256 amount) internal view { if (paused()) revert TokenPaused(); if (frozen[from] || frozen[to]) revert FrozenAccount(); if (!identityRegistry.isVerified(to)) revert ReceiverNotVerified(to); bool allowed = compliance.canTransfer(from, to, amount); if (!allowed) revert ComplianceRejected(from, to, amount);}function transfer(address to, uint256 amount) public returns (bool) { _beforeTokenTransfer(msg.sender, to, amount); _transfer(msg.sender, to, amount); return true;}코드에서 봐야 할 지점은 transfer가 실패하는 이유를 분리해 남기는 부분이다. KYC 미완료, freeze, pause, concentration limit은 모두 사용자에게 다른 안내와 운영 조치를 요구한다.
백엔드전송 전 사전 검증 응답
type TransferPreflight = { fromVerified: boolean; toVerified: boolean; frozen: boolean; limitRemaining: bigint;};function explainTransferBlock(preflight: TransferPreflight, amount: bigint) { if (!preflight.fromVerified) return "sender_identity_missing"; if (!preflight.toVerified) return "receiver_identity_missing"; if (preflight.frozen) return "account_frozen"; if (preflight.limitRemaining < amount) return "investor_limit_exceeded"; return "ok";}프론트엔드는 이 preflight 결과를 transaction 전 단계에서 보여준다. 사용자가 서명한 뒤 revert를 보는 구조는 permissioned asset UX로는 적합하지 않다.
클라이언트전송 버튼 상태와 조치 안내
type TransferBlockReason = | "sender_identity_missing" | "receiver_identity_missing" | "account_frozen" | "investor_limit_exceeded" | "ok";function transferCta(reason: TransferBlockReason) { const copy = { sender_identity_missing: "보내는 계정의 투자자 인증을 먼저 완료해야 합니다.", receiver_identity_missing: "받는 계정이 이 자산을 보유할 자격을 갖추지 않았습니다.", account_frozen: "계정 제한 상태라 전송할 수 없습니다. 지원팀 확인이 필요합니다.", investor_limit_exceeded: "투자자 한도를 초과합니다. 일부 금액만 전송하거나 한도 갱신이 필요합니다.", ok: "전송 가능" } satisfies Record<TransferBlockReason, string>; return { disabled: reason !== "ok", label: copy[reason] };}permissioned token의 UX는 "revert가 났다"가 아니라 "어떤 자격이 부족한가"를 알려야 한다. 이 코드는 compliance reason을 사용자가 취할 수 있는 행동으로 바꾼다.
인덱서claim 만료와 전송 실패 감시
select holder, claim_type, expires_atfrom identity_claimswhere expires_at < now() + interval '14 days'order by expires_at asc;claim expiry를 미리 감시하지 않으면 정상 holder가 갑자기 전송 실패를 겪는다. permissioned asset 운영자는 실패 transaction이 아니라 만료 예정 claim을 먼저 봐야 한다.
강의 포인트
| 관점 | 확인할 질문 | 증거로 남길 것 |
|---|---|---|
| identity lifecycle | onboarding, claim issuance, expiry, revocation이 정의됐는가 | identity flow diagram |
| transfer gate | mint, transfer, forced transfer, recovery에서 compliance가 일관되게 적용되는가 | transfer restriction matrix |
| privacy boundary | 어떤 정보는 온체인 proof로, 어떤 정보는 offchain record로 남길 것인가 | privacy boundary note |
| market access | secondary market과 DeFi contract가 holder 자격을 얻을 수 있는가 | eligible holder policy |
| stablecoin reserve | permissioned RWA를 reserve로 보유할 때 liquidation 병목이 무엇인가 | liquidation risk memo |
실무 예시
tokenized treasury를 stablecoin issuer reserve로 보유한다고 가정한다. issuer는 qualified investor일 수 있지만, DeFi lending pool이나 liquidation contract는 eligible holder가 아닐 수 있다.
| 상황 | 위험 | 설계 대응 |
|---|---|---|
| issuer가 RWA token을 팔아 현금화해야 함 | buyer allowlist가 좁아 liquidation이 지연됨 | liquidity provider와 redemption channel을 사전 정의 |
| claim이 만료된 holder가 transfer 시도 | secondary sale이 실패함 | claim expiry alert와 renewal UX 제공 |
| DeFi contract가 collateral을 받음 | contract가 identity를 갖지 못해 transfer 실패 | adapter 또는 custody model 검토 |
| forced transfer 권한 존재 | 운영자가 임의 이전할 수 있는 governance risk | multisig, timelock, event monitoring 적용 |
흔한 오해와 실패 시나리오
| 오해 | 실제로 확인할 것 |
|---|---|
| permissioned token도 ERC-20처럼 아무 pool에 넣을 수 있다고 본다. | contract holder도 identity/compliance 조건을 통과해야 한다. |
| KYC 완료를 영구 상태로 본다. | claim expiry, jurisdiction change, revocation policy가 필요하다. |
| 전송 실패를 단순 "not allowed"로 보여준다. | 사용자가 조치할 수 있도록 claim expired, receiver not eligible, cap exceeded 같은 reason을 분리한다. |
| privacy와 compliance를 같은 장부에 넣는다. | 온체인에는 필요한 proof와 status만 두고 민감 정보는 offchain boundary를 둔다. |
| forced transfer 권한을 recovery 기능으로만 본다. | issuer/agent 권한은 abuse와 incident response 양쪽을 모두 검토해야 한다. |
실습 과제
- ERC-3643 허가형 토큰과 identity 이해 점검: investor onboarding, claim issuance, transfer, claim expiry, revocation, recovery flow를 순서도로 그린다.
- 전송 제한 정책 작성: sender/receiver eligibility, country cap, holder cap, lockup, frozen status, forced transfer 조건을 표로 만든다.
- privacy boundary 정의: 온체인에 남길 status와 offchain에 보관할 KYC detail을 분리한다.
- reserve liquidation memo: permissioned RWA token을 stablecoin reserve로 보유할 때 market access와 emergency liquidation 경로를 작성한다.
완료 기준
- identity registry 역할을 설명했다.
- 전송 제한 정책을 작성했다.
- privacy boundary를 정의했다.
근거 자료
- ERC3643 허가형 토큰: 04-RWA-토큰화/03-ERC3643-허가형-토큰.md
- ERC-3643: T-REX Permissioned Tokens: https://eips.ethereum.org/EIPS/eip-3643