読了時間:10分
概要
ERC-3643は、パーミッション型トークン向けのイーサリアム・トークン規格です。パーミッション型トークンとは、KYC/AML、投資家の適格性、管轄区域の要件など、あらかじめ定義されたコンプライアンス規則を満たす主体のみが保有および譲渡できるトークンを指します。この規格は、資産の保有者が誰であるか、またその者が当該資産を保有または取引する権限を有しているかどうかを把握する必要がある、規制対象の資産向けに設計されています。
当初はT-REX(Token for Regulated EXchanges)として知られ、Tokenyによって立ち上げられたこのプロジェクトは、現在、 ERC-3643 として正式に規定され、実世界資産(RWA)の許可型トークン化の標準化に注力するERC-3643協会によって管理されています。
実際には、ERC-3643 は一連のスマートコントラクトであり、これらが連携して以下を実装しています:
- オンチェーンIDおよびクレーム(via ONCHAINID経由)
- 適格保有者向けのID登録機関
- モジュール式のコンプライアンス規則
- 転送時にコンプライアンスを強制しつつ、ERC-20との互換性を維持するトークン契約
ERC-3643は、身元確認およびコンプライアンスに関するルールをトークン規格に直接組み込んでいるため、有価証券、不動産、ファンド、その他の規制対象金融商品といった実物資産(RWA)のトークン化に最適な選択肢となります。
主な業務内容
- 通常のERC-20と比較して、ERC-3643がどのような問題を解決しようとしているのかを理解する
- 全体的なアーキテクチャ(コア契約、レジストリ、およびロール)について学ぶ
- オンチェーン上でアイデンティティとコンプライアンスがどのように適用されているかをご覧ください
- ERC-3643システムにおける送金の仕組みについて解説します
- 導入、役割、およびRWAの一般的な活用事例の概要を把握する
必要なもの
- Solidityの基本的な知識と ERC-20
- EVMの EVMの理解
- KYC/AMLおよび規制に関する高度な知識
- に関する認識 EIP-173 (契約の所有権)およびロールベースのアクセス制御パターンに関する認識
本ガイドに掲載されているコード例は監査を受けておらず、概念の理解のみを目的として提供されています。徹底的な検証、テスト、および独立したセキュリティ監査を行わない限り、本番環境でこれらを使用しないでください。
ERC-3643が解決する問題
本題に入る前に、まず背景を整理しておきましょう。標準的なERC-20トークンはパーミッションレスです。誰でも送信でき、誰でも受け取ることができ、どのアドレスでも保有することができます。これは、次のような資産にとっての特徴であり、 DAI または UNI.
しかし、トークン化された有価証券(企業の株式)や分割所有権化された不動産といった実世界の資産を扱う場合、これが問題となります。実世界の規制では、誰が資産を保有しているかを把握し、以下の基準に基づいて譲渡を制限することが求められています:
- 本人確認:保有者はKYCを通過していますか?
- 管轄:受取人は制裁対象国に所在していますか?
- 適格性:保有者は、この有価証券を購入することが認められている「適格投資家」ですか?
- ロックアップ:その資産は、売却できない「ロックアップ」期間中ですか?
ERC-3643は、当初T-REX(Token for Regulated EXchanges)として知られていましたが、これらの規則をオンチェーンで実現するために構築されました。これは、ERC-20互換トークンに「コンプライアンス対応機能」を持たせる一連のスマートコントラクトです。
標準要件
大まかに言えば、ERC-3643の実装では以下を提供すべきです:
-
互換性と表面
- ERC-20との互換性を維持する
- 振替に関する標準的な事前チェックを公開する(
canTransfer) - 規制対象となるフローに必要なバッチ処理および管理機能をサポートする
-
アイデンティティとコンプライアンス
- オンチェーンIDシステム(例:ONCHAINID)を統合する
- 転送、ミント、バーンにはコンプライアンス層を使用する
-
操作と機能
- 一時停止およびフリーズのサポート(グローバル、アドレス単位、および部分的なフリーズ)
- 機密性の高い操作(強制送金、復旧、発行/焼却)には、EIP-173の所有権とエージェントの役割を併用する
ERC-3643のアーキテクチャ
ERC-3643は意図的にモジュール式に設計されています。すべてを単一のモノリシックなトークン契約にまとめるのではなく、複数の契約に機能を分散させています。
一目でわかるように、主な構成要素は以下の通りです:
| コンポーネント | 概要 |
|---|---|
| ONCHAINID | 信頼できる発行者によって発行され、ユーザーに対する検証可能な権利を保持する、独立したアイデンティティ契約(ERC-734/735に基づく)。 |
| 信頼できる発行者登録簿 | ユーザーの身元に関する主張を追加することが信頼されているアドレス(例:KYCプロバイダー)の一覧 |
| クレームトピック登録簿 | 必須のクレームタイプのリスト(例:KYC認証済み、認定投資家など)。 |
| IDレジストリ | ウォレットをONCHAINIDおよび国に紐付け、次のような検証情報を公開します。 isVerified. |
| コンプライアンス契約 | オファーおよび譲渡に関するルールを定義し、譲渡の前後で参照される。 |
| 許可型トークン(T-REX) | ERC-20互換のトークンです。このトークンは、Identity RegistryおよびCompliance契約への参照情報を保持しており、転送を行う前にこれらの契約を参照します。 |
ONCHAINID
ONCHAINIDは、鍵と検証可能なクレームを記録する汎用IDコントラクトです。
クレームの例としては、次のようなものがあります:
- アドレス X はプロバイダー Y による KYC 審査に合格しました
- この投資家は、管轄区域Zにおいて認定投資家として登録されています。
これらのクレームは、信頼できる発行者(KYCプロバイダーや規制対象機関など)によって発行されます。この契約では、プライバシー保護のため、個人を特定できる情報(PII)を直接保存せず、参照情報とハッシュ値を保存しています。
複数のウォレットを同じ基盤となるIDに関連付けることができ、コード内ではこのIDは通常、次のように参照されます。 アイデンティティ. ONCHAINID は、 コンプライアンスに関連する事実の根拠.
信頼できる発行者登録簿
「信頼できる発行者レジストリ」は、特定のトークンについてどのクレーム発行者が信頼されているか、また各発行者がどのクレームトピックに署名できるかを追跡します。
たとえば、次のようなものを信頼するかもしれません:
- 特定のKYCプロバイダーは、
KYC_VALIDATEDトピック。 - 規制対象事業者(対象分野:)
認定投資家.
そのトークンのコンプライアンスチェックにおいては、これらの発行者による主張のみが有効とみなされます。
クレームトピック登録簿
「クレーム・トピック・レジストリ」は、トークンを保有する上で重要なクレームの種類を定義しており、その例としては次のようなものがあります:
KYC_VALIDATED認定投資家NOT_IN_RESTRICTED_COUNTRY制裁リスト未掲載
とともに、 信頼できる発行者登録簿, そこで定義されているのは どの請求項が必要か そして それらを発行できる者.
IDレジストリ
アイデンティティ・レジストリは、トークン保有者にとってのゲートキーパーです:
- ホワイトリストに登録された各ウォレットのONCHAINIDを保存します
- 暴露する
isVerified(address) - 認証済みの身元のみが登録されたままとなるよう強制する
通常、それは以下に依存しています IdentityRegistryStorage これにより、複数のトークンが、トークン固有の登録情報を維持しつつ、1つのホワイトリストを共有できるようになります。KYC完了後、投資家はONCHAINIDをリンクまたはデプロイし、信頼できる発行者から必要なクレームを受け取り、そのウォレットは国コード(ISO-3166の数値)とともに登録されます。
コンプライアンス契約
コンプライアンス契約には、募集規則および譲渡制限が規定されています。例:
- 国ごとの投資家数の上限。
- 投資家1人あたりの最大ポジションサイズ。
- 管轄区域の許可/拒否リスト。
- ロックアップや権利確定といった、期間に基づくルール。
標準インターフェース面:
関数 canTransfer(address from, 宛先 宛先, uint256 amount) 外部 ビュー 返り値 (bool);
function transferred(address from, 宛先 宛先, uint256 amount) external;
関数 作成(address to, uint256 amount) external;
function destroyed(address from, uint256 amount) external;
トークン契約は、コンプライアンス契約を利用して以下のことを行います:
- 転送が許可されているかどうかを事前に確認する (
canTransfer). - 転送、発行、および焼却が行われた後、コンプライアンスロジックに通知する(
転送された,作成,破壊された) これにより、内部状態(大文字化、カウンタなど)を同期させることができます。
許可型トークン(T-REX)
このトークンは標準のERC-20機能を実装しており、以下の参照を保持しています。 IdentityRegistry そして、その コンプライアンス 契約。トークンを無闇に送信するのではなく、各転送に対していくつかの追加チェックを行い、その転送が許可されていることを確認します。転送を次のようにラップします:
- 一時停止/フリーズチェック
- コンプライアンスチェック
- 転送後のフック (
転送された)
代表的な拡張機能には、次のようなものがあります:
- 強制的な転送とトークンの復旧
- 一時停止/フリーズ(グローバルおよびアドレス単位)
- 一部凍結(残高の一部のみ利用可能)
- バッチ処理
RWAトークンの送金仕組み
それでは、ERC-3643トークンの転送がどのように行われるのか、手順を追って見ていきましょう。
ステップ1:ユーザーが送金を開始する
あるユーザー(アリス)がトークンの 転送 または transferFrom いつものように、トークンを新しいアドレス(Bob)に転送するには:
トークン.transfer(bob.アドレス, 金額);
トークン.transferFrom(from, bob.アドレス, 金額); // 手当が使用された場合
ステップ2:資格審査
その トークン このスマートコントラクトはトークンを移動させません。まず、 IDレジストリ. その論理は通常、以下の通りです:
- トークンが一時停止されているか、いずれかのアドレスが凍結されているかを確認します
- 受信機が以下の状態であることを確認します。 登録済み また、必要なクレームが
IdentityRegistry電話でisVerified()関数
多くの実装では、トークンは
identityRegistry.isVerified(...)直接実行し、その後呼び出しますcompliance.canTransfer(...). 他のケースでは、適格性チェックは内部に組み込まれており、canTransferそれ自体。重要なのは、両方が 資格要件 そして コンプライアンス規則 残高が移動する前に、これらのルールが適用されます。
ステップ3:コンプライアンス評価
資格審査の後、 トークン 契約は2番目の確認段階に進みます: compliance.canTransfer(alice.address, bob.address, amount).
その コンプライアンス 契約は、そのモジュール型ロジックを検証して、転送が許可されており、いかなるルールにも違反していないかどうかを判断します。
コンプライアンス契約では、以下のルールを評価する場合があります:
- グローバルな上限(例:管轄区域ごとの保有者数など)
- 投資家ごとおよび国ごとの建玉制限
- タイムウィンドウ、ロックアップ、および権利確定
- そのトークンに対して設定されたカスタムモジュール
いかなる規則にも違反があった場合、 canTransfer リターン false そうすれば、トークンは元の状態に戻るはずです。
ステップ4:転送
すべてのチェックに合格した場合、送金は通常のERC-20送金と同様に実行されます。その後、 トークン 呼び出し compliance.transferred(from, to, amount) 今後のチェックに備えて、コンプライアンスの状態を更新するため。
Mintでは、 トークン 呼び出し compliance.created(to, amount), そして実行時には、以下を呼び出します compliance.destroyed(from, amount) つまり、コンプライアンス・エンジンは供給状況の変化も追跡するのです。
請求書は信頼できる発行者によって署名され、ONCHAINIDを介して保存されるため、適格性に関する検証可能な監査証跡を維持することができます。
監査可能な記録が残されています:
- 誰がいつ何を所持していたか
- どのような請求および規則により、譲渡が可能となったのか
- レジストリおよびコンプライアンス・モジュールにおけるガバナンスの経時的な変化
役割と権限
ERC-3643では、(EIP-173に基づく)オーナーと、機密性の高い機能を操作できるエージェントのアドレスとを区別しています。エージェントの役割は次のように標準化されています:
interface IAgentRole {
event AgentAdded(address indexed agent);
event AgentRemoved(address indexed agent);
function addAgent(address agent) external;
function removeAgent(address agent) external;
function isAgent(address agent) external view returns (bool);
}
所有者は、エージェントおよび高レベルの設定を管理します。エージェントは、実装に応じて、フリーズ、強制移管、発行/焼却、バッチ処理などのアクションを実行します。
開発者向けの主要インターフェース
ERC-3643の実装によって明らかになった主要な標準化インターフェース:
- ERC3643 トークン
- IDレジストリ
- IDレジストリのストレージ
- コンプライアンス
- 信頼できる発行者
- 請求の項目
interface IERC3643 is IERC20 {
// getters
function onchainID() external view returns (address);
function identityRegistry() external view returns (IIdentityRegistry);
function compliance() external view returns (ICompliance);
function paused() external view returns (bool);
function isFrozen(address user) external view returns (bool);
function getFrozenTokens(address user) external view returns (uint256);
// admin
function pause() external;
function unpause() external;
function setAddressFrozen(address user, bool freeze) external;
function freezePartialTokens(address user, uint256 amount) external;
function unfreezePartialTokens(address user, uint256 amount) external;
function setIdentityRegistry(address identityRegistry) external;
function setCompliance(address compliance) external;
// lifecycle
function forcedTransfer(address from, address to, uint256 amount) external returns (bool);
function mint(address to, uint256 amount) external;
function burn(address user, uint256 amount) external;
function recoveryAddress(address lostWallet, address newWallet, address investorOnchainID) external returns (bool);
// batch helpers
function batchTransfer(address[] calldata toList, uint256[] calldata amounts) external;
}
interface IIdentityRegistry {
// wiring
function setIdentityRegistryStorage(address storageAddr) external;
function setClaimTopicsRegistry(address topics) external;
function setTrustedIssuersRegistry(address issuers) external;
// actions
function registerIdentity(address user, IIdentity id, uint16 country) external;
function deleteIdentity(address user) external;
function updateCountry(address user, uint16 country) external;
function updateIdentity(address user, IIdentity id) external;
// reads
function isVerified(address user) external view returns (bool);
function identity(address user) external view returns (IIdentity);
function investorCountry(address user) external view returns (uint16);
}
interface IIdentityRegistryStorage {
function storedIdentity(address user) external view returns (IIdentity);
function storedInvestorCountry(address user) external view returns (uint16);
function addIdentityToStorage(address user, IIdentity id, uint16 country) external;
function removeIdentityFromStorage(address user) external;
function modifyStoredInvestorCountry(address user, uint16 country) external;
function modifyStoredIdentity(address user, IIdentity id) external;
function bindIdentityRegistry(address identityRegistry) external;
function unbindIdentityRegistry(address identityRegistry) external;
function linkedIdentityRegistries() external view returns (address[] memory);
}
interface ICompliance {
function canTransfer(address from, address to, uint256 amount) external view returns (bool);
function transferred(address from, address to, uint256 amount) external;
function created(address to, uint256 amount) external;
function destroyed(address from, uint256 amount) external;
}
interface ITrustedIssuersRegistry {
function addTrustedIssuer(IClaimIssuer issuer, uint[] calldata claimTopics) external;
function removeTrustedIssuer(IClaimIssuer issuer) external;
function updateIssuerClaimTopics(IClaimIssuer issuer, uint[] calldata claimTopics) external;
function getTrustedIssuers() external view returns (IClaimIssuer[] memory);
function isTrustedIssuer(address issuer) external view returns (bool);
function getTrustedIssuerClaimTopics(IClaimIssuer issuer) external view returns (uint[] memory);
function getTrustedIssuersForClaimTopic(uint256 claimTopic) external view returns (IClaimIssuer[] memory);
function hasClaimTopic(address issuer, uint claimTopic) external view returns (bool);
}
interface IClaimTopicsRegistry {
function addClaimTopic(uint256 claimTopic) external;
function removeClaimTopic(uint256 claimTopic) external;
function getClaimTopics() external view returns (uint256[] memory);
}
デザインのまとめ
ERC-3643トークンの展開には、少なくとも以下の手順が含まれます:
- レジストリのデプロイ:
クレームトピックレジストリ,信頼できる発行者登録簿,IdentityRegistryStorage,IdentityRegistry. - トピックと発行者を設定する:クレームのトピックと、サポートされているトピックを指定した信頼できる発行者を追加します。
- ストレージをIDレジストリにバインドし、IDレジストリにレジストリを設定します。
- デプロイ
コンプライアンスそして、デプロイ後にそれをトークンに紐付けます。 - 以下の参照先を指定してトークンをデプロイします。
IdentityRegistryそしてコンプライアンス. - 「オーナー」と「エージェント」の役割を設定し、機密性の高い機能をエージェントに限定します。
- 投資家の身元を登録する(
住所,ONCHAINID,国) 識別子レジストリ内。 - 使用方法
ミント供給量を配分し、ミント/バーンの決定を確実に行う作成/破棄.
一般的な利用例
- トークン化された私募ファンド/VC/PE:認定投資家または機関投資家のみに限定する
- セキュリティ・トークン・オファリング(STO):管轄区域の制限、保有者数の上限、ロックアップ期間などを適用する。
- トークン化された不動産:適格な投資家のみが不動産の持分所有権を保有できるようにする
- 規制対象の取引所:すべての売買注文がオンチェーンで検証される、規制に準拠した流通市場を構築する
ERC-3643トークンはERC-20との互換性を維持しているため、ウォレット、カストディアン、取引所(許可されている範囲での集中型または分散型)、およびポートフォリオ・分析ツールと連携することが可能です。ただし、それらのプラットフォームが、当該資産の許可型という性質(例えば、コンプライアンス上の理由による送金取り消しへの対応など)に対応できることが条件となります。
今後の予定
ここから、以下の操作が可能です:
-
ERC-3643のホワイトペーパーと仕様書の全文をご覧ください
この概要の範囲を超える、「デリバリー・ヴァーサス・デリバリー(DvD)」や取引所との連携、アップグレード可能性のパターンといったエッジケースについて詳しく掘り下げてみましょう。
-
リファレンス実装を詳しく見る
ERC-3643 / T-REX リポジトリをクローンし、レジストリとトークンをローカル環境またはテストネット環境にデプロイして、準拠した転送と非準拠の転送を比較して試してみてください。
-
シンプルなRWAのユースケースのプロトタイプを作成する
例えば:
- 特定の法域の認定投資家のみがトークンを保有できる、トークン化された私募ファンド
- ロックアップ期間と譲渡可能期間が設定されたトークン化された不動産資産
ERC-3643 を使用して、それらのルールをトークンに直接エンコードします。
-
監視およびコンプライアンス対応ツールの構築
Quicknode Streams を使用して、以下の配信を購読してください:
移籍ERC-3643 トークンからのイベント- コンプライアンス・モジュールからのカスタムイベント(例:規則違反、強制移送など)
そのデータをダッシュボード、アラートシステム、または社内のコンプライアンスツールに取り込みます。
これらの次のステップを検討していくうちに、ERC-3643がご自身のRWAやセキュリティトークンのロードマップにどのように組み込まれるのか、より明確に理解できるようになるでしょう。
結論
このガイドでは、ERC-3643が、おなじみのERC-20モデルの上に、オンチェーンID、適格性チェック、およびモジュール式のコンプライアンスルールを重ね合わせることで、規制対象の許可型資産をサポートする方法について学びました。
イーサリアムやその他のEVMチェーン上でRWAやセキュリティトークンのインフラを構築する場合、ERC-3643を利用すれば、コンプライアンス要件をゼロから作り直す必要がなく、オープンソースの基盤(T-REX)を活用できます。Quicknodeの信頼性の高いインフラと組み合わせることで、現実世界の規制枠組みに適合したパーミッション型トークンの設計、展開、監視が可能になります。
ニュースレターを購読して、さらに多くの記事やガイドをご覧ください。Twitterでフィードバックをお寄せいただくか、Discordのコミュニティサーバーにご参加ください。
皆様からのフィードバックを心よりお待ちしております!❤️
ご意見や新しいトピックに関するご要望などがありましたら、ぜひお知らせください。皆様からのご連絡を心よりお待ちしております。