Skip to main contentA-REX Core

Whitepaper · 08

Security Framework

Threat model, invariants, access control, the hook trust boundary, enforcement key management, upgrade safety and audit posture of the A-REX Core reference implementation.

Security posture in one paragraph

The reference token has one choke point (_update), a fixed evaluation order, a reentrancy lock around the entire hook sequence, role-based authority that is never derived from balances, ERC-7201 storage, and a small surface: eight external state-changing functions beyond ERC-1155. The most powerful capabilities — freezing, forced transfer, hook administration, upgrades — are separate roles intended for multisigs and timelocks, and every use of them is an event.

Invariants

InvariantEnforced byTested by
totalSupply(id) equals the sum of balances for idOpenZeppelin ERC1155Supply; transform burns then mints through _updatelineage tests (split, merge, processing)
status == 255 is terminalsetBatchStatus reverts with ARexInvalidStatusTransitionstatus tests
A retired batch cannot be minted or transferred, only burned_updateretired-batch test
amount ≤ balance − frozen for holder-initiated moves_update; forcedTransfer lowers frozen to balance − amountfreeze/forced tests
No hook can re-enter a balance-changing functionstorage lock set before checks, cleared after notificationsReentrantHook test
Hooks are evaluated in registration order; removal preserves orderarray shift in removeHookordering test
A rejected operation changes no balance and emits no transferchecks run before super._updaterejection test (executed count unchanged)
Authority never derives from balanceevery state-changing function is role-gated or ERC-1155-approval-gated"holding tokens grants nothing" tests
canTransfer == (transferCheck == 0)canTransfer is defined as thatconformance tests

Threat model

Actors and capabilities

ActorCanCannot
Holdertransfer unfrozen units to eligible receivers; burn; re-batch same commodity/unit with conserved quantitychange status, mint, process into another commodity, move frozen units
Approved operatorsame as holder for the approving accountanything a holder cannot
ISSUER_ROLEcreate batchesmove others' tokens
TRANSFORMER_ROLEprocessing transforms of tokens it holds or is approved fortransform tokens without approval
STATUS_ROLEchange status (including retire), update metadatamove tokens
ENFORCER_ROLEfreeze any amount; force any transferbypass hooks (they run with OP_FORCED_TRANSFER)
HOOK_ADMIN_ROLEadd/remove hookschange balances directly
PAUSER_ROLEhalt everything except forced transfers—
UPGRADER_ROLEreplace implementation— (this is total power; see key management)
Hook contractreject operations; observe them; answer eligibilityre-enter; change balances

Scenarios

Malicious or buggy hook (denial of service). A hook that always rejects blocks all transfers of the token; one that reverts in check does the same. Mitigation: HOOK_ADMIN_ROLE can remove any hook at any time (order preserved); PAUSER_ROLE can halt while investigating; forced transfers still run, so enforcement is not lost. Registration verifies ERC-165 support and non-zero flags, and rejects EOAs. Recommendation: audit hooks before registering; keep the number small; put the admin behind a timelock so that hook changes are visible before they take effect.

Hook re-entrance. A hook's onExecuted calls back into safeTransferFrom. Mitigation: the lock; the call reverts with ARexReentrantCall. Note that ERC-1155's receiver callback (onERC1155Received) runs after the lock is released, as in every ERC-1155 token; the token's state is final by then.

Compromised enforcement key. Whoever holds ENFORCER_ROLE can move any tokens. Mitigation: multisig with a documented procedure (court order, pledge agreement, sanctions notice); every action emits ForcedTransfer/Frozen; hooks can require an order reference in transfer data (OP_FORCED_TRANSFER is not exempt from hooks). Consider a timelock for non-urgent enforcement.

Compromised upgrader. Total compromise. Mitigation: multisig plus timelock; OpenZeppelin upgrade validations in CI; ERC-7201 storage to avoid layout accidents.

