Skip to main content

Source code

查看 ComplianceManage 合约源码
ComplianceManage 不负责铸造代币,也不维护资产销售状态。它供 RWAToken 等业务合约调用,核心价值在于把“是否允许某个用户执行某种操作”的判断从代币业务层抽离出来,形成可单独治理和升级的合规服务层。
当前合规模型不是纯白名单模式,而是三个机制的组合:
  • 黑名单:被列入黑名单的地址会在代币转账路径中被直接拒绝。
  • 签名授权:用户在执行一级销售等敏感操作前,需要持有有效签名。
  • 已验证 Token 调用限制:只有被批准的业务合约才能消费这些签名授权结果。
ComplianceManage 不是通用 KYC 注册表,也不是完整的身份系统。它的定位是一个面向特定业务合约的链上合规控制器。
ECDSA 是以太坊最常见的签名恢复机制。当前实现通过 ECDSA.recover() 从消息摘要和签名中恢复出签名地址,再判断该地址是否为 owner 或签名管理员。
关于架构组件:
  • ERC-1967 与 UUPS:通过 UUPSUpgradeable 运行在 ERC-1967 代理之上。升级授权由 _authorizeUpgrade() 决定。
  • Initializable 与 OwnableUpgradeable:由于是可升级实例,初始化必须通过 initialize() 完成。OwnableUpgradeable 提供最高治理权限。
合约定义了三类主要角色:
owner 最高权限持有者,可设置或撤销子管理员,并控制升级。
名单管理员 PERMISSION_LIST_MANAGER,负责黑名单管理。
签名管理员 PERMISSION_SIGNATURE_MANAGER,负责签名授权相关操作,以及批准哪些 Token 合约可以调用签名校验。
这种权限拆分的意义在于降低单个热钱包失误时的影响范围。名单管理者不需要拥有升级权限,签名管理者也不需要拥有全部治理能力。
黑名单通过 mapping(address => bool) public blacklist 保存。业务合约可以直接读取该映射,也可以通过 isBlacklisted() 做只读查询。当前提供两种更新方式:
  1. setBlacklist(address[] calldata users, bool status):批量更新,单次最多 100 个地址。
  2. setBlacklistSingle(address user, bool status):单地址更新。
设计要点:
  • 批量接口限制最大长度,避免过大数组造成异常高 gas 消耗。
  • 只有状态真正发生变化时才写入并触发事件。
  • 零地址在单地址接口中会被拒绝,批量接口则会跳过零地址。
verifySignature() 是关键业务入口,附带 onlyVerifiedToken 修饰器。典型流程如下:
1

参数传入

业务合约传入 usersignatureoperationexpireTime
2

时间校验

合约先检查当前时间是否已超过 expireTime
3

生成摘要

chainId、合约地址、用户、当前 nonce、操作类型和过期时间生成消息摘要。
4

恢复签名

转换为 EIP-191 签名消息后,恢复签名地址并判断其是否为 owner 或签名管理员。
5

消费授权

若校验通过,递增 txNonce[user],消费当前授权。
verifiedTokens 映射用于限制哪些业务合约可以调用 verifySignature()
  • RWAToken 在部署后会被注册为已验证 Token。
  • 未注册地址调用会直接触发 TokenNotVerified()
  • 是否允许某个业务合约消费签名,是一个单独的治理决策。
这是“合规服务层”和“业务合约层”解耦的重要接口边界。
子管理员配置由 mapping(address => SubAdmin) public subAdmins 保存:
采用单一权限等级字段,而不是复杂的多布尔位授权表。更适合当前权限简单、职责清晰的场景。
升级授权函数:
  • 代理壳合约本身不决定能否升级,最终由 owner 控制。
  • 新实现必须保持当前存储布局兼容。uint256[50] private __gap; 用于为未来新增变量预留空间,不是任意重排变量的许可证。
审计时应重点关注:
  • 签名路径是否与链下签名服务完全一致,尤其是 operation 与 nonce 的编码顺序。
  • verifiedTokens 是否只包含被信任的业务合约。
  • 签名管理员与名单管理员的操作权限是否与运维流程一致。
  • owner 是否通过安全的多签或治理流程控制升级与管理员设置。
  • 升级后版本是否保持签名消息格式和 nonce 语义兼容。
RWATokenComplianceManage 的主要调用方之一:
  • 转账联动RWAToken._update() 直接查询 blacklist 映射,对黑名单地址的普通转账进行拒绝。
  • 认购联动RWAToken.mint() 调用 verifySignature(),要求买家先通过签名授权,随后才能完成 USDT 支付和代币铸造。