RWA 代币化 —— 发行管理模块
发行管理模块负责 RWA 代币发行请求的全生命周期管理,通过审批工作流确保代币发行的合规性和安全性。
1. 概述
RWATokenIssuanceManager 实现了代币发行的审批流程:
1 | ┌─────────────────────────────────────────────────────────┐ |
| 状态 | 说明 |
|---|---|
| Pending | 请求已提交,等待审批 |
| Approved | 请求已批准,等待执行 |
| Rejected | 请求已拒绝 |
| Deployed | 调用已执行完成 |
2. 角色与权限
1 | bytes32 public constant APPROVER_ROLE = keccak256("APPROVER_ROLE"); |
| 角色 | 权限 |
|---|---|
| DEFAULT_ADMIN_ROLE | 管理角色、设置费用、白名单管理、升级合约 |
| APPROVER_ROLE | 审批/拒绝发行请求 |
| EMERGENCY_ROLE | 紧急暂停、紧急提款 |
3. 数据结构
3.1 发行请求
1 | struct TokenIssuanceRequest { |
3.2 状态枚举
1 | enum RequestStatus { |
3.3 存储映射
1 | // 请求 ID → 请求详情 |
4. 核心功能
4.1 提交请求
submitTokenRequest
提交代币发行请求。
1 | function submitTokenRequest( |
内部实现:
1 | function _submitTokenRequest( |
使用示例:
1 | // 构造铸造调用数据 |
4.2 审批请求
approveRequest
批准发行请求。
1 | function approveRequest(uint256 requestId) external onlyApprover validRequest(requestId) { |
rejectRequest
拒绝发行请求,需提供拒绝原因。
1 | function rejectRequest(uint256 requestId, string memory reason) external onlyApprover validRequest(requestId) { |
4.3 执行调用
executeApprovedCall
执行已批准的发行请求。
1 | function executeApprovedCall(uint256 requestId) external validRequest(requestId) nonReentrant returns (bytes memory) { |
内部执行逻辑:
1 | function _executeCall(uint256 requestId) internal returns (bytes memory) { |
4.4 批量操作
batchApproveRequests
批量批准多个请求。
1 | function batchApproveRequests(uint256[] calldata requestIds) external onlyApprover nonReentrant { |
batchRejectRequests
批量拒绝多个请求。
1 | function batchRejectRequests( |
batchExecuteApprovedCalls
批量执行已批准的请求。
1 | function batchExecuteApprovedCalls(uint256[] calldata requestIds) external nonReentrant { |
5. DelegateCall 白名单
delegatecall 会在调用者的上下文中执行目标代码,存在安全风险,因此需要白名单控制。
5.1 设置白名单
1 | function setDelegateCallTargetWhitelist(address target, bool whitelisted) |
5.2 批量设置
1 | function batchSetDelegateCallTargetWhitelist( |
5.3 查询白名单
1 | function isDelegateCallTargetWhitelisted(address target) external view returns (bool) { |
6. 费用管理
支持收取请求费用。
1 | uint256 public requestFee; |
7. 查询函数
1 | // 获取请求详情 |
8. 紧急控制
8.1 紧急暂停
1 | bool public emergencyPaused; |
区别:
pause():常规暂停,由 Admin 控制emergencyPause():紧急暂停,由 Emergency 角色控制,恢复需要 Admin
8.2 紧急提款
1 | function emergencyWithdraw(address token, uint256 amount) external onlyEmergency { |
9. 工作流程示例
9.1 标准发行流程
1 | 1. 项目方准备发行 |
9.2 批量发行流程
1 | // 1. 准备多个铸造请求 |
10. 事件
1 | event RequestSubmitted(uint256 indexed requestId, address indexed requester, address indexed to, bool isDelegateCall); |
11. 安全考虑
11.1 调用验证
- 目标地址必须是合约
- 调用数据不能为空
- delegatecall 目标必须在白名单中
11.2 状态检查
- 只能审批 Pending 状态的请求
- 只能执行 Approved 状态的请求
- 状态转换是单向的,不可逆
11.3 权限分离
- 提交:任何人
- 审批:APPROVER_ROLE
- 执行:任何人(但必须先被批准)
- 紧急操作:EMERGENCY_ROLE
11.4 Gas 优化
- 使用 assembly 执行调用
- 批量操作使用 unchecked 算术
- 缓存存储变量到内存