Status abuse. STATUS_ROLE can retire a batch held by others. This is intentional — a warehouse, inspector or regulator declaring a lot unfit — and must be disclosed to holders. Mitigation: assign to an accountable institution; every change is an event with a reason.

Issuer fraud. ISSUER_ROLE can create a batch that does not exist physically. The token cannot prevent this; it makes it attributable (issuer, originRef, metadataHash) and lets attestations from independent parties (warehouse, inspector, registry) be required before transfer via AttestationHook.

Metadata substitution. setBatchMetadata changes the hash and URI. Mitigation: role-gated; BatchMetadataUpdated and URI events keep the history; earlier documents remain verifiable against earlier hashes.

Front-running of transferCheck. A pre-flight check can become stale before the transaction executes (a hook's state changes). The transaction re-evaluates; the worst case is a revert with a precise code.

Gas griefing through hooks. Each hook adds one external call per affected id per phase. A hook with unbounded loops makes transfers unaffordable. Mitigation: hook authoring rules (bounded check), review before registration.

Upgradeable hook trust. A hook deployed behind a proxy can change transfer policy without any change on the token. Mitigation: treat hook admin keys with the same care as HOOK_ADMIN_ROLE; prefer immutable hooks for production.

Access control model

OpenZeppelin AccessControl with eight roles on the token and one on the attestation registry; DEFAULT_ADMIN_ROLE administers all of them. Recommended production layout:

RoleHolder
DEFAULT_ADMIN_ROLE, UPGRADER_ROLE, HOOK_ADMIN_ROLEgovernance multisig behind a timelock
ENFORCER_ROLEenforcement multisig (compliance + legal)
PAUSER_ROLEincident-response key (fast)
ISSUER_ROLE, STATUS_ROLE, TRANSFORMER_ROLEoperational services with least privilege, rotated
ATTEST_ADMIN_ROLEcertification authority or platform

initialize grants everything to one admin for convenience; the deployment checklist requires redistribution before production.

Enforcement and pause semantics

  • Pause blocks mints, transfers, burns and transforms; it does not block forced transfers, so a lawful order can be executed during an incident.
  • Forced transfers skip canSend/canReceive and the frozen-balance check, lower the frozen amount to what remains, and still run hooks with OP_FORCED_TRANSFER. Reference hooks return OK for that op; a hook that governs enforcement may require order references in data.
  • Freezing may exceed the balance (ERC-7943), so a lien can cover future deposits.

Upgrade safety

  • UUPS; _authorizeUpgrade gated by UPGRADER_ROLE.
  • ERC-7201 namespaced storage struct; append-only.
  • OpenZeppelin upgrades plugin validations run in tests and should run in CI before any upgrade transaction.
  • The per-file optimizer.runs = 1 setting keeps the implementation under EIP-170; a change that pushes it over fails at compile time with a warning and at deployment with a revert.

Dependency and build security

  • OpenZeppelin Contracts and Contracts-Upgradeable pinned to 5.3.0; lockfile committed; CI uses npm ci.
  • Solidity 0.8.22, viaIR, EVM paris (no transient storage dependence, deployable on chains that have not adopted Cancun).
  • No external libraries linked; no delegatecall outside the UUPS proxy.

Audit posture

  • 46 tests on the reference implementation, hooks and extensions cover every invariant above, including a seeded randomized invariant run.
  • Gas and size are measured by scripts in the repository.
  • A third-party audit of ARexToken, ARexAttestations and the reference hooks is a stated precondition for a production anchor and for submitting the ERC (see Future Developments).
  • Formal verification of the pipeline invariants is on the roadmap; the invariants are small enough to be stated as properties.

Residual risks the standard does not remove

  • The physical existence and quality of a lot are attested, not proven; the token makes claims attributable, not true.
  • Off-chain metadata availability depends on the storage chosen; the hash guarantees integrity, not availability.
  • Hook and module governance is only as good as the keys that control it.