Skip to main contentA-REX Foundation

Diagrams · 03

Transfer pipeline

Every balance change in the reference token passes through one function. The order below is fixed; transferCheck and canTransfer replay it as views.

Sequence of a transfer with two hooks

sequenceDiagram
    autonumber
    participant U as Holder / operator
    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: lock (reentrancy) · not paused
    T->>E: canSend(from) / canReceive(to)
    E-->>T: true / true
    T->>T: batch exists · 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: emit EPCIS-shaped event
    T->>T: unlock
    T-->>U: TransferSingle

What happens on rejection

flowchart LR
    A[check returns code ≠ 0] --> B["revert ARexHookRejected(hook, code)"]
    B --> C[no balance changed]
    B --> D[no TransferSingle emitted]
    B --> E["front-end maps code → message<br/>e.g. keccak256('AREX:BATCH_EXPIRED')"]

Evaluation order and who can skip what

StepHolder transferforcedTransfer (ENFORCER_ROLE)transform
lockyesyesyes
pauseblocksdoes not blockblocks
canSend / canReceiveyesskippedyes (inputs from from, outputs to to)
frozen balanceenforcedlowered to balance − amountenforced
hooks checkOP_TRANSFEROP_FORCED_TRANSFEROP_TRANSFORM for inputs and outputs
hooks onExecutedyesyesyes