Skip to main contentA-REX Core

Стандарт

Interface reference

Every function, event, error and type of the five normative interfaces, generated from contracts/standard/ and its NatSpec on each build. For the normative prose, read the specification.

Доступно только на английском
Этот документ опубликован на английском языке. Главы whitepaper и диаграммы переведены; нормативный стандарт, руководства по системному проектированию и записи о решениях остаются на английском, чтобы существовал единый авторитетный текст.
InterfaceLayerERC-165 idRequiredSource
IERC7943MultiToken00x41c4fbadMUSTcontracts/standard/IERC7943MultiToken.sol
IARexBatch10xe22639e0MUSTcontracts/standard/IARexBatch.sol
IARexHook20x332afcbbMUST for hookscontracts/standard/IARexHook.sol
IARexHookManager20x964f4861MUST (getHooks)contracts/standard/IARexHookManager.sol
IARexAttest30xad603a6cSHOULD (token or companion)contracts/standard/IARexAttest.sol

IERC7943MultiToken

interface IERC7943MultiToken is IERC165 · layer 0 · id 0x41c4fbad · MUST

ERC-1155 variant of ERC-7943 (uRWA, Universal Real World Asset interface).

Reproduced verbatim from the Final ERC-7943 text so that A-REX tokens are detectable by any ERC-7943-aware integrator. Interface ID: 0x41c4fbad. A-REX requires every conformant token to implement this interface; it supplies the enforcement primitives (freeze, forced transfer, eligibility) that regulators, custodians and courts expect from a token backed by a physical asset.

Functions

forcedTransfer

function forcedTransfer(address from, address to, uint256 tokenId, uint256 amount) external returns (bool result);

Takes tokens from one address and transfers them to another.

Requires specific authorization. Used for regulatory compliance or recovery scenarios.

setFrozenTokens

function setFrozenTokens(address account, uint256 tokenId, uint256 amount) external returns (bool result);

Changes the frozen status of amount of tokenId tokens belonging to an account.

Overwrites the current value, similar to an approve function. It can exceed the balance.

canSend

function canSend(address account) external view returns (bool allowed);

Checks if a specific account is allowed to send tokens according to token rules.

canReceive

function canReceive(address account) external view returns (bool allowed);

Checks if a specific account is allowed to receive tokens according to token rules.

getFrozenTokens

function getFrozenTokens(address account, uint256 tokenId) external view returns (uint256 amount);

Checks the frozen amount of a specific tokenId for account.

canTransfer

function canTransfer(address from, address to, uint256 tokenId, uint256 amount) external view returns (bool allowed);

Checks if a transfer is currently possible according to token rules, including frozen balances.

Events

EventWhen
ForcedTransfer(address indexed from, address indexed to, uint256 indexed tokenId, uint256 amount)Emitted when tokens are taken from one address and transferred to another.
Frozen(address indexed account, uint256 indexed tokenId, uint256 amount)Emitted when setFrozenTokens is called, changing the frozen amount of tokenId tokens for account.

Errors

ErrorRaised when
ERC7943CannotSend(address account)Error reverted when an account is not allowed to send tokens.
ERC7943CannotReceive(address account)Error reverted when an account is not allowed to receive tokens.
ERC7943CannotTransfer(address from, address to, uint256 tokenId, uint256 amount)Error reverted when a transfer is not allowed according to internal rules.
ERC7943InsufficientUnfrozenBalance(address account, uint256 tokenId, uint256 amount, uint256 unfrozen)Error reverted when a transfer is attempted from account with an amount of tokenId less than or equal to its balance, but greater than its unfrozen balance.

IARexBatch

interface IARexBatch is IERC165 · layer 1 · id 0xe22639e0 · MUST

A-REX Core, layer 1: the minimal on-chain representation of an agricultural batch.

This interface is deliberately small. Everything agricultural that is not the identity of a batch or its lineage belongs in hooks (IARexHook) or in off-chain metadata referenced by uri and committed by metadataHash.

