本文介绍了ERC-3643,这是一个以太坊代币标准,专为受监管的资产设计,它通过链上身份、资格检查和模块化合规规则,在ERC-20模型的基础上,支持需要许可的代币。ERC-3643由ERC-3643协会管理,旨在标准化现实世界资产的许可代币化,适用于证券、房地产和基金等用例。
ERC-3643 是以太坊许可型代币的标准,意味着代币只能由满足预定义的合规性规则(如 KYC/AML、投资者资格和管辖区要求)的身份持有和转移。它专为受监管的资产而设计,你必须知道谁持有该资产以及他们是否被允许持有或交易它。
最初被称为 T-REX (Token for Regulated EXchanges,受监管交易所代币),由 Tokeny 发起,现在正式成为 ERC-3643,并由 ERC-3643 协会管理,该协会专注于将现实世界资产 (RWA) 的许可型代币化进行标准化。
在实践中,ERC-3643 是智能合约套件,共同实现:
由于 ERC-3643 将身份和合规性规则直接集成到代币标准中,因此它是代币化 RWA(如证券、房地产、基金和其他受监管工具)的绝佳选择。
warning
本指南中的代码示例未经审计,仅用于概念理解。未经彻底审查、测试和独立安全审计,请勿在生产中使用它们。
在深入研究之前,让我们设置背景。标准 ERC-20 代币是无需许可的。任何人都可以发送它,任何人都可以接收它,并且任何地址都可以持有它。对于像 DAI 或 UNI 这样的资产来说,这是一个特性。
但是,当处理现实世界的资产时,例如代币化的证券(公司股份)或 fractionalized 房地产,这就会成为一个问题。现实世界的法规要求你了解谁持有该资产,并根据以下内容限制转让:
ERC-3643,最初被称为 T-REX (Token for Regulated EXchanges, 受监管交易所代币),旨在将这些规则引入链上。它是一个智能合约套件,使与 ERC-20 兼容的代币具有“合规性感知”。
从高层次来看,ERC-3643 的实现应提供:
canTransfer)ERC-3643 是有意的模块化。它没有将所有内容都放在一个单体代币合约中,而是将职责分配给多个合约。
概括地说,核心组件是:
| 组件 | 摘要 |
|---|---|
| ONCHAINID | 一个单独的身份合约(基于 ERC-734/735),它持有用户可验证的 claim,由受信任的发行者发布。 |
| 受信任的发行者注册表 | 受信任的地址列表(例如,KYC 提供商),可以添加有关用户身份的 claim |
| Claim Topics 注册表 | 所需 claim 类型的目录(例如,KYC 验证、合格投资者)。 |
| 身份注册表 | 将钱包映射到 ONCHAINID 和国家/地区,公开 isVerified 等验证。 |
| 合规性合约 | 编码提供和转移规则,在转移之前/之后查询。 |
| 许可型代币 (T-REX) | 与 ERC-20 兼容的代币。它持有对身份注册表和合规性合约的引用,并在任何转移之前咨询它们。 |
ONCHAINID 是一个通用身份合约,用于记录密钥和可验证的 claim。
claim 示例包括:
受信任的发行者(如 KYC 提供商或受监管机构)会发布这些 claim。该合约不会直接存储个人身份信息 (PII),而是存储引用和哈希以保护隐私。
多个钱包可以链接到相同的底层身份,并且在代码中,此身份通常被称为 IIdentity。ONCHAINID 充当与合规性相关的事实的锚点。
受信任的发行者注册表 跟踪哪些 claim 发行者对于给定的代币是受信任的,以及每个发行者可以签署哪些 claim 主题。
例如,你可能会信任:
KYC_VALIDATED 主题的特定 KYC 提供商。ACCREDITED_INVESTOR 的受监管实体。只有这些发行者的 claim 才被视为对该代币的合规性检查有效。
Claim Topics 注册表 定义哪些 claim 类型对于持有代币很重要,例如:
KYC_VALIDATEDACCREDITED_INVESTORNOT_IN_RESTRICTED_COUNTRYNOT_ON_SANCTIONS_LIST与 Trusted Issuers Registry 一起,它定义了需要哪些 claim 以及谁可以发布它们。
身份注册表 是代币持有者的看门人:
isVerified(address)它通常依赖于 IdentityRegistryStorage,因此多个代币可以共享一个白名单,同时保留特定于代币的注册表。在 KYC 之后,投资者链接或部署 ONCHAINID,从受信任的发行者收到所需的 claim,并且他们的钱包已注册国家/地区代码(ISO-3166 数字)。
合规性 合约编码提供规则和转移限制。例子:
标准接口:
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;
代币合约使用合规性合约来:
canTransfer)。transferred、created、destroyed),以便它可以保持内部状态(上限、计数器等)同步。该代币实现标准 ERC-20 功能,并保存对 IdentityRegistry 和 Compliance 合约的引用。它不会盲目地发送代币,而是通过一些额外的检查来路由每个转移,以确保允许移动。它用以下内容包装转移:
transferred)典型的扩展包括:
现在,让我们逐步了解 ERC-3643 代币转账是如何运作的。
用户(Alice)像往常一样调用代币的 transfer 或 transferFrom 函数,以将代币转账到新地址(Bob):
token.transfer(bob.address, amount);
token.transferFrom(from, bob.address, amount); // 如果使用 allowance
Token 合约不会移动代币。它首先通过 Identity Registry 执行资格检查。该逻辑通常如下:
isVerified() 函数,确保接收者已注册并在 IdentityRegistry 中具有所需的 claim在许多实现中,代币直接调用
identityRegistry.isVerified(...),然后调用compliance.canTransfer(...)。在其他实现中,资格检查捆绑在canTransfer本身中。重要的一点是,在任何余额移动之前,都会强制执行资格和合规性规则。
在资格检查之后,Token 合约继续进行第二次检查:compliance.canTransfer(alice.address, bob.address, amount)。
Compliance 合约检查其模块化逻辑,以确定是否允许转移,并且未违反任何规则。
合规性合约可以评估以下规则:
如果违反任何规则,canTransfer 将返回 false,并且代币应该回滚。
如果所有检查都通过,则转移像正常的 ERC-20 转移一样执行。然后,Token 调用 compliance.transferred(from, to, amount) 以更新合规性状态,以供将来检查。
在铸造时,Token 调用 compliance.created(to, amount),在销毁时,它调用 compliance.destroyed(from, amount),以便合规性引擎也跟踪供应变化。
可审计性
由于 claim 由受信任的发行者签名并通过 ONCHAINID 存储,因此你可以维护资格的可验证审计跟踪。
你有一个可审计的跟踪:
ERC-3643 将 Owner(根据 EIP-173)与可以操作敏感功能的 Agent 地址分开。Agent 角色是标准化的:
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);
}
Owner 管理代理和高级配置。Agent 执行诸如冻结、强制转移、铸造/销毁和批量操作之类的操作,具体取决于实现。
ERC-3643 实现公开的关键标准化接口:
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 代币部署涉及:
ClaimTopicsRegistry、TrustedIssuersRegistry、IdentityRegistryStorage、IdentityRegistry。Compliance,并在部署后将其绑定到代币。IdentityRegistry 和 Compliance。address、ONCHAINID、country)。mint 分配供应,并确保铸造/销毁调用 created/destroyed。由于它仍然与 ERC-20 兼容,因此 ERC-3643 代币可以与钱包、托管人、交易所(中心化或分散式,在允许的情况下)以及投资组合和分析工具集成,只要这些平台准备好处理资产的许可性质(例如,处理由于合规性导致的转移回滚)。
从这里,你可以:
深入研究诸如交割与支付 (DvD)、交易所集成和可升级性模式之类的极端情况,这些模式超出了本概述的范围。
克隆 ERC-3643 / T-REX 存储库,将注册表和代币部署到本地或测试网环境,并尝试符合合规性和不合规性的转移。
例如:
使用 ERC-3643 将这些规则直接编码到代币中。
使用 Quicknode Streams 订阅到:
Transfer 事件来自你的合规性模块的自定义事件(例如,违反规则、强制转移)
然后将该数据馈送到仪表板、警报系统或内部合规性工具中。
当你探索这些后续步骤时,你将更加清楚地了解 ERC-3643 如何融入你自己的 RWA 或证券代币路线图。
在本指南中,你学习了 ERC-3643 如何在熟悉的 ERC-20 模型之上分层链上身份、资格检查和模块化合规性规则,以支持受监管的许可资产。
如果你正在以太坊或其他 EVM 链上构建 RWA 或证券代币基础设施,ERC-3643 提供了一个开源基础 (T-REX),而不是从头开始重新发明合规性。结合 Quicknode 的可靠基础设施,你可以设计、部署和监控符合现实世界监管框架的许可代币。
订阅我们的新闻通讯,了解更多文章和指南。通过 Twitter 分享反馈或加入我们的 Discord 社区服务器。
如果你有任何反馈或对新主题的请求,请告诉我们。我们很乐意听到你的来信。
- 原文链接: quicknode.com/guides/rea...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!