Skip to main contentA-REX Foundation

Livre blanc · 13

Analyse des performances

Gaz mesuré de l'implémentation de référence avec zéro, un et deux hooks ; ce qui détermine le coût ; et recommandations de déploiement.

Méthode

Les chiffres ci-dessous proviennent de scripts/gas-report-standard.js exécuté sur le réseau en processus de Hardhat contre l'implémentation de référence compilée (solc 0.8.22, viaIR, optimizer.runs = 1 pour ARexToken), septembre 2026. « À chaud » (warm) désigne la même paire expéditeur/destinataire/identifiant que lors du transfert précédent (emplacements de stockage déjà touchés dans le bloc). Hooks : EligibilityHook (CHECK + ELIGIBILITY) et ExpiryHook (CHECK). Pour reproduire :

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

Résultats

xychart-beta
    title "Gaz d'un transfert à chaud selon le nombre de hooks (milliers)"
    x-axis ["aucun hook", "Éligibilité", "Éligibilité + Expiration"]
    y-axis "gaz (k)" 0 --> 140
    bar [66.8, 91.2, 119.6]

Le coût croît linéairement avec le nombre de hooks : chacun représente un appel externe à check par identifiant, plus canSend et canReceive pour un hook d'éligibilité. Le tableau donne chaque opération.

Opération0 hook1 hook2 hooks
createBatch (nouvel identifiant, émission de 1000)264,096283,831299,396
safeTransferFrom (premier, à froid)80,687108,266136,682
safeTransferFrom (à chaud)66,79091,166119,582
transform fractionnement 1 → 2 (deux nouveaux identifiants)564,422595,707636,858
setFrozenTokens54,18854,18854,188
forcedTransfer80,15289,90999,569
burn66,62183,00193,395

Transfert à chaud avec exactement un hook de chaque type (coût marginal de la règle) :

xychart-beta horizontal
    title "Gaz marginal d'un hook sur un transfert à chaud (milliers)"
    x-axis ["DeliveryHook", "Traceability (émission)", "EligibilityHook", "ExpiryHook", "SeasonalHook", "PerishabilityHook"]
    y-axis "gaz ajouté (k)" 0 --> 35
    bar [12.3, 17.4, 24.4, 25.2, 27.5, 31.0]

TraceabilityHook en mode persistant ajoute 184.5k et est exclu du graphique pour des raisons d'échelle.

HookGazΔ par rapport à l'absence de hook
EligibilityHook91,166+24,376
ExpiryHook92,023+25,233
SeasonalHook94,324+27,534
PerishabilityHook97,813+31,023
DeliveryHook (aucune livraison active)79,076+12,286
TraceabilityHook, émission seule84,152+17,362
TraceabilityHook, persistant251,273+184,483

Ce qui détermine le coût

  • Un transfert sans hook coûte ~67k à chaud, c'est-à-dire ERC-1155 plus le suivi de l'offre plus les lectures d'existence, de statut et de gel du lot et la comptabilité du pipeline (mise de côté des données, verrou). C'est le plancher.
  • Chaque hook ajoute environ 25–30k à un transfert : un appel à check (view, inter-contrats) plus, pour les hooks d'éligibilité, des appels à canSend et canReceive. Le coût est linéaire en fonction du nombre de hooks et du nombre d'identifiants dans un transfert groupé. Sonder chaque contrat de règle pour chaque capacité avec supportsInterface avant de l'appeler ajouterait plusieurs appels statiques par identifiant ; ce surcoût n'existe pas, car les drapeaux sont mis en cache à l'enregistrement.
  • createBatch est dominé par le stockage : la structure Batch (six mots plus une chaîne) et les emplacements de solde et d'offre d'ERC-1155. C'est un coût unique par lot.
  • transform crée de nouveaux identifiants : un fractionnement en deux paie deux enregistrements de lot plus deux émissions plus une destruction, plus les appels de hooks sur chaque mouvement (OP_TRANSFORM). Un fractionnement en n coûte à peu près n × createBatch plus une destruction ; la fusion de n en un seul coûte à peu près n destructions plus un createBatch.
  • La mise en application est peu coûteuse : un gel occupe un seul emplacement ; un transfert forcé coûte ce que coûte un transfert plus l'écriture de dégel et l'événement.
  • transferCheck / canTransfer sont des vues : gratuites off-chain, et suivent le même chemin de code que la transaction.

Ce que la conception apporte

Conception par sondage de capacitésA-REX Core (ARexToken)
Transfert avec n contrats de règlesidentifiants × modules × (sondes supportsInterface + appel de hook) avant l'exécution de toute logiqueidentifiants × hooks × 1 appel (+2 pour les hooks d'éligibilité) ; drapeaux mis en cache à l'enregistrement
Rejetrevert avec chaîne (copiée en mémoire, non indexable)erreur personnalisée avec l'adresse du hook et un code bytes32
Filiationindisponible~280k par lot de sortie
Gel / transfert forcéindisponible54k / 80k

La colonne de gauche décrit la conception qu'A-REX Core remplace (ADR-004, ADR-005) ; seule la colonne de droite est mesurée.

Recommandations de déploiement

  • Le coût monétaire est gas × gas price × token price, et les deux derniers facteurs varient de plusieurs ordres de grandeur selon les chaînes et les jours. À titre d'illustration seulement, à 0.01 gwei et 3,000 USD par ETH, un transfert à chaud avec deux hooks (119,582 gaz) coûte environ 0.0036 USD et un createBatch (264,096 gaz) environ 0.008 USD ; à 20 gwei sur le mainnet d'Ethereum, les mêmes opérations coûtent environ 7.2 et 15.8 USD. Mesurez sur la chaîne cible avant de vous engager dans un modèle d'économie unitaire.
  • Transferts groupés : safeBatchTransferFrom amortit les coûts fixes ; le coût des hooks reste proportionnel au nombre d'identifiants.
  • Ordre des hooks : placez en premier les hooks peu coûteux qui rejettent beaucoup ; un rejet interrompt le pipeline avant l'exécution des hooks plus coûteux.
  • Nombre de hooks : trois à cinq suffisent à la plupart des émetteurs ; chaque hook supplémentaire représente un coût mesurable par transfert et une surface de gouvernance.
  • Métadonnées : gardez uri courte (un CID ou un Digital Link) ; la chaîne est stockée on-chain.
  • Lectures off-chain : utilisez transferCheck avant de soumettre ; une transaction annulée coûte tout de même du gaz.

Débit

Le jeton lui-même n'est pas le goulet d'étranglement ; c'est la chaîne. Un transfert unique est une transaction ; une transformation avec n sorties est une transaction comportant n émissions. L'indexation de la filiation exige de lire les événements BatchTransformed, émis une fois par opération avec les listes complètes de quantités ; un indexeur n'a donc rien à reconstituer à partir des événements propres à chaque transfert.

Taille des contrats

ARexToken se déploie à 24,136 octets (limite 24,576), compilé avec optimizer.runs = 1. Les autres contrats sont petits : ARexAttestations 2,708 ; hooks entre 1,358 (ExpiryHook) et 6,215 (DeliveryHook), TraceabilityHook 4,076 ; extensions entre 3,716 et 4,588. Ajouter des fonctionnalités au jeton lui-même est limité par la taille, par conception — c'est à cela que servent les hooks et les contrats compagnons.