Design rules (normative, see standard/AREX-CORE.md):

  • No closed enumerations. Commodity, unit and status are open codes so that a new crop, a new grading scheme or a new lifecycle can be adopted without redeploying.
  • No personal data. Geolocation of a plot is personal data of the producer under the GDPR and Latin American data-protection laws; only a reference (originRef) is stored.
  • Pre-harvest is a first-class case: producedAt == 0 means "not yet produced".
  • Lineage is mandatory: transform is the only way to split, merge or process a batch, so every output batch can be traced back to its inputs (EPCIS TransformationEvent).
  • Status is changed by an authorized role, never by holding a balance.

Interface ID: see ARexInterfaceIds.IAREX_BATCH.

struct BatchInit

Fields supplied by the issuer when a batch is created or transformed.

FieldTypeMeaning
commoditybytes32Namespaced commodity code, e.g. ARexCodes.commodity("HS", "100199").
unitbytes32UN/CEFACT Recommendation 20 unit code, e.g. bytes32("KGM").
producedAtuint64Unix time of harvest/production; 0 = not yet produced (pre-harvest).
expiresAtuint64Unix time after which the batch is considered expired; 0 = none.
originRefbytes32Hash or reference to origin evidence (EUDR DDS reference, registry ID, truncated geohash). Never raw coordinates.
metadataHashbytes32keccak256 of the canonical off-chain metadata document.
uristringLocation of the metadata document (IPFS, HTTPS, GS1 Digital Link).

struct Batch

Full batch record as stored by the token.

FieldTypeMeaning
issueraddressAccount that created the batch (or performed the transformation).
createdAtuint64Block timestamp of creation.
statusuint80 = ACTIVE, 255 = RETIRED (terminal). 1..254 are issuer-defined.
commoditybytes32Namespaced commodity code, e.g. ARexCodes.commodity("HS", "100199").
unitbytes32UN/CEFACT Recommendation 20 unit code, e.g. bytes32("KGM").
producedAtuint64Unix time of harvest/production; 0 = not yet produced (pre-harvest).
expiresAtuint64Unix time after which the batch is considered expired; 0 = none.
originRefbytes32Hash or reference to origin evidence (EUDR DDS reference, registry ID, truncated geohash). Never raw coordinates.
metadataHashbytes32keccak256 of the canonical off-chain metadata document.
uristringLocation of the metadata document (IPFS, HTTPS, GS1 Digital Link).

Functions

createBatch

function createBatch(BatchInit calldata init, uint256 quantity, address to, bytes calldata data) external returns (uint256 id);

Create a new batch and mint quantity units of it to to.

MUST revert if quantity == 0, if init.commodity == 0 or init.unit == 0, or if init.expiresAt != 0 && init.producedAt != 0 && init.expiresAt <= init.producedAt. MUST emit BatchCreated and the ERC-1155 TransferSingle event. MUST run the hook pipeline with op = OP_MINT.

ParameterMeaning
initBatch fields.
quantityUnits minted, expressed in init.unit.
toRecipient of the minted units.
dataForwarded to hooks and to the ERC-1155 receiver.

Returns: id The new batch / token id.

batchOf

function batchOf(uint256 id) external view returns (Batch memory);

Returns the batch record. MUST revert with ARexBatchNotFound if id does not exist.

batchExists

function batchExists(uint256 id) external view returns (bool);

Non-reverting existence check for hooks and integrators.

totalSupply

function totalSupply(uint256 id) external view returns (uint256);

Circulating units of the batch (ERC-1155 supply tracking is mandatory).

setBatchStatus

function setBatchStatus(uint256 id, uint8 status, bytes32 reason) external;

Change the lifecycle status of a batch.

MUST be restricted to an authorized role; MUST NOT be granted by token balance. Status 255 (RETIRED) is terminal: once set it MUST NOT change. MUST emit BatchStatusChanged.

setBatchMetadata

function setBatchMetadata(uint256 id, bytes32 metadataHash, string calldata uri) external;

Update the metadata commitment of a batch (e.g. after a lab result is added).

