示意图 · 03
转移管线
参考代币中的每一次余额变动都经过同一个函数。下面的顺序是固定的;transferCheck 和 canTransfer 以视图方式重放该顺序。
带两个钩子的转移时序
sequenceDiagram
autonumber
participant U as 持有人 / 操作方
participant T as ARexToken._update
participant E as EligibilityHook (CHECK, ELIGIBILITY)
participant X as ExpiryHook (CHECK)
participant R as TraceabilityHook (EXECUTED)
U->>T: safeTransferFrom(from, to, id, amount, data)
T->>T: 加锁(重入锁)· 未暂停
T->>E: canSend(from) / canReceive(to)
E-->>T: true / true
T->>T: 批次存在 · status != RETIRED · amount ≤ balance − frozen
T->>E: check(OP_TRANSFER, operator, from, to, id, amount, data)
E-->>T: OK
T->>X: check(OP_TRANSFER, …)
X-->>T: OK
T->>T: super._update (balances, supply)
T->>R: onExecuted(OP_TRANSFER, …)
R-->>T: 发出 EPCIS 形态的事件
T->>T: 解锁
T-->>U: TransferSingle被拒绝时会发生什么
flowchart LR
A["check 返回的代码 ≠ 0"] --> B["revert ARexHookRejected(hook, code)"]
B --> C["没有任何余额变动"]
B --> D["没有发出 TransferSingle"]
B --> E["前端把代码映射为消息<br/>例如 keccak256('AREX:BATCH_EXPIRED')"]求值顺序与谁可以跳过什么
| 步骤 | 持有人转移 | forcedTransfer(ENFORCER_ROLE) | transform |
|---|---|---|---|
| 加锁 | 是 | 是 | 是 |
| 暂停 | 阻止 | 不阻止 | 阻止 |
canSend / canReceive | 是 | 跳过 | 是(输入来自 from,输出发往 to) |
| 冻结余额 | 强制检查 | 下调至 balance − amount | 强制检查 |
钩子 check | OP_TRANSFER | OP_FORCED_TRANSFER | 输入和输出均为 OP_TRANSFORM |
钩子 onExecuted | 是 | 是 | 是 |