Диаграммы · 03
Конвейер переводов
Каждое изменение баланса в эталонном токене проходит через одну функцию. Порядок ниже зафиксирован; transferCheck и canTransfer воспроизводят его как view-функции.
Последовательность перевода с двумя хуками
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 (балансы, предложение)
T->>R: onExecuted(OP_TRANSFER, …)
R-->>T: генерация события в форме EPCIS
T->>T: разблокировка
T-->>U: TransferSingleЧто происходит при отказе
flowchart LR
A["check возвращает код ≠ 0"] --> B["откат с 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 | да | да | да |