MUST be restricted to an authorized role. MUST emit BatchMetadataUpdated.

transform

function transform(address from, address to, uint256[] calldata inputIds, uint256[] calldata inputAmounts, BatchInit[] calldata outputs, uint256[] calldata outputAmounts, bytes32 processRef) external returns (uint256[] memory outputIds);

Burn inputAmounts of inputIds held by from and mint new batches outputs with outputAmounts to to, recording lineage.

Covers split (1 input, n outputs), merge (n inputs, 1 output) and processing (n → m). msg.sender MUST be from or an approved operator of from (ERC-1155 semantics). MUST revert with ARexLengthMismatch on inconsistent array lengths. MUST run the hook pipeline with op = OP_TRANSFORM for every input burn and output mint. MUST emit BatchTransformed, one BatchCreated per output, and ERC-1155 transfer events. Conservation of quantity is NOT enforced by the standard (processing changes units and mass); it is the job of hooks and off-chain audit.

Returns: outputIds Ids of the created output batches, in order.

parentsOf

function parentsOf(uint256 id) external view returns (uint256[] memory);

Direct parents of a batch (empty for batches created with createBatch).

Events

EventWhen
BatchCreated(uint256 indexed id, address indexed issuer, bytes32 indexed commodity, bytes32 unit, uint256 quantity, address to)Emitted once per batch creation, including outputs of transform.
BatchStatusChanged(uint256 indexed id, uint8 previousStatus, uint8 newStatus, bytes32 reason)Emitted when the lifecycle status of a batch changes.
BatchMetadataUpdated(uint256 indexed id, bytes32 metadataHash, string uri)Emitted when the metadata commitment of a batch is updated.
BatchTransformed(address indexed operator, uint256[] inputIds, uint256[] inputAmounts, uint256[] outputIds, uint256[] outputAmounts, bytes32 processRef)Emitted by transform. Maps one-to-one to an EPCIS 2.0 TransformationEvent.

Errors

ErrorRaised when
ARexBatchNotFound(uint256 id)
ARexBatchRetired(uint256 id)
ARexInvalidBatch(bytes32 reason)
ARexInvalidStatusTransition(uint256 id, uint8 from, uint8 to)
ARexLengthMismatch()

IARexHook

interface IARexHook is IERC165 · layer 2 · id 0x332afcbb · MUST for hooks

A-REX Core, layer 2: the single extension point of a conformant token.

Every rule that is not the identity of a batch (eligibility, sanctions, expiry, seasonal windows, custody, transfer limits, documents, escrow, ...) is a hook. Hooks are contracts, deployed by anyone, attached to a token by its administrator.

The token calls hooks in registration order and stops at the first non-zero code. A hook never reverts a transfer directly: it returns a bytes32 code and the token reverts with ARexHookRejected(hook, code). Codes are open, namespaced constants (see ARexCodes) so that front-ends, indexers and auditors can interpret them.

hookFlags() tells the token which callbacks the hook wants; the token caches the flags at registration so that a transfer costs one external call per interested hook, not one supportsInterface probe per capability.

The hook learns which token is calling from msg.sender; a single hook deployment can therefore serve many tokens.

Functions

hookFlags

function hookFlags() external view returns (uint8);

Bitmap of callbacks this hook implements.

bit 0 (ARexCodes.HOOK_CHECK): check is called before every operation. bit 1 (ARexCodes.HOOK_EXECUTED): onExecuted is called after every operation. bit 2 (ARexCodes.HOOK_ELIGIBILITY): canSend / canReceive are consulted. A conformant hook MUST return a constant value.

check

function check(uint8 op, address operator, address from, address to, uint256 id, uint256 amount, bytes calldata data) external view returns (bytes32 code);

Validate an operation. MUST be a view. MUST NOT revert for policy reasons; return a non-zero code instead. bytes32(0) means allowed.

ParameterMeaning
opARexCodes.OP_MINT / OP_TRANSFER / OP_BURN / OP_FORCED_TRANSFER / OP_TRANSFORM.
operatormsg.sender of the token call that triggered the operation.
fromSource account (address(0) for mints).
toDestination account (address(0) for burns).
idBatch id.
amountUnits affected.
dataOpaque data forwarded by the token.

onExecuted

function onExecuted(uint8 op, address operator, address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

Notification after an operation has been applied to balances.

MUST NOT re-enter the token's balance-changing functions; the token guards against it. Parameters as in check.

canSend

function canSend(address account) external view returns (bool);

Account-level eligibility to send (KYC/KYB, sanctions, allowlists). Only consulted if HOOK_ELIGIBILITY is set.

canReceive

function canReceive(address account) external view returns (bool);

Account-level eligibility to receive. Only consulted if HOOK_ELIGIBILITY is set.

Errors

ErrorRaised when
ARexHookRejected(address hook, bytes32 code)Reverted by the token when a hook returns a non-zero code.

IARexHookManager

interface IARexHookManager · layer 2 · id 0x964f4861 · MUST (getHooks)

A-REX Core, layer 2 (token side): how a token exposes and manages its hook pipeline.

getHooks is mandatory so that anyone can audit which rules govern a token. registerHook / removeHook are the recommended administrative surface; a token MAY use a different governance mechanism (timelock, multisig, immutable list) as long as the events below are emitted.

Functions

getHooks

function getHooks() external view returns (address[] memory);

Ordered list of active hooks. Hooks are evaluated in this order.

hookFlagsOf

function hookFlagsOf(address hook) external view returns (uint8);

Cached flags of a registered hook (0 if not registered).

registerHook

function registerHook(address hook) external;

Append a hook to the pipeline. MUST verify supportsInterface(IARexHook) and cache hookFlags().

removeHook

function removeHook(address hook) external;

Remove a hook, preserving the relative order of the remaining hooks.

Events

EventWhen
HookRegistered(address indexed hook, uint8 flags, uint256 position)
HookRemoved(address indexed hook)

Errors

ErrorRaised when
ARexHookAlreadyRegistered(address hook)
ARexHookNotRegistered(address hook)
ARexInvalidHook(address hook)

IARexAttest

interface IARexAttest is IERC165 · layer 3 · id 0xad603a6c · SHOULD (token or companion)

A-REX Core, layer 3: open attestations about a batch (certifications, inspections, lab results, regulatory declarations).

An attestation is (batch id, topic) -> (issuer, reference, validity window). Topics are open bytes32 values, namespaced by convention (see ARexCodes.topic), so a new certification scheme never requires a redeploy. They map directly to:

  • ERC-735 / ONCHAINID claim topics (uint256 -> bytes32),
  • Ethereum Attestation Service schema UIDs (bytes32),
  • W3C Verifiable Credential types (hash of the type URI). The token keeps only the commitment; the evidence lives off-chain at ref. Only issuers trusted for a topic can attest to it, mirroring ERC-3643's TrustedIssuersRegistry without imposing an identity provider.

struct Attestation

FieldTypeMeaning
issueraddress
refbytes32Hash of the evidence document or external certificate id.
issuedAtuint64
expiresAtuint640 = no expiry.
revokedbool

Functions

attest

function attest(uint256 id, bytes32 topic, bytes32 ref, uint64 expiresAt) external;

Record an attestation. msg.sender MUST be a trusted issuer for topic.

Re-attesting the same (id, topic) overwrites the record; history is in the event log.

revokeAttestation

function revokeAttestation(uint256 id, bytes32 topic, bytes32 reason) external;

Revoke an attestation. MUST be callable by its issuer; MAY be callable by an admin role.

getAttestation

function getAttestation(uint256 id, bytes32 topic) external view returns (Attestation memory);

Raw record. MUST revert with ARexAttestationNotFound if none exists.

isAttested

function isAttested(uint256 id, bytes32 topic) external view returns (bool);

True if an attestation exists, is not revoked, is not expired and its issuer is still trusted.

isTrustedIssuer

function isTrustedIssuer(bytes32 topic, address issuer) external view returns (bool);

Whether issuer may attest to topic.

Events

EventWhen
Attested(uint256 indexed id, bytes32 indexed topic, address indexed issuer, bytes32 ref, uint64 expiresAt)
AttestationRevoked(uint256 indexed id, bytes32 indexed topic, address indexed issuer, bytes32 reason)
TrustedIssuerUpdated(bytes32 indexed topic, address indexed issuer, bool trusted)

Errors

ErrorRaised when
ARexUntrustedIssuer(bytes32 topic, address issuer)
ARexAttestationNotFound(uint256 id, bytes32 topic)

ARexCodes

Constants shared by tokens, hooks and front-ends (contracts/standard/ARexCodes.sol). Only the operation, flag and status values are normative; the rejection codes are recommended.

GroupNameTypeValue
Operations (fixed by the standard)OP_MINTuint81
Operations (fixed by the standard)OP_TRANSFERuint82
Operations (fixed by the standard)OP_BURNuint83
Operations (fixed by the standard)OP_FORCED_TRANSFERuint84
Operations (fixed by the standard)OP_TRANSFORMuint85
Hook flags (fixed by the standard)HOOK_CHECKuint81 << 0
Hook flags (fixed by the standard)HOOK_EXECUTEDuint81 << 1
Hook flags (fixed by the standard)HOOK_ELIGIBILITYuint81 << 2
Batch status (fixed by the standard)STATUS_ACTIVEuint80
Batch status (fixed by the standard)STATUS_RETIREDuint8255
Rejection codes (convention: keccak256("AREX:<NAME>"))OKbytes32bytes32(0)
Rejection codes (convention: keccak256("AREX:<NAME>"))PAUSEDbytes32keccak256("AREX:PAUSED")
Rejection codes (convention: keccak256("AREX:<NAME>"))FROZENbytes32keccak256("AREX:FROZEN")
Rejection codes (convention: keccak256("AREX:<NAME>"))SENDER_INELIGIBLEbytes32keccak256("AREX:SENDER_INELIGIBLE")
Rejection codes (convention: keccak256("AREX:<NAME>"))RECEIVER_INELIGIBLEbytes32keccak256("AREX:RECEIVER_INELIGIBLE")
Rejection codes (convention: keccak256("AREX:<NAME>"))SANCTIONEDbytes32keccak256("AREX:SANCTIONED")
Rejection codes (convention: keccak256("AREX:<NAME>"))BATCH_NOT_FOUNDbytes32keccak256("AREX:BATCH_NOT_FOUND")
Rejection codes (convention: keccak256("AREX:<NAME>"))BATCH_RETIREDbytes32keccak256("AREX:BATCH_RETIRED")
Rejection codes (convention: keccak256("AREX:<NAME>"))BATCH_INACTIVEbytes32keccak256("AREX:BATCH_INACTIVE")
Rejection codes (convention: keccak256("AREX:<NAME>"))BATCH_EXPIREDbytes32keccak256("AREX:BATCH_EXPIRED")
Rejection codes (convention: keccak256("AREX:<NAME>"))BATCH_NOT_PRODUCEDbytes32keccak256("AREX:BATCH_NOT_PRODUCED")
Rejection codes (convention: keccak256("AREX:<NAME>"))LIMIT_EXCEEDEDbytes32keccak256("AREX:LIMIT_EXCEEDED")
Rejection codes (convention: keccak256("AREX:<NAME>"))DOCUMENT_MISSINGbytes32keccak256("AREX:DOCUMENT_MISSING")
Rejection codes (convention: keccak256("AREX:<NAME>"))SEASON_CLOSEDbytes32keccak256("AREX:SEASON_CLOSED")
Rejection codes (convention: keccak256("AREX:<NAME>"))IN_TRANSITbytes32keccak256("AREX:IN_TRANSIT")
Rejection codes (convention: keccak256("AREX:<NAME>"))ATTESTATION_MISSINGbytes32keccak256("AREX:ATTESTATION_MISSING")