Skip to main contentA-REX Core

Whitepaper · 13

Análisis de rendimiento

Gas medido de la implementación de referencia con cero, uno y dos hooks; qué determina el coste; y orientaciones de despliegue.

Método

Las cifras siguientes proceden de scripts/gas-report-standard.js, ejecutado en la red en proceso de Hardhat contra la implementación de referencia compilada (solc 0.8.22, viaIR, optimizer.runs = 1 para ARexToken), en septiembre de 2026. «En caliente» significa el mismo par remitente/destinatario/id que la transferencia anterior (slots de almacenamiento ya tocados en el bloque). Hooks: EligibilityHook (CHECK + ELIGIBILITY) y ExpiryHook (CHECK). Para reproducirlo:

npx hardhat run scripts/gas-report-standard.js

Resultados

xychart-beta
    title "Gas de una transferencia en caliente según el número de hooks (miles)"
    x-axis ["sin hooks", "Eligibility", "Eligibility + Expiry"]
    y-axis "gas (k)" 0 --> 140
    bar [66.8, 91.2, 119.6]

El coste crece linealmente con el número de hooks: cada uno supone una llamada externa a check por id, más canSend y canReceive en el caso de un hook de elegibilidad. La tabla indica cada operación.

Operación0 hooks1 hook2 hooks
createBatch (id nuevo, acuñación de 1000)264,096283,831299,396
safeTransferFrom (primera, en frío)80,687108,266136,682
safeTransferFrom (en caliente)66,79091,166119,582
transform división 1 → 2 (dos ids nuevos)564,422595,707636,858
setFrozenTokens54,18854,18854,188
forcedTransfer80,15289,90999,569
burn66,62183,00193,395

Transferencia en caliente con exactamente un hook de cada tipo (coste marginal de la regla):

xychart-beta horizontal
    title "Gas marginal de un hook en una transferencia en caliente (miles)"
    x-axis ["DeliveryHook", "Traceability (emisión)", "EligibilityHook", "ExpiryHook", "SeasonalHook", "PerishabilityHook"]
    y-axis "gas añadido (k)" 0 --> 35
    bar [12.3, 17.4, 24.4, 25.2, 27.5, 31.0]

TraceabilityHook en modo persistente añade 184.5k y se omite del gráfico por razones de escala.

HookGasΔ frente a sin hook
EligibilityHook91,166+24,376
ExpiryHook92,023+25,233
SeasonalHook94,324+27,534
PerishabilityHook97,813+31,023
DeliveryHook (sin entrega activa)79,076+12,286
TraceabilityHook, solo emisión84,152+17,362
TraceabilityHook, persistente251,273+184,483

Qué determina el coste

  • Una transferencia sin hooks cuesta ~67k en caliente, es decir, ERC-1155 más el seguimiento del suministro más las lecturas de existencia, estado y congelación del lote y la gestión interna de la canalización (almacenamiento temporal de datos, bloqueo). Este es el mínimo.
  • Cada hook añade aproximadamente 25–30k a una transferencia: una llamada a check (vista, entre contratos) más, en el caso de los hooks de elegibilidad, las llamadas a canSend y canReceive. El coste es lineal en el número de hooks y en el número de ids de una transferencia múltiple. Sondear cada contrato de reglas para cada capacidad con supportsInterface antes de llamarlo añadiría varias llamadas estáticas por id; esa sobrecarga no existe porque los indicadores se almacenan en caché en el registro.
  • createBatch está dominado por el almacenamiento: el struct Batch (seis palabras más una cadena de texto) y los slots de saldo y de suministro de ERC-1155. Es un coste único por lote.
  • transform crea ids nuevos: una división en dos paga dos registros de lote, más dos acuñaciones, más una quema, más las llamadas a hooks en cada tramo (OP_TRANSFORM). Una división en n cuesta aproximadamente n × createBatch más una quema; fusionar n en uno cuesta aproximadamente n quemas más un createBatch.
  • La ejecución forzosa es barata: congelar es un solo slot; una transferencia forzosa cuesta lo que cuesta una transferencia más la escritura de descongelación y el evento.
  • transferCheck / canTransfer son vistas: gratuitas fuera de la cadena y con la misma ruta de código que la transacción.

Lo que aporta el diseño

Diseño con sondeo de capacidadesA-REX Core (ARexToken)
Transferencia con n contratos de reglasids × módulos × (sondeos de supportsInterface + llamada al hook) antes de que se ejecute ninguna lógicaids × hooks × 1 llamada (+2 para los hooks de elegibilidad); indicadores en caché en el registro
Rechazoreversión con cadena de texto (copiada a memoria, no indexable)error personalizado con la dirección del hook y un código bytes32
Linajeno disponible~280k por lote de salida
Congelación / transferencia forzosano disponible54k / 80k

La columna izquierda describe el diseño que A-REX Core sustituye (ADR-004, ADR-005); solo la columna derecha está medida.

Orientaciones de despliegue

  • El coste en dinero es gas × gas price × token price, y los dos últimos factores cambian en órdenes de magnitud entre cadenas y entre días. Solo a modo ilustrativo, a 0.01 gwei y 3,000 USD por ETH, una transferencia en caliente con dos hooks (119,582 gas) cuesta unos 0.0036 USD y un createBatch (264,096 gas) unos 0.008 USD; a 20 gwei en la red principal de Ethereum, las mismas operaciones cuestan unos 7.2 y 15.8 USD. Mídase en la cadena de destino antes de comprometerse con un modelo de economía unitaria.
  • Transferencias múltiples: safeBatchTransferFrom amortiza los costes fijos; el coste de los hooks sigue escalando con el número de ids.
  • Orden de los hooks: colóquense primero los hooks baratos y de alto rechazo; un rechazo detiene la canalización antes de que se ejecuten hooks más caros.
  • Número de hooks: entre tres y cinco bastan para la mayoría de los emisores; cada hook adicional supone un coste medible por transferencia y una superficie de gobernanza.
  • Metadatos: manténgase uri corta (un CID o un Digital Link); la cadena de texto se almacena en la cadena.
  • Lecturas fuera de la cadena: úsese transferCheck antes de enviar; una transacción revertida sigue costando gas.

Capacidad de procesamiento

El cuello de botella no es el token, sino la cadena. Una transferencia individual es una transacción; una transformación con n salidas es una transacción con n acuñaciones. Indexar el linaje requiere leer los eventos BatchTransformed, que se emiten una vez por operación con las listas completas de cantidades, de modo que un indexador no necesita reconstruir nada a partir de los eventos por transferencia.

Tamaño de los contratos

ARexToken se despliega con 24,136 bytes (límite 24,576), compilado con optimizer.runs = 1. Los demás contratos son pequeños: ARexAttestations 2,708; hooks entre 1,358 (ExpiryHook) y 6,215 (DeliveryHook), TraceabilityHook 4,076; extensiones entre 3,716 y 4,588. Añadir funcionalidad al propio token está limitado por el tamaño por diseño: para eso sirven los hooks y los contratos complementarios.