Whitepaper · 13
Análise de Desempenho
Gás medido da implementação de referência com zero, um e dois hooks; o que determina o custo; e orientações de implantação.
Método
Os números abaixo vêm de scripts/gas-report-standard.js, executado na rede em processo do Hardhat contra a implementação de referência compilada (solc 0.8.22, viaIR, optimizer.runs = 1 para ARexToken), em setembro de 2026. "Quente" significa o mesmo par remetente/destinatário/id da transferência anterior (slots de armazenamento já tocados no bloco). Hooks: EligibilityHook (CHECK + ELIGIBILITY) e ExpiryHook (CHECK). Para reproduzir:
npx hardhat run scripts/gas-report-standard.js
Resultados
xychart-beta
title "Gás de transferência quente por número de hooks (milhares)"
x-axis ["sem hooks", "Eligibility", "Eligibility + Expiry"]
y-axis "gás (k)" 0 --> 140
bar [66.8, 91.2, 119.6]O custo cresce linearmente com o número de hooks: cada um é uma chamada externa a check por id, mais canSend e canReceive no caso de um hook de elegibilidade. A tabela apresenta todas as operações.
| Operação | 0 hooks | 1 hook | 2 hooks |
|---|---|---|---|
createBatch (novo id, cunhagem de 1000) | 264,096 | 283,831 | 299,396 |
safeTransferFrom (primeira, fria) | 80,687 | 108,266 | 136,682 |
safeTransferFrom (quente) | 66,790 | 91,166 | 119,582 |
transform divisão 1 → 2 (dois novos ids) | 564,422 | 595,707 | 636,858 |
setFrozenTokens | 54,188 | 54,188 | 54,188 |
forcedTransfer | 80,152 | 89,909 | 99,569 |
burn | 66,621 | 83,001 | 93,395 |
Transferência quente com exatamente um hook de cada tipo (custo marginal da regra):
xychart-beta horizontal
title "Gás marginal de um hook em uma transferência quente (milhares)"
x-axis ["DeliveryHook", "Traceability (emissão)", "EligibilityHook", "ExpiryHook", "SeasonalHook", "PerishabilityHook"]
y-axis "gás adicionado (k)" 0 --> 35
bar [12.3, 17.4, 24.4, 25.2, 27.5, 31.0]TraceabilityHook no modo persistido acrescenta 184.5k e foi deixado de fora do gráfico por causa da escala.
| Hook | Gás | Δ vs. sem hook |
|---|---|---|
| EligibilityHook | 91,166 | +24,376 |
| ExpiryHook | 92,023 | +25,233 |
| SeasonalHook | 94,324 | +27,534 |
| PerishabilityHook | 97,813 | +31,023 |
| DeliveryHook (nenhuma entrega ativa) | 79,076 | +12,286 |
| TraceabilityHook, apenas emissão | 84,152 | +17,362 |
| TraceabilityHook, persistido | 251,273 | +184,483 |
O que determina o custo
- Uma transferência sem hooks custa ~67k a quente, isto é, o ERC-1155 mais o controle da oferta mais as leituras de existência/status/congelamento do lote e a contabilidade do pipeline (armazenamento temporário dos dados, trava). Esse é o piso.
- Cada hook acrescenta aproximadamente 25–30k a uma transferência: uma chamada a
check(view, entre contratos) mais, para hooks de elegibilidade, as chamadas acanSendecanReceive. O custo é linear no número de hooks e no número de ids em uma transferência múltipla. Sondar cada contrato de regra para cada capacidade comsupportsInterfaceantes de chamá-lo acrescentaria várias chamadas estáticas por id; esse custo adicional não existe porque as flags são armazenadas em cache no registro. createBatché dominado pelo armazenamento: a structBatch(seis palavras mais uma string) e os slots de saldo e de oferta do ERC-1155. É um custo único por lote.transformcria novos ids: uma divisão em dois paga dois registros de lote, mais duas cunhagens, mais uma queima, mais as chamadas aos hooks em cada etapa (OP_TRANSFORM). Uma divisão em n custa aproximadamenten × createBatchmais uma queima; unir n em um custa aproximadamentenqueimas mais um createBatch.- O enforcement é barato: congelar é um slot; uma transferência forçada custa o que custa uma transferência mais a escrita de descongelamento e o evento.
transferCheck/canTransfersão views: gratuitas off-chain e com o mesmo caminho de código da transação.
O que o projeto proporciona
| Projeto com sondagem de capacidades | A-REX Core (ARexToken) | |
|---|---|---|
| Transferência com n contratos de regra | ids × módulos × (sondagens supportsInterface + chamada ao hook) antes de qualquer lógica ser executada | ids × hooks × 1 chamada (+2 para hooks de elegibilidade); flags em cache no registro |
| Rejeição | revert com string (copiada para a memória, não indexável) | erro personalizado com o endereço do hook e um código bytes32 |
| Linhagem | indisponível | ~280k por lote de saída |
| Congelamento / transferência forçada | indisponível | 54k / 80k |
A coluna da esquerda descreve o projeto que o A-REX Core substitui (ADR-004, ADR-005); apenas a da direita foi medida.
Orientações de implantação
- O custo em dinheiro é
gas × gas price × token price, e os dois últimos variam em ordens de grandeza entre redes e dias. Como mera ilustração, a 0.01 gwei e 3,000 USD por ETH, uma transferência quente com dois hooks (119,582 de gás) custa cerca de 0.0036 USD e umcreateBatch(264,096 de gás) cerca de 0.008 USD; a 20 gwei na mainnet do Ethereum, as mesmas operações custam cerca de 7.2 e 15.8 USD. Meça na rede de destino antes de se comprometer com um modelo de economia unitária. - Transferências múltiplas:
safeBatchTransferFromdilui os custos fixos; o custo dos hooks continua crescendo com o número de ids. - Ordem dos hooks: coloque primeiro os hooks baratos e de alta taxa de rejeição; uma rejeição interrompe o pipeline antes que os hooks mais caros sejam executados.
- Número de hooks: de três a cinco cobrem a maioria dos emissores; cada hook adicional é um custo mensurável por transferência e uma superfície de governança.
- Metadados: mantenha
uricurta (um CID ou um Digital Link); a string é armazenada on-chain. - Leituras off-chain: use
transferCheckantes de enviar; uma transação revertida ainda custa gás.
Vazão
O token em si não é o gargalo; a blockchain é. Uma única transferência é uma transação; uma transformação com n saídas é uma transação com n cunhagens. A indexação da linhagem exige a leitura dos eventos BatchTransformed, que são emitidos uma vez por operação com as listas completas de quantidades, de modo que um indexador não precisa reconstruir nada a partir de eventos por transferência.
Tamanho do contrato
ARexToken é implantado com 24,136 bytes (limite de 24,576), compilado com optimizer.runs = 1. Os demais contratos são pequenos: ARexAttestations 2,708; hooks entre 1,358 (ExpiryHook) e 6,215 (DeliveryHook), TraceabilityHook 4,076; extensões entre 3,716 e 4,588. Acrescentar funcionalidade ao próprio token é limitado por tamanho, por projeto — é para isso que servem os hooks e os contratos complementares.