Whitepaper · 16
Приложения
Авторитетные источники: contracts/standard/ .sol (CC0) и standard/AREX CORE.md. Идентификаторы интерфейсов воспроизводятся командой npm run interface ids.
Приложение A: Справочник по интерфейсам
Авторитетные источники: contracts/standard/*.sol (CC0) и standard/AREX-CORE.md. Идентификаторы интерфейсов воспроизводятся командой npm run interface-ids.
A.1 Сводка конформности
| Интерфейс | Идентификатор ERC-165 | Токен | Хук |
|---|---|---|---|
IERC1155 | 0xd9b67a26 | ДОЛЖЕН | — |
IERC7943MultiToken | 0x41c4fbad | ДОЛЖЕН | — |
IARexBatch | 0xe22639e0 | ДОЛЖЕН | — |
IARexHookManager | 0x964f4861 | ДОЛЖЕН (getHooks) | — |
IARexAttest | 0xad603a6c | СЛЕДУЕТ (токен или сопутствующий контракт) | — |
IARexHook | 0x332afcbb | — | ДОЛЖЕН |
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, дословно)
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 и 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 Константы (ARexCodes)
| Группа | Значения |
|---|---|
| Операции | OP_MINT = 1, OP_TRANSFER = 2, OP_BURN = 3, OP_FORCED_TRANSFER = 4, OP_TRANSFORM = 5 |
| Флаги хуков | HOOK_CHECK = 1, HOOK_EXECUTED = 2, HOOK_ELIGIBILITY = 4 |
| Статус | STATUS_ACTIVE = 0, STATUS_RETIRED = 255 |
Коды (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 |
| Вспомогательные функции | commodity(scheme, code), unit(code), topic(name), code(namespace, name) |
A.7 Роли эталонной реализации
ISSUER_ROLE, TRANSFORMER_ROLE, STATUS_ROLE, ENFORCER_ROLE, HOOK_ADMIN_ROLE, PAUSER_ROLE, UPGRADER_ROLE, DEFAULT_ADMIN_ROLE в ARexToken (каждая — keccak256("AREX_<NAME>")); ATTEST_ADMIN_ROLE в ARexAttestations. Дополнительные view-функции: isExpired(id), transferCheck(from, to, id, amount); дополнительная функция: burn(from, id, amount); слот ERC-7201 0x8ed599b6be05dec05297c009a1279a71df771ad996fe924d0b5a47326ff60900.
A.8 Эталонные хуки и расширения
| Контракт | Вид | Ключевые функции |
|---|---|---|
PerishabilityHook | хук | setCommodityDecay, setBatchDecay, valueBps, secondsRemaining, isExpired |
SeasonalHook | хук | addWindow, clearWindows, windowsOf, isOpen |
DeliveryHook | хук | schedule, pickUp, markInTransit, recordReading, confirmDelivered, cancel, dispute, resolve, getDelivery, lockedUnits |
TraceabilityHook | хук | recordEvent, eventCount, getEvents; флаг конструктора persist |
CommodityPriceOracle | расширение | submit, finalizeRound, latestAnswer, getRound, currentRound, isStale, setParameters |
CarbonImmobilizationWrapper | расширение | recordImmobilization, linkToBatch, retire, release, attestBacking, backingOf, linksOf |
ParametricInsurance | расширение | fund, issue, claim, expire, getPolicy, freeCapacity |
A.9 Схема метаданных
standard/schema/batch-metadata.schema.json (JSON Schema 2020-12). Обязательные: schemaVersion, commodity{scheme, code}, unit, quantity. Заметные необязательные группы: 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[]. Пример — в standard/examples/batch-metadata.example.json.
Приложение B: Глоссарий
| Термин | Значение |
|---|---|
| Партия | Идентификатор токена ERC-1155 с записью Batch: лот одного товара в одной единице измерения с общим происхождением и временем производства. |
| Переформирование партий | transform, выходы которого имеют тот же товар и ту же единицу измерения, что и входы, а количества сохраняются (разделение, объединение). В эталонной реализации доступно держателям. |
| Переработка | transform, изменяющий товар, единицу измерения или количество. В эталонной реализации требует TRANSFORMER_ROLE. |
| Родословная | Граф, образуемый событиями BatchTransformed и parentsOf. |
| Хук | Контракт, реализующий IARexHook, зарегистрированный в токене и вычисляемый по порядку при каждой операции. |
| Код отказа | bytes32, возвращаемый check хука; 0 означает «разрешено»; соглашение — keccak256("NAMESPACE:NAME"). |
| Допуск | Разрешение на уровне аккаунта отправлять или получать, на которое отвечают хуки с флагом HOOK_ELIGIBILITY; предоставляется как canSend/canReceive из ERC-7943. |
| Замороженный баланс | Единицы, которыми аккаунт владеет, но не может перемещать (setFrozenTokens); может превышать баланс. |
| Принудительный перевод | Перемещение единиц ролью ENFORCER_ROLE без согласия держателя (ERC-7943). |
| Аттестация | (batch, topic) → (issuer, reference, validity), записанная доверенным эмитентом по данной теме. |
| Тема | bytes32, идентифицирующий предмет аттестации; открытое значение; соответствует темам утверждений ERC-735 и идентификаторам схем EAS. |
| Ссылка на происхождение | originRef: хеш или ссылка на доказательства происхождения; никогда не координаты. |
| Коммитмент метаданных | metadataHash, keccak256 канонического офчейн-документа по адресу uri. |
| Статус | значение жизненного цикла uint8; 0 — активна, 255 — погашена (терминальное значение); 1..254 определяются эмитентом. |
| CTE / KDE | Критическое событие отслеживания / ключевой элемент данных (FSMA 204). |
| DDS | Заявление о должной осмотрительности (EUDR). |
| EPCIS | GS1 Electronic Product Code Information Services — словарь событий для прослеживаемости (версия 2.0). |
| CPR / CPR-e | Cédula de Produto Rural — бразильская дебиторская задолженность по урожаю; электронная форма регистрируется в уполномоченных организациях. |
| EWR | Электронная складская расписка по U.S. Warehouse Act. |
| MLETR | Типовой закон ЮНСИТРАЛ об электронных передаваемых записях. |
| ERC-7943 (uRWA) | Универсальный интерфейс реального актива (Universal Real World Asset): заморозка, принудительный перевод, допуск; статус Final, май 2026 г. |
| ERC-3643 (T-REX) | Стандарт токенов с разрешительным доступом для ценных бумаг на основе ERC-20; статус Final, декабрь 2023 г. |
| ERC-7201 | Раскладка хранилища с пространствами имён для обновляемых контрактов. |
Приложение C: Библиография
Стандарты и спецификации
- Radomski, W. и др. «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 декабря 2023 г. https://eips.ethereum.org/EIPS/eip-3643
- «ERC-7943: uRWA — Universal Real World Asset Interface». Final, 27 мая 2026 г. https://eips.ethereum.org/EIPS/eip-7943
- «ERC-7201: Namespaced Storage Layout». 2023.
- «ERC-735: Claim Holder». 2017 (черновик).
- Документация 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.
- Документация OpenZeppelin Contracts 5.x; сообщение о партнёрстве OpenZeppelin и T-REX Network, июль 2026 г.
Регулирование и право
- FDA. «Requirements for Additional Traceability Records for Certain Foods». Окончательное правило, Federal Register 87(219), 2022; «Compliance Date Extension», Federal Register, 7 августа 2025 г.
- Регламент (ЕС) 2023/1115 (об обезлесении); Регламент (ЕС) 2025/2650 (изменение); пресс-релиз Совета ЕС от 18 декабря 2025 г.
- Регламент (ЕС) 2023/1114 (MiCA); руководящие принципы ESMA по квалификации криптоактивов в качестве финансовых инструментов, декабрь 2024 г.
- European Data Protection Board. «Guidelines 02/2025 on processing of personal data through blockchain technologies», версия 2.0, 7 июля 2026 г.
- SEC. Release No. 33-11412, 17 марта 2026 г. SEC v. W.J. Howey Co., 328 U.S. 293 (1946).
- GENIUS Act, Public Law 119-27 (2025); подзаконные акты, Federal Register, 18 августа 2026 г.
- Uniform Commercial Code, поправки 2022 г., статья 12 (контролируемые электронные записи).
- U.S. Warehouse Act; 7 CFR Part 869 (электронные складские расписки).
- UNCITRAL. «Model Law on Electronic Transferable Records». 2017. Великобритания, Electronic Trade Documents Act 2023.
- Comisión Nacional de Valores (Аргентина). Resolución General 1150/2026. Ley 9.643 (варранты).
- Бразилия. Lei 8.929/1994, Lei 13.986/2020 (CPR); Lei 11.076/2004 (CDA/WA); CVM Resolução 88 и Consulta Pública SDM 05/2025.
- Verra. «Verra Addresses Crypto Instruments and Tokens». 2022; VCS Program Guide.
- Директива (ЕС) 2024/825 (о расширении прав потребителей в интересах «зелёного» перехода).
Исследования и отрасль
- Zhang, P., Schmidt, D. C. «Blockchain Applications in Food Supply Chain Management: A Systematic Review». Journal of Food Engineering, 279, 2020.
- Caro, M. P. и др. «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»; объявление об инициативе по стандартизации ISO TC 307.
- Chainlink. «Automated Compliance Engine (ACE): Technical Overview». 2025–2026.
Приложение D: Шаблоны
D.1 Минимальный хук
Источник: contracts/examples/MyHook.sol (импортирует ../reference/hooks/ARexHookBase.sol и ../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 Развёртывание (плагин upgrades)
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 Каркас метаданных
{ "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": "…" } }
Приложение E: Часто задаваемые вопросы
Является ли A-REX ERC? Пока нет. Спецификация написана в формате ERC и будет подана после промышленного развёртывания, независимых реализаций и аудита. Номер не присвоен; имена в коде не используют префикс ERC.
Обязательно ли использовать ARexToken? Нет. Интерфейсы можно реализовать любым способом; эталонная реализация — лишь один из них.
Обязательно ли использовать эталонные хуки? Нет. Это демонстрации. Их можно скопировать, заменить или написать собственные.
Может ли хук заблокировать принудительный перевод? Он может вернуть код для OP_FORCED_TRANSFER, и токен откатит транзакцию. Эталонные хуки этого не делают; хук, регулирующий принудительное исполнение (например, требующий ссылку на распоряжение), может.
Куда помещать координаты? В офчейн-хранилище с ограниченным доступом, на которое ссылаются метаданные, но никогда не ончейн.
Как представить будущий урожай? producedAt = 0; переводы ограничиваются с помощью ExpiryHook(allowPreHarvestTransfers).
Сохраняется ли количество в transform? Стандартом — нет; эталонная реализация позволяет любому держателю переформировать партии, когда количество сохраняется, и требует TRANSFORMER_ROLE в остальных случаях.
Является ли токен ценной бумагой? Стандарт этого не решает. Решает предложение. Следует обратиться к юристам; поверхность принудительного исполнения присутствует при любом ответе.