Skip to main contentA-REX Core

Whitepaper · 16

Apéndices

Fuentes vinculantes: contracts/standard/ .sol (CC0) y standard/AREX CORE.md. Los ids de interfaz se reproducen con npm run interface ids.

Apéndice A: Referencia de interfaces

Fuentes vinculantes: contracts/standard/*.sol (CC0) y standard/AREX-CORE.md. Los ids de interfaz se reproducen con npm run interface-ids.

A.1 Resumen de conformidad

Interfazid ERC-165TokenHook
IERC11550xd9b67a26DEBE—
IERC7943MultiToken0x41c4fbadDEBE—
IARexBatch0xe22639e0DEBE—
IARexHookManager0x964f4861DEBE (getHooks)—
IARexAttest0xad603a6cDEBERÍA (token o contrato complementario)—
IARexHook0x332afcbb—DEBE

A.2 IARexBatch

struct BatchInit { bytes32 commodity; bytes32 unit; uint64 producedAt; uint64 expiresAt; bytes32 originRef; bytes32 metadataHash; string uri; }
struct Batch { address issuer; uint64 createdAt; uint8 status; bytes32 commodity; bytes32 unit; uint64 producedAt; uint64 expiresAt; bytes32 originRef; bytes32 metadataHash; string uri; }


event BatchCreated(uint256 indexed id, address indexed issuer, bytes32 indexed commodity, bytes32 unit, uint256 quantity, address to);
event BatchStatusChanged(uint256 indexed id, uint8 previousStatus, uint8 newStatus, bytes32 reason);
event BatchMetadataUpdated(uint256 indexed id, bytes32 metadataHash, string uri);
event BatchTransformed(address indexed operator, uint256[] inputIds, uint256[] inputAmounts, uint256[] outputIds, uint256[] outputAmounts, bytes32 processRef);


error ARexBatchNotFound(uint256 id);
error ARexBatchRetired(uint256 id);
error ARexInvalidBatch(bytes32 reason);
error ARexInvalidStatusTransition(uint256 id, uint8 from, uint8 to);
error ARexLengthMismatch();


function createBatch(BatchInit calldata init, uint256 quantity, address to, bytes calldata data) external returns (uint256 id);
function batchOf(uint256 id) external view returns (Batch memory);
function batchExists(uint256 id) external view returns (bool);
function totalSupply(uint256 id) external view returns (uint256);
function setBatchStatus(uint256 id, uint8 status, bytes32 reason) external;
function setBatchMetadata(uint256 id, bytes32 metadataHash, string calldata uri) external;
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);
function parentsOf(uint256 id) external view returns (uint256[] memory);

A.3 IERC7943MultiToken (ERC-7943, literal)

event ForcedTransfer(address indexed from, address indexed to, uint256 indexed tokenId, uint256 amount);
event Frozen(address indexed account, uint256 indexed tokenId, uint256 amount);
error ERC7943CannotSend(address account);
error ERC7943CannotReceive(address account);
error ERC7943CannotTransfer(address from, address to, uint256 tokenId, uint256 amount);
error ERC7943InsufficientUnfrozenBalance(address account, uint256 tokenId, uint256 amount, uint256 unfrozen);
function forcedTransfer(address from, address to, uint256 tokenId, uint256 amount) external returns (bool result);
function setFrozenTokens(address account, uint256 tokenId, uint256 amount) external returns (bool result);
function canSend(address account) external view returns (bool allowed);
function canReceive(address account) external view returns (bool allowed);
function getFrozenTokens(address account, uint256 tokenId) external view returns (uint256 amount);
function canTransfer(address from, address to, uint256 tokenId, uint256 amount) external view returns (bool allowed);

A.4 IARexHook y IARexHookManager

interface IARexHook is IERC165 {
    error ARexHookRejected(address hook, bytes32 code);
    function hookFlags() external view returns (uint8);
    function check(uint8 op, address operator, address from, address to, uint256 id, uint256 amount, bytes calldata data) external view returns (bytes32 code);
    function onExecuted(uint8 op, address operator, address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
    function canSend(address account) external view returns (bool);
    function canReceive(address account) external view returns (bool);
}
interface IARexHookManager {
    event HookRegistered(address indexed hook, uint8 flags, uint256 position);
    event HookRemoved(address indexed hook);
    error ARexHookAlreadyRegistered(address hook);
    error ARexHookNotRegistered(address hook);
    error ARexInvalidHook(address hook);
    function getHooks() external view returns (address[] memory);
    function hookFlagsOf(address hook) external view returns (uint8);
    function registerHook(address hook) external;
    function removeHook(address hook) external;
}

A.5 IARexAttest

struct Attestation { address issuer; bytes32 ref; uint64 issuedAt; uint64 expiresAt; bool revoked; }
event Attested(uint256 indexed id, bytes32 indexed topic, address indexed issuer, bytes32 ref, uint64 expiresAt);
event AttestationRevoked(uint256 indexed id, bytes32 indexed topic, address indexed issuer, bytes32 reason);
event TrustedIssuerUpdated(bytes32 indexed topic, address indexed issuer, bool trusted);
error ARexUntrustedIssuer(bytes32 topic, address issuer);
error ARexAttestationNotFound(uint256 id, bytes32 topic);
function attest(uint256 id, bytes32 topic, bytes32 ref, uint64 expiresAt) external;
function revokeAttestation(uint256 id, bytes32 topic, bytes32 reason) external;
function getAttestation(uint256 id, bytes32 topic) external view returns (Attestation memory);
function isAttested(uint256 id, bytes32 topic) external view returns (bool);
function isTrustedIssuer(bytes32 topic, address issuer) external view returns (bool);

A.6 Constantes (ARexCodes)

GrupoValores
OperacionesOP_MINT = 1, OP_TRANSFER = 2, OP_BURN = 3, OP_FORCED_TRANSFER = 4, OP_TRANSFORM = 5
Indicadores de hookHOOK_CHECK = 1, HOOK_EXECUTED = 2, HOOK_ELIGIBILITY = 4
EstadoSTATUS_ACTIVE = 0, STATUS_RETIRED = 255
Códigos (keccak256("AREX:…"))PAUSED, FROZEN, SENDER_INELIGIBLE, RECEIVER_INELIGIBLE, SANCTIONED, BATCH_NOT_FOUND, BATCH_RETIRED, BATCH_INACTIVE, BATCH_EXPIRED, BATCH_NOT_PRODUCED, LIMIT_EXCEEDED, DOCUMENT_MISSING, SEASON_CLOSED, IN_TRANSIT, ATTESTATION_MISSING
Funciones auxiliarescommodity(scheme, code), unit(code), topic(name), code(namespace, name)

A.7 Roles de la implementación de referencia

ISSUER_ROLE, TRANSFORMER_ROLE, STATUS_ROLE, ENFORCER_ROLE, HOOK_ADMIN_ROLE, PAUSER_ROLE, UPGRADER_ROLE, DEFAULT_ADMIN_ROLE en ARexToken (cada uno keccak256("AREX_<NAME>")); ATTEST_ADMIN_ROLE en ARexAttestations. Vistas adicionales: isExpired(id), transferCheck(from, to, id, amount); función adicional: burn(from, id, amount); slot ERC-7201 0x8ed599b6be05dec05297c009a1279a71df771ad996fe924d0b5a47326ff60900.

A.8 Hooks y extensiones de referencia

ContratoTipoFunciones principales
PerishabilityHookhooksetCommodityDecay, setBatchDecay, valueBps, secondsRemaining, isExpired
SeasonalHookhookaddWindow, clearWindows, windowsOf, isOpen
DeliveryHookhookschedule, pickUp, markInTransit, recordReading, confirmDelivered, cancel, dispute, resolve, getDelivery, lockedUnits
TraceabilityHookhookrecordEvent, eventCount, getEvents; indicador de constructor persist
CommodityPriceOracleextensiónsubmit, finalizeRound, latestAnswer, getRound, currentRound, isStale, setParameters
CarbonImmobilizationWrapperextensiónrecordImmobilization, linkToBatch, retire, release, attestBacking, backingOf, linksOf
ParametricInsuranceextensiónfund, issue, claim, expire, getPolicy, freeCapacity

A.9 Esquema de metadatos

standard/schema/batch-metadata.schema.json (JSON Schema 2020-12). Obligatorios: schemaVersion, commodity{scheme, code}, unit, quantity. Grupos opcionales destacados: traceabilityLotCode, gs1{gtin, lgtin, sscc, glnProducer, digitalLink}, production, origin{country, originRef, eudr{ddsReference}, geohashPrecision, geohash}, quality{gradeScheme, grade, measurements[]}, status.table, attestations[], documents[]{type, hash, uri, registry, registryId}, epcis{bizStep, disposition, readPoint, bizLocation}, restricted{uri, hash, accessPolicy}, attributes[]. Ejemplo en standard/examples/batch-metadata.example.json.

Apéndice B: Glosario

TérminoSignificado
LoteUn id de token ERC-1155 con un registro Batch: un lote de un producto básico en una unidad, con origen y momento de producción compartidos.
ReagrupaciónUn transform cuyas salidas tienen el mismo producto básico y la misma unidad que las entradas y cuyas cantidades se conservan (división, fusión). Abierta a los titulares en la implementación de referencia.
ProcesamientoUn transform que cambia el producto básico, la unidad o la cantidad. Requiere TRANSFORMER_ROLE en la implementación de referencia.
LinajeEl grafo formado por los eventos BatchTransformed y parentsOf.
HookUn contrato que implementa IARexHook, registrado en un token y evaluado en orden en cada operación.
Código de rechazoUn bytes32 devuelto por el check de un hook; 0 significa permitido; convención keccak256("NAMESPACE:NAME").
ElegibilidadPermiso a nivel de cuenta para enviar o recibir, al que responden los hooks marcados con HOOK_ELIGIBILITY; se expone como canSend/canReceive de ERC-7943.
Saldo congeladoUnidades que una cuenta posee pero no puede mover (setFrozenTokens); puede superar el saldo.
Transferencia forzosaMovimiento de unidades por parte de ENFORCER_ROLE sin el consentimiento del titular (ERC-7943).
Atestación(batch, topic) → (issuer, reference, validity) registrada por un emisor de confianza para ese tema.
TemaUn bytes32 que identifica el objeto de una atestación; abierto; se corresponde con los temas de declaración de ERC-735 y con los ids de esquema de EAS.
Referencia de origenoriginRef: un hash o una referencia a la evidencia de origen; nunca coordenadas.
Compromiso de metadatosmetadataHash, keccak256 del documento canónico fuera de la cadena situado en uri.
EstadoValor uint8 del ciclo de vida; 0 activo, 255 retirado (terminal); 1..254 definidos por el emisor.
CTE / KDEEvento crítico de seguimiento / elemento de datos clave (FSMA 204).
DDSDeclaración de diligencia debida (EUDR).
EPCISGS1 Electronic Product Code Information Services, el vocabulario de eventos para la trazabilidad (versión 2.0).
CPR / CPR-eCédula de Produto Rural, el derecho de cobro sobre cosechas de Brasil; forma electrónica registrada ante entidades autorizadas.
EWRRecibo de almacén electrónico conforme a la U.S. Warehouse Act.
MLETRLey Modelo de UNCITRAL sobre Documentos Transmisibles Electrónicos.
ERC-7943 (uRWA)Interfaz universal de activos del mundo real: congelación, transferencia forzosa, elegibilidad; Final en mayo de 2026.
ERC-3643 (T-REX)Estándar de token con permisos para valores sobre ERC-20; Final en diciembre de 2023.
ERC-7201Disposición de almacenamiento con espacios de nombres para contratos actualizables.

Apéndice C: Bibliografía

Estándares y especificaciones

  • Radomski, W. et al. "EIP-1155: Multi Token Standard." Ethereum Improvement Proposals, 2018.
  • Vogelsteller, F., Buterin, V. "EIP-20: Token Standard." 2015.
  • "ERC-165: Standard Interface Detection." 2018.
  • "ERC-3643: T-REX — Token for Regulated EXchanges." Final, 15 de diciembre de 2023. https://eips.ethereum.org/EIPS/eip-3643
  • "ERC-7943: uRWA — Universal Real World Asset Interface." Final, 27 de mayo de 2026. https://eips.ethereum.org/EIPS/eip-7943
  • "ERC-7201: Namespaced Storage Layout." 2023.
  • "ERC-735: Claim Holder." 2017 (borrador).
  • Documentación de Ethereum Attestation Service.
  • GS1. "EPCIS and CBV Standard 2.0." 2022. GS1 US. "EPCIS Recommendations for FSMA 204 Critical Tracking Events." 2024.
  • UN/CEFACT. "Recommendation No. 20: Codes for Units of Measure Used in International Trade."
  • IETF RFC 8785. "JSON Canonicalization Scheme (JCS)." 2020.
  • Documentación de OpenZeppelin Contracts 5.x; anuncio de la alianza entre OpenZeppelin y T-REX Network, julio de 2026.

Normativa y legislación

  • FDA. "Requirements for Additional Traceability Records for Certain Foods." Norma definitiva, Federal Register 87(219), 2022; "Compliance Date Extension," Federal Register, 7 de agosto de 2025.
  • Reglamento (UE) 2023/1115 (deforestación); Reglamento (UE) 2025/2650 (modificación); nota de prensa del Consejo de la UE, 18 de diciembre de 2025.
  • Reglamento (UE) 2023/1114 (MiCA); Directrices de la ESMA sobre la calificación de los criptoactivos como instrumentos financieros, diciembre de 2024.
  • Comité Europeo de Protección de Datos. "Guidelines 02/2025 on processing of personal data through blockchain technologies," versión 2.0, 7 de julio de 2026.
  • SEC. Release No. 33-11412, 17 de marzo de 2026. SEC v. W.J. Howey Co., 328 U.S. 293 (1946).
  • GENIUS Act, Public Law 119-27 (2025); reglamentos de desarrollo, Federal Register, 18 de agosto de 2026.
  • Uniform Commercial Code, Enmiendas de 2022, Artículo 12 (Controllable Electronic Records).
  • U.S. Warehouse Act; 7 CFR Part 869 (Electronic Warehouse Receipts).
  • UNCITRAL. "Model Law on Electronic Transferable Records." 2017. Reino Unido, Electronic Trade Documents Act 2023.
  • Comisión Nacional de Valores (Argentina). Resolución General 1150/2026. Ley 9.643 (warrants).
  • Brasil. Lei 8.929/1994, Lei 13.986/2020 (CPR); Lei 11.076/2004 (CDA/WA); CVM Resolução 88 y Consulta Pública SDM 05/2025.
  • Verra. "Verra Addresses Crypto Instruments and Tokens." 2022; VCS Program Guide.
  • Directiva (UE) 2024/825 (empoderamiento de los consumidores para la transición ecológica).

Investigación y sector

  • Zhang, P., Schmidt, D. C. "Blockchain Applications in Food Supply Chain Management: A Systematic Review." Journal of Food Engineering, 279, 2020.
  • Caro, M. P. et al. "Blockchain-based Traceability in Agri-Food Supply Chain Management." IEEE, 2018.
  • FAO. "The State of Food and Agriculture." 2023.
  • Banco Mundial. "Future of Food: Harnessing Digital Technologies to Improve Food System Outcomes." 2022.
  • ERC3643 Association. "History of ERC-3643"; anuncio de la iniciativa de estandarización de ISO TC 307.
  • Chainlink. "Automated Compliance Engine (ACE): Technical Overview." 2025–2026.

Apéndice D: Plantillas

D.1 Hook mínimo

Fuente: contracts/examples/MyHook.sol (importa ../reference/hooks/ARexHookBase.sol y ../standard/IARexBatch.sol).

contract MyHook is ARexHookBase {
    function hookFlags() public pure override returns (uint8) {
        return ARexCodes.HOOK_CHECK;
    }


    function check(uint8 op, address, address, address, uint256 id, uint256, bytes calldata)
        external
        view
        override
        returns (bytes32)
    {
        if (op != ARexCodes.OP_TRANSFER) return ARexCodes.OK;
        IARexBatch.Batch memory b = IARexBatch(msg.sender).batchOf(id);
        b; // decide from b.commodity, b.producedAt, b.expiresAt, b.status ...
        return ARexCodes.OK;
    }
}

D.2 Despliegue (plugin de actualizaciones)

const token = await upgrades.deployProxy(await ethers.getContractFactory("ARexToken"), [admin, baseURI], { kind: "uups" });
const attestations = await (await ethers.getContractFactory("ARexAttestations")).deploy(admin, await token.getAddress());
await token.registerHook(await (await ethers.getContractFactory("EligibilityHook")).deploy(admin));
await token.registerHook(await (await ethers.getContractFactory("ExpiryHook")).deploy(true));

D.3 Esqueleto de metadatos

{ "schemaVersion": "1.0.0", "commodity": { "scheme": "HS", "code": "100199" }, "unit": "KGM", "quantity": 250000,
  "traceabilityLotCode": "…", "production": { "producedAt": "…" }, "origin": { "country": "AR", "originRef": "…" },
  "status": { "table": { "1": "IN_STORAGE" } }, "documents": [ { "type": "warehouse_receipt", "hash": "…", "registryId": "…" } ],
  "restricted": { "uri": "…", "hash": "…", "accessPolicy": "…" } }

Apéndice E: Preguntas frecuentes

¿Es A-REX un ERC? Todavía no. La especificación está escrita en formato ERC y se presentará tras un despliegue en producción, implementaciones independientes y una auditoría. No se ha asignado ningún número; los nombres en el código no usan el prefijo ERC.

¿Es obligatorio usar ARexToken? No. Las interfaces pueden implementarse de cualquier manera; la referencia es solo una de ellas.

¿Es obligatorio usar los hooks de referencia? No. Son demostraciones. Pueden copiarse, sustituirse o escribirse otros propios.

¿Puede un hook bloquear una transferencia forzosa? Puede devolver un código para OP_FORCED_TRANSFER, y el token revertirá. Los hooks de referencia no lo hacen; un hook que gobierne la ejecución forzosa (por ejemplo, exigiendo una referencia de orden) puede hacerlo.

¿Dónde van las coordenadas? En un almacenamiento restringido fuera de la cadena, referenciado desde los metadatos; nunca en la cadena.

¿Cómo se representa una cosecha futura? producedAt = 0; las transferencias se controlan con ExpiryHook(allowPreHarvestTransfers).

¿Se conserva la cantidad en transform? No por el estándar; la referencia permite que cualquier titular reagrupe cuando se conserva y exige TRANSFORMER_ROLE en caso contrario.

¿Es el token un valor? El estándar no lo decide. Lo decide la oferta. Consúltese a un asesor jurídico; la superficie de ejecución forzosa está ahí sea cual sea la respuesta.