Whitepaper · 13
Leistungsanalyse
Gemessenes Gas der Referenzimplementierung mit null, einem und zwei Hooks; was die Kosten bestimmt; und Hinweise zum Deployment.
Methode
Die folgenden Zahlen stammen aus scripts/gas-report-standard.js, ausgeführt im In-Process-Netzwerk von Hardhat gegen die kompilierte Referenzimplementierung (solc 0.8.22, viaIR, optimizer.runs = 1 für ARexToken), September 2026. „Warm“ bedeutet dasselbe Paar aus Sender, Empfänger und ID wie beim vorherigen Transfer (Speicher-Slots, die im Block bereits berührt wurden). Hooks: EligibilityHook (CHECK + ELIGIBILITY) und ExpiryHook (CHECK). Reproduzierbar mit:
npx hardhat run scripts/gas-report-standard.js
Ergebnisse
xychart-beta
title "Gas eines Warm-Transfers nach Anzahl der Hooks (Tausend)"
x-axis ["keine Hooks", "Berechtigung", "Berechtigung + Ablauf"]
y-axis "Gas (k)" 0 --> 140
bar [66.8, 91.2, 119.6]Die Kosten wachsen linear mit der Anzahl der Hooks: Jeder verursacht einen externen check-Aufruf pro ID, bei einem Berechtigungs-Hook zusätzlich canSend und canReceive. Die Tabelle nennt jede Operation.
| Operation | 0 Hooks | 1 Hook | 2 Hooks |
|---|---|---|---|
createBatch (neue ID, Mint von 1000) | 264,096 | 283,831 | 299,396 |
safeTransferFrom (erster, kalt) | 80,687 | 108,266 | 136,682 |
safeTransferFrom (warm) | 66,790 | 91,166 | 119,582 |
transform Teilung 1 → 2 (zwei neue 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 |
Warm-Transfer mit genau einem Hook jeder Art (Grenzkosten der Regel):
xychart-beta horizontal
title "Marginales Gas eines Hooks bei einem Warm-Transfer (Tausend)"
x-axis ["DeliveryHook", "Traceability (emit)", "EligibilityHook", "ExpiryHook", "SeasonalHook", "PerishabilityHook"]
y-axis "zusätzliches Gas (k)" 0 --> 35
bar [12.3, 17.4, 24.4, 25.2, 27.5, 31.0]TraceabilityHook im persistierenden Modus fügt 184.5k hinzu und ist der Übersichtlichkeit halber nicht im Diagramm enthalten.
| Hook | Gas | Δ ggü. ohne Hook |
|---|---|---|
| EligibilityHook | 91,166 | +24,376 |
| ExpiryHook | 92,023 | +25,233 |
| SeasonalHook | 94,324 | +27,534 |
| PerishabilityHook | 97,813 | +31,023 |
| DeliveryHook (keine aktive Lieferung) | 79,076 | +12,286 |
| TraceabilityHook, nur emittierend | 84,152 | +17,362 |
| TraceabilityHook, persistierend | 251,273 | +184,483 |
Was die Kosten bestimmt
- Ein Transfer ohne Hooks kostet warm ca. 67k, also ERC-1155 plus Mengenverfolgung plus die Lesezugriffe auf Existenz, Status und eingefrorenen Betrag der Charge sowie die Buchführung der Pipeline (Datenzwischenspeicher, Sperre). Das ist die Untergrenze.
- Jeder Hook fügt bei einem Transfer etwa 25–30k hinzu: ein
check-Aufruf (View, Contract-übergreifend) plus bei Berechtigungs-Hooks die AufrufecanSendundcanReceive. Die Kosten sind linear in der Anzahl der Hooks und in der Anzahl der IDs in einem Sammeltransfer. Würde jeder Regel-Contract vor dem Aufruf für jede Fähigkeit mitsupportsInterfaceabgefragt, kämen mehrere statische Aufrufe pro ID hinzu; dieser Mehraufwand entfällt, weil die Flags bei der Registrierung zwischengespeichert werden. createBatchwird vom Speicher dominiert: dasBatch-Struct (sechs Wörter plus eine Zeichenkette) und die ERC-1155-Slots für Saldo und Gesamtmenge. Es sind einmalige Kosten pro Charge.transformerzeugt neue IDs: Eine Teilung in zwei trägt zwei Chargendatensätze plus zwei Mints plus einen Burn, dazu Hook-Aufrufe bei jedem Teilvorgang (OP_TRANSFORM). Eine Teilung in n kostet in etwan × createBatchplus einen Burn; das Zusammenführen von n in eine kostet in etwanBurns plus ein createBatch.- Durchsetzung ist günstig: Einfrieren ist ein Slot; ein erzwungener Transfer kostet so viel wie ein Transfer plus den Schreibzugriff zum Aufheben des Einfrierens und das Ereignis.
transferCheck/canTransfersind Views: Off-Chain kostenlos und derselbe Codepfad wie die Transaktion.
Was der Entwurf bringt
| Entwurf mit Fähigkeitsabfrage | A-REX Core (ARexToken) | |
|---|---|---|
| Transfer mit n Regel-Contracts | IDs × Module × (supportsInterface-Abfragen + Hook-Aufruf), bevor irgendeine Logik läuft | IDs × Hooks × 1 Aufruf (+2 bei Berechtigungs-Hooks); Flags bei der Registrierung zwischengespeichert |
| Ablehnung | Revert mit Zeichenkette (in den Memory kopiert, nicht indexierbar) | benutzerdefinierter Fehler mit Hook-Adresse und bytes32-Code |
| Abstammung | nicht verfügbar | ca. 280k pro Ausgabecharge |
| Einfrieren / erzwungener Transfer | nicht verfügbar | 54k / 80k |
Die linke Spalte beschreibt den Entwurf, den A-REX Core ersetzt (ADR-004, ADR-005); nur die rechte Spalte ist gemessen.
Hinweise zum Deployment
- Die Kosten in Geld ergeben sich aus
gas × gas price × token price, und die letzten beiden ändern sich zwischen Chains und Tagen um Größenordnungen. Nur zur Veranschaulichung: Bei 0.01 gwei und 3,000 USD je ETH kostet ein Warm-Transfer mit zwei Hooks (119,582 Gas) etwa 0.0036 USD und eincreateBatch(264,096 Gas) etwa 0.008 USD; bei 20 gwei im Ethereum-Mainnet kosten dieselben Operationen etwa 7.2 und 15.8 USD. Vor der Festlegung eines Unit-Economics-Modells ist auf der Ziel-Chain zu messen. - Sammeltransfers:
safeBatchTransferFromamortisiert Fixkosten; die Hook-Kosten skalieren weiterhin mit der Anzahl der IDs. - Hook-Reihenfolge: Günstige Hooks mit hoher Ablehnungsquote an den Anfang stellen; eine Ablehnung stoppt die Pipeline, bevor teurere Hooks laufen.
- Anzahl der Hooks: Drei bis fünf genügen den meisten Ausstellern; jeder zusätzliche Hook bedeutet messbare Kosten pro Transfer und eine zusätzliche Governance-Fläche.
- Metadaten:
urikurz halten (eine CID oder ein Digital Link); die Zeichenkette wird On-Chain gespeichert. - Off-Chain-Lesezugriffe: Vor dem Absenden
transferCheckverwenden; eine revertierte Transaktion kostet dennoch Gas.
Durchsatz
Der Engpass ist nicht der Token selbst, sondern die Chain. Ein einzelner Transfer ist eine Transaktion; eine Transformation mit n Ausgaben ist eine Transaktion mit n Mints. Die Indexierung der Abstammung erfordert das Lesen von BatchTransformed-Ereignissen, die einmal pro Operation mit vollständigen Mengenlisten emittiert werden, sodass ein Indexer nichts aus den Ereignissen einzelner Transfers rekonstruieren muss.
Contract-Größe
ARexToken wird mit 24,136 Byte ausgerollt (Limit 24,576) und mit optimizer.runs = 1 kompiliert. Die übrigen Contracts sind klein: ARexAttestations 2,708; Hooks zwischen 1,358 (ExpiryHook) und 6,215 (DeliveryHook), TraceabilityHook 4,076; Erweiterungen zwischen 3,716 und 4,588. Dem Token selbst Funktionalität hinzuzufügen, ist konstruktionsbedingt durch die Größe begrenzt – dafür sind Hooks und Begleit-Contracts da.