Whitepaper · 16
Apêndices
Fontes de referência: contracts/standard/ .sol (CC0) e standard/AREX CORE.md. Identificadores de interface reproduzidos por npm run interface ids.
Apêndice A: Referência de Interfaces
Fontes de referência: contracts/standard/*.sol (CC0) e standard/AREX-CORE.md. Identificadores de interface reproduzidos por npm run interface-ids.
A.1 Resumo de conformidade
| Interface | ID ERC-165 | Token | Hook |
|---|---|---|---|
IERC1155 | 0xd9b67a26 | DEVE | — |
IERC7943MultiToken | 0x41c4fbad | DEVE | — |
IARexBatch | 0xe22639e0 | DEVE | — |
IARexHookManager | 0x964f4861 | DEVE (getHooks) | — |
IARexAttest | 0xad603a6c | DEVERIA (token ou complementar) | — |
IARexHook | 0x332afcbb | — | DEVE |
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 e 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)
| Grupo | Valores |
|---|---|
| Operações | OP_MINT = 1, OP_TRANSFER = 2, OP_BURN = 3, OP_FORCED_TRANSFER = 4, OP_TRANSFORM = 5 |
| Flags de hook | HOOK_CHECK = 1, HOOK_EXECUTED = 2, HOOK_ELIGIBILITY = 4 |
| Status | STATUS_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 |
| Auxiliares | commodity(scheme, code), unit(code), topic(name), code(namespace, name) |
A.7 Papéis da implementação de referência
ISSUER_ROLE, TRANSFORMER_ROLE, STATUS_ROLE, ENFORCER_ROLE, HOOK_ADMIN_ROLE, PAUSER_ROLE, UPGRADER_ROLE, DEFAULT_ADMIN_ROLE em ARexToken (cada um keccak256("AREX_<NAME>")); ATTEST_ADMIN_ROLE em ARexAttestations. Views adicionais: isExpired(id), transferCheck(from, to, id, amount); função adicional: burn(from, id, amount); slot ERC-7201 0x8ed599b6be05dec05297c009a1279a71df771ad996fe924d0b5a47326ff60900.
A.8 Hooks e extensões de referência
| Contrato | Tipo | Funções principais |
|---|---|---|
PerishabilityHook | hook | setCommodityDecay, setBatchDecay, valueBps, secondsRemaining, isExpired |
SeasonalHook | hook | addWindow, clearWindows, windowsOf, isOpen |
DeliveryHook | hook | schedule, pickUp, markInTransit, recordReading, confirmDelivered, cancel, dispute, resolve, getDelivery, lockedUnits |
TraceabilityHook | hook | recordEvent, eventCount, getEvents; flag de construtor persist |
CommodityPriceOracle | extensão | submit, finalizeRound, latestAnswer, getRound, currentRound, isStale, setParameters |
CarbonImmobilizationWrapper | extensão | recordImmobilization, linkToBatch, retire, release, attestBacking, backingOf, linksOf |
ParametricInsurance | extensão | fund, issue, claim, expire, getPolicy, freeCapacity |
A.9 Esquema de metadados
standard/schema/batch-metadata.schema.json (JSON Schema 2020-12). Obrigatórios: schemaVersion, commodity{scheme, code}, unit, quantity. Grupos opcionais notáveis: 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[]. Exemplo em standard/examples/batch-metadata.example.json.
Apêndice B: Glossário
| Termo | Significado |
|---|---|
| Lote | Um identificador de token ERC-1155 com um registro Batch: um lote de uma commodity em uma unidade, com origem e data de produção comuns. |
| Reagrupamento | Uma transform cujas saídas têm a mesma commodity e a mesma unidade das entradas e cujas quantidades são conservadas (divisão, união). Aberta aos titulares na implementação de referência. |
| Processamento | Uma transform que altera a commodity, a unidade ou a quantidade. Exige TRANSFORMER_ROLE na implementação de referência. |
| Linhagem | O grafo formado pelos eventos BatchTransformed e por parentsOf. |
| Hook | Um contrato que implementa IARexHook, registrado em um token e avaliado em ordem em toda operação. |
| Código de rejeição | Um bytes32 retornado por check de um hook; 0 significa permitido; convenção keccak256("NAMESPACE:NAME"). |
| Elegibilidade | Permissão, no nível da conta, para enviar ou receber, respondida por hooks sinalizados com HOOK_ELIGIBILITY; exposta como canSend/canReceive do ERC-7943. |
| Saldo congelado | Unidades que uma conta detém, mas não pode mover (setFrozenTokens); pode exceder o saldo. |
| Transferência forçada | Movimentação de unidades por ENFORCER_ROLE sem o consentimento do titular (ERC-7943). |
| Atestação | (batch, topic) → (issuer, reference, validity) registrada por um emissor confiável para aquele tópico. |
| Tópico | Um bytes32 que identifica o assunto de uma atestação; aberto; mapeia-se para tópicos de declaração do ERC-735 e para identificadores de esquema do EAS. |
| Referência de origem | originRef: um hash ou uma referência às evidências de origem; nunca coordenadas. |
| Compromisso de metadados | metadataHash, keccak256 do documento canônico off-chain em uri. |
| Status | Valor uint8 de ciclo de vida; 0 ativo, 255 baixado (terminal); 1..254 definidos pelo emissor. |
| CTE / KDE | Evento crítico de rastreamento / elemento-chave de dados (FSMA 204). |
| DDS | Declaração de devida diligência (EUDR). |
| EPCIS | GS1 Electronic Product Code Information Services, o vocabulário de eventos para rastreabilidade (versão 2.0). |
| CPR / CPR-e | Cédula de Produto Rural, o recebível de safra do Brasil; forma eletrônica registrada em entidades autorizadas. |
| EWR | Recibo de armazém eletrônico nos termos do U.S. Warehouse Act. |
| MLETR | Lei Modelo da UNCITRAL sobre Registros Eletrônicos Transferíveis. |
| ERC-7943 (uRWA) | Interface Universal de Ativos do Mundo Real: congelamento, transferência forçada, elegibilidade; Final em maio de 2026. |
| ERC-3643 (T-REX) | Padrão de token permissionado para valores mobiliários sobre ERC-20; Final em dezembro de 2023. |
| ERC-7201 | Layout de armazenamento com namespace para contratos atualizáveis. |
Apêndice C: Bibliografia
Padrões e especificações
- 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 dezembro de 2023. https://eips.ethereum.org/EIPS/eip-3643
- "ERC-7943: uRWA — Universal Real World Asset Interface." Final, 27 de maio de 2026. https://eips.ethereum.org/EIPS/eip-7943
- "ERC-7201: Namespaced Storage Layout." 2023.
- "ERC-735: Claim Holder." 2017 (rascunho).
- Documentação do 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.
- Documentação do OpenZeppelin Contracts 5.x; anúncio da parceria entre a OpenZeppelin e a T-REX Network, julho de 2026.
Regulamentação e legislação
- FDA. "Requirements for Additional Traceability Records for Certain Foods." Regra final, Federal Register 87(219), 2022; "Compliance Date Extension," Federal Register, 7 de agosto de 2025.
- Regulamento (UE) 2023/1115 (Desmatamento); Regulamento (UE) 2025/2650 (alteração); comunicado de imprensa do Conselho da UE, 18 de dezembro de 2025.
- Regulamento (UE) 2023/1114 (MiCA); Diretrizes da ESMA sobre a qualificação de criptoativos como instrumentos financeiros, dezembro de 2024.
- European Data Protection Board. "Guidelines 02/2025 on processing of personal data through blockchain technologies," versão 2.0, 7 de julho de 2026.
- SEC. Release No. 33-11412, 17 de março de 2026. SEC v. W.J. Howey Co., 328 U.S. 293 (1946).
- GENIUS Act, Public Law 119-27 (2025); regulamentação de implementação, Federal Register, 18 de agosto de 2026.
- Uniform Commercial Code, 2022 Amendments, Article 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); Resolução CVM 88 e Consulta Pública SDM 05/2025.
- Verra. "Verra Addresses Crypto Instruments and Tokens." 2022; VCS Program Guide.
- Diretiva (UE) 2024/825 (empoderamento dos consumidores para a transição ecológica).
Pesquisa e indústria
- 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.
- World Bank. "Future of Food: Harnessing Digital Technologies to Improve Food System Outcomes." 2022.
- ERC3643 Association. "History of ERC-3643"; anúncio da iniciativa de padronização do ISO TC 307.
- Chainlink. "Automated Compliance Engine (ACE): Technical Overview." 2025–2026.
Apêndice D: Modelos
D.1 Hook mínimo
Fonte: contracts/examples/MyHook.sol (importa ../reference/hooks/ARexHookBase.sol e ../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 Implantação (plugin de atualizações)
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 metadados
{ "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: Perguntas Frequentes
O A-REX é um ERC? Ainda não. A especificação está escrita em formato ERC e será submetida após uma implantação em produção, implementações independentes e uma auditoria. Nenhum número foi atribuído; os nomes no código não usam o prefixo ERC.
É obrigatório usar o ARexToken? Não. Implemente as interfaces da maneira que preferir; a referência é apenas uma das formas.
É obrigatório usar os hooks de referência? Não. São demonstrações. Copie-os, substitua-os ou escreva os próprios.
Um hook pode bloquear uma transferência forçada? Pode retornar um código para OP_FORCED_TRANSFER, e o token reverterá. Os hooks de referência não o fazem; um hook que trate de enforcement (por exemplo, exigindo uma referência de ordem) pode.
Onde ficam as coordenadas? Em armazenamento off-chain restrito, referenciado a partir dos metadados, nunca on-chain.
Como representar uma safra futura? producedAt = 0; condicione as transferências com ExpiryHook(allowPreHarvestTransfers).
A quantidade é conservada em transform? Não pelo padrão; a referência permite que qualquer titular faça o reagrupamento quando ela é conservada e exige TRANSFORMER_ROLE nos demais casos.
O token é um valor mobiliário? O padrão não decide. A oferta é que decide. Consulte assessoria jurídica; a superfície de enforcement está presente qualquer que seja a resposta.