Whitepaper · 04
Visión general de la solución
Arquitectura de A-REX Core: tres niveles con un único sentido de dependencia, la canalización de transferencia, los actores y cómo se despliegan las piezas.
Tres niveles, un único sentido de dependencia
A-REX separa lo que debe estandarizarse de lo que simplemente debe funcionar:
Las cuatro capas del estándar
flowchart TB
L3["Capa 3 · IARexAttest<br/>attest · revokeAttestation · isAttested · emisores de confianza por tema"]
L2["Capa 2 · IARexHook + IARexHookManager<br/>hookFlags · check → bytes32 · onExecuted · getHooks"]
L1["Capa 1 · IARexBatch<br/>createBatch · batchOf · setBatchStatus · setBatchMetadata · transform · parentsOf"]
L0["Capa 0 · ERC-1155 + ERC-165 + IERC7943MultiToken<br/>freeze · forcedTransfer · canSend · canReceive · canTransfer"]
L3 --- L2 --- L1 --- L0
classDef l3 fill:#edf5ff,stroke:#0f62fe,color:#161616
classDef l2 fill:#d0e2ff,stroke:#0f62fe,color:#161616
classDef l1 fill:#a6c8ff,stroke:#0f62fe,color:#161616
classDef l0 fill:#78a9ff,stroke:#0043ce,color:#161616
class L3 l3
class L2 l2
class L1 l1
class L0 l0Los dos niveles del repositorio y el sentido de la dependencia
flowchart LR
STD["<b>El estándar</b><br/>standard/ · contracts/standard/<br/>normativo · CC0"]
REF["<b>Implementación de referencia</b><br/>ARexToken · ARexAttestations<br/>MIT"]
DEMO["<b>Demostraciones</b><br/>7 hooks · 3 extensiones<br/>MIT · no normativo"]
STD -->|implementado por| REF -->|demostrado por| DEMO
DEMO -.->|dependen solo de las interfaces| STDEl estándar nunca depende de la referencia; el token nunca depende de los hooks. Si se eliminan todos los hooks y todas las extensiones, sigue existiendo un token conforme. Esta es la propiedad que permite a un tercero implementar A-REX sin adoptar nada de este repositorio salvo seis archivos de interfaz.
Qué es un lote
Un lote es un id de token ERC-1155 con un registro:
struct Batch {
address issuer; // who created it (or performed the transformation)
uint64 createdAt;
uint8 status; // 0 ACTIVE · 255 RETIRED (terminal) · 1..254 issuer-defined
bytes32 commodity; // keccak256("HS:100199"), keccak256("FAO:0111"), keccak256("GTIN:0779…")
bytes32 unit; // UN/CEFACT Rec. 20: "KGM", "TNE", "LTR", "BX"
uint64 producedAt; // 0 = not yet produced (pre-harvest)
uint64 expiresAt; // 0 = none
bytes32 originRef; // hash / reference to origin evidence — never coordinates
bytes32 metadataHash; // keccak256 of the off-chain document
string uri; // where the document is
}
Todo lo demás, más detallado (calidad, humedad, proteína, envasado, identificadores GS1, el código de lote de trazabilidad, la referencia de la declaración del EUDR, informes de laboratorio, la tabla de estados del emisor), reside en el documento de metadatos cuyo hash queda comprometido en la cadena. El documento sigue un JSON Schema publicado y alineado con EPCIS 2.0 y con los elementos de datos clave de la FSMA 204.
La canalización de transferencia
Todo cambio de saldo (acuñación, transferencia, quema, transferencia forzosa, transformación) pasa por un único punto de paso obligado en el token de referencia. El orden es fijo y auditable:
flowchart TD
A[safeTransferFrom / createBatch / burn / forcedTransfer / transform] --> B["bloqueo de reentrada"]
B --> C{"¿en pausa?"}
C -- sí, no forzada --> X1[EnforcedPause]
C -- no --> D{"canSend from / canReceive to<br/>conjunción de hooks ELIGIBILITY"}
D -- false --> X2[ERC7943CannotSend / CannotReceive]
D -- true --> E{"por id: ¿existe? ¿no está retirado?<br/>¿cantidad ≤ saldo − congelado?"}
E -- falla --> X3[ARexBatchNotFound / ARexBatchRetired /<br/>ERC7943InsufficientUnfrozenBalance]
E -- correcto --> F{"por id, por cada hook CHECK en orden:<br/>check → código"}
F -- código ≠ 0 --> X4["ARexHookRejected(hook, code)"]
F -- todos 0 --> G["saldos actualizados · suministro total registrado"]
G --> H["por id, por cada hook EXECUTED: onExecuted"]
H --> I["desbloqueo"]Dos vistas reproducen la misma lógica sin modificar el estado: canTransfer (booleano, como exige ERC-7943) y transferCheck (el primer código de rechazo, de modo que una interfaz pueda indicar al usuario por qué).
Las transferencias forzosas omiten la pausa y las comprobaciones de elegibilidad (la ejecución forzosa debe funcionar cuando todo lo demás está congelado), pero siguen ejecutando los hooks con OP_FORCED_TRANSFER, de modo que un hook puede exigir, por ejemplo, una referencia de orden judicial en los datos de la transferencia.
Linaje
transform es la operación única para dividir, fusionar y procesar:
graph LR
W1["trigo #1<br/>250 t · agricultor"] -- "transform (reagrupación)" --> W2["trigo #2<br/>100 t · comprador A"]
W1 -- "transform (reagrupación)" --> W3["trigo #3<br/>150 t · comprador B"]
W2 -- "transform (procesamiento, TRANSFORMER_ROLE)" --> F4["harina #4<br/>75 t · molino"]- La reagrupación (mismo producto básico, misma unidad, cantidad conservada) está abierta a cualquier titular u operador aprobado: una cooperativa que divide un lote de silo entre sus socios, un exportador que fusiona entregas.
- El procesamiento (cualquier otro caso) exige además
TRANSFORMER_ROLE. parentsOf(4) == [2],parentsOf(2) == [1]; un eventoBatchTransformedpor operación, que es unTransformationEventde EPCIS por construcción.
Ejecución forzosa
ENFORCER_ROLE puede congelar cualquier cantidad de cualquier cuenta (setFrozenTokens, que puede superar el saldo, como especifica ERC-7943) y mover tokens sin el consentimiento del titular (forcedTransfer). Esto es lo que hace utilizable un token de lote fuera de una demostración: un prestamista que ejecuta un warrant, un tribunal que ordena la incautación de grano almacenado, un almacén que recupera un lote después de que un cliente pierde sus claves. Toda acción de ejecución forzosa es un evento.
Hooks
Un hook es un contrato con cinco funciones y un mapa de bits de indicadores constante. El token almacena en caché los indicadores en el momento del registro, de modo que una transferencia cuesta una llamada externa por cada hook interesado, y no un sondeo de interfaz por capacidad y por módulo. Un hook averigua qué token lo llama a partir de msg.sender; un mismo despliegue puede servir a muchos tokens.
Los hooks de referencia demuestran las tres capacidades:
| Hook | Capacidad | Qué demuestra |
|---|---|---|
EligibilityHook | CHECK + ELIGIBILITY | las listas de permitidos/bloqueados y de sanciones alimentan canSend / canReceive y producen códigos precisos |
ExpiryHook | CHECK | control de perecibilidad y de precosecha derivado únicamente del registro del lote |
AttestationHook | CHECK | «el café necesita una declaración del EUDR atestada antes de poder venderse» |
PerishabilityHook | CHECK | modelos de decaimiento y vistas de valor; los lotes caducados o sin valor no se mueven |
SeasonalHook | CHECK | ventanas de cosecha y de comercialización por producto básico |
DeliveryHook | CHECK + EXECUTED | bloqueo de custodia durante la entrega; la liquidación es la propia transferencia, identificada mediante data |
TraceabilityHook | EXECUTED | registro de eventos con forma de EPCIS de cada operación, más eventos críticos de seguimiento manuales |
Extensiones complementarias (no son hooks): CommodityPriceOracle, CarbonImmobilizationWrapper, ParametricInsurance.
Atestaciones
Un contrato complementario registra (batch, topic) → (issuer, reference, validity). Solo los emisores de confianza para un tema pueden atestar; la revocación, la caducidad y la pérdida de confianza hacen que isAttested sea falso. Los temas son bytes32, de modo que los temas de declaración de ERC-735, los ids de esquema de Ethereum Attestation Service y los hashes de nombres de certificación funcionan sin una tabla en el estándar.
Actores y roles
| Actor | Rol típico en el token de referencia | Acción típica |
|---|---|---|
| Plataforma originadora, cooperativa, elevador de granos | ISSUER_ROLE | createBatch |
| Agricultor / titular | ninguno | transferir, reagrupar, quemar |
| Molino, envasador, procesador | TRANSFORMER_ROLE | transform de procesamiento |
| Almacén, inspector, plataforma | STATUS_ROLE | setBatchStatus, setBatchMetadata |
| Certificador, laboratorio, autoridad | emisor de confianza para un tema | attest |
| Prestamista, custodio designado por el tribunal, cumplimiento | ENFORCER_ROLE | setFrozenTokens, forcedTransfer |
| Gobernanza (multifirma, timelock) | DEFAULT_ADMIN_ROLE, HOOK_ADMIN_ROLE, UPGRADER_ROLE, PAUSER_ROLE | roles, hooks, actualizaciones, pausa |
Nada en el estándar fija estos roles; son la forma en que la implementación de referencia ejerce los requisitos obligatorios («restringido a un rol autorizado»).
Formas de despliegue
- L2 público (Polygon, Arbitrum, Base, Optimism): el más económico y componible; adecuado para la comercialización y la financiación de productos básicos cuando las contrapartes son empresas.
- Cadena EVM con permisos: cuando lo exijan las autoridades de protección de datos o la institución ancla; el EDPB fomenta expresamente los diseños con permisos. El estándar es agnóstico respecto de la cadena.
- Híbrido: lotes en una cadena pública, datos restringidos (polígonos de parcelas, identidad del productor) tras un almacenamiento con control de acceso referenciado desde los metadatos.
El conjunto de referencia se despliega con un módulo de Ignition o con un script: proxy del token, registro de atestaciones, hooks de elegibilidad y de caducidad.
Decisiones de diseño y las alternativas que sustituyen
| Alternativa considerada | A-REX Core | Motivo |
|---|---|---|
| una interfaz de núcleo amplia con enumeraciones para producto básico, calidad y estado | IARexBatch de 8 funciones con códigos abiertos | nada que redesplegar para un nuevo cultivo, esquema o ciclo de vida |
| interfaces de capacidades sondeadas en cada transferencia | una única interfaz de hook, con indicadores en caché | gas lineal en el número de hooks, no en ids × módulos × sondeos |
| motivos en forma de cadena de texto | códigos bytes32 y errores tipados | legibles por máquina, indexables |
| estado del ciclo de vida modificable por cualquier titular | solo mediante rol; RETIRED es terminal | seguridad |
| fecha de cosecha obligatoriamente en el pasado | se admite producedAt == 0 | financiación de precosecha |
| sin división / fusión / procesamiento | transform + parentsOf | trazabilidad, retiradas de producto, EPCIS |
| sin congelación ni transferencia forzosa | ERC-7943 | exigibilidad |
| coordenadas almacenadas en la cadena | solo referencia de origen | GDPR / EDPB 02/2025 |
| se exigen contratos de registro y de identidad | no se exige nada | sin una pila de identidad impuesta |