Top 10 Best Practices für die Optimierung von Gas in Ethereum Smart Contracts

Fortgeschrittene1/3/2025, 11:25:57 AM
Dieser Artikel untersucht die Probleme mit den Gasgebühren im Ethereum-Hauptnetz und Methoden zur Optimierung. Er konzentriert sich auf den Gasmechanismus der EVM, Kernkonzepte zur Optimierung der Gas-Kosten und bewährte Verfahren zur Entwicklung von Smart Contracts. Dazu gehören die Reduzierung des Speicherbedarfs, die Variable-Packing, die Optimierung von Datentypen und die Verwendung von festen Variablen.

Durch die Befolgung dieser Praktiken können Entwickler den Gasverbrauch in Smart Contracts reduzieren, Transaktionskosten senken und effizientere und benutzerfreundlichere Anwendungen erstellen.

Gasgebühren auf dem Ethereum-Mainnet waren schon immer ein großes Problem, insbesondere während Zeiten von Netzwerküberlastung. Zu Spitzenzeiten müssen Benutzer oft extrem hohe Transaktionsgebühren zahlen. Daher ist die Optimierung der Gas-Kosten während der Entwicklung von Smart Contracts entscheidend. Die Gasoptimierung kann nicht nur die Transaktionskosten effektiv reduzieren, sondern auch die Transaktionseffizienz verbessern und den Benutzern ein wirtschaftlicheres und effizienteres Blockchain-Erlebnis bieten.

In diesem Artikel wird der Gasgebührenmechanismus der Ethereum Virtual Machine (EVM), die Kernkonzepte im Zusammenhang mit der Optimierung von Gasgebühren und bewährte Verfahren zur Optimierung von Gasgebühren bei der Entwicklung von Smart Contracts erläutert. Es wird gehofft, dass dieser Inhalt Entwickler inspiriert und unterstützt, während er auch gewöhnlichen Benutzern hilft, das Funktionieren des EVM-Gasgebührensystems besser zu verstehen und so die Herausforderungen im Blockchain-Ökosystem anzugehen.

Überblick über den EVM Gasgebührenmechanismus

In EVM-kompatiblen Netzwerken bezieht sich "Gas" auf die Einheit, die zur Messung der Rechenleistung erforderlich ist, um bestimmte Operationen auszuführen.

Die folgende Abbildung veranschaulicht die Struktur der EVM. In der Abbildung wird der Gasverbrauch in drei Teile aufgeteilt: Ausführung von Operationen, externe Nachrichtenaufrufe sowie Lese- und Schreibvorgänge des Arbeitsspeichers und des Speichers.

Quelle: Offizielle Ethereum-Website[1]

Seit der Aktivierung von EIP-1559 (London Hard Fork) werden die Gasgebühren mit folgender Formel berechnet:

Gasgebühr = verwendete Gaseinheiten * (Grundgebühr + Prioritätsgebühr)

Die Grundgebühr wird verbrannt, während die Prioritätsgebühr als Anreiz dient, die Validatoren dazu zu ermutigen, die Transaktion in die Blockchain aufzunehmen. Wenn Sie eine Transaktion mit einer höheren Prioritätsgebühr senden, erhöht sich die Wahrscheinlichkeit, dass die Transaktion im nächsten Block enthalten ist. Dies ähnelt einem „Trinkgeld“, das von Benutzern an die Validatoren gezahlt wird.

1. Verständnis der Gasoptimierung in EVM

Beim Kompilieren eines Smart Contracts mit Solidity wird der Vertrag in eine Reihe von "Betriebscodes" oder Opcodes umgewandelt.

Jeder Opcode (wie das Erstellen eines Vertrags, das Durchführen von Nachrichtenaufrufen, der Zugriff auf den Kontospeicher und das Ausführen von Operationen auf der virtuellen Maschine) hat eine zugehörige Gasverbrauchskosten, die im Ethereum Yellow Paper[2] dokumentiert sind.

Nach mehreren EIP-Änderungen wurden die Gasgebühren einiger Opcodes angepasst, die von den Werten im Yellow Paper abweichen können. Für detaillierte Informationen zu den neuesten Kosten von Opcodes, siehe diese Quelle[3].

2. Grundkonzepte der Gasoptimierung

Das Kernkonzept der Gasoptimierung besteht darin, kosteneffiziente Operationen auf der EVM-Blockchain zu priorisieren und Operationen zu vermeiden, die hohe Gas kosten verursachen.

Im EVM sind die folgenden Operationen vergleichsweise kostengünstig:

  • [ ] Lesen und Schreiben von Speichervariablen
  • [ ] Lesen von konstanten und unveränderlichen Variablen
  • [ ] Lesen und Schreiben von lokalen Variablen
  • Lesen von calldata-Variablen, wie zum Beispiel calldata-Arrays und Strukturen
  • [ ] Interne Funktionsaufrufe

Zu den kostspieligen Operationen gehören:

  • Lesen und Schreiben von Zustandsvariablen, die im Vertragspeicher gespeichert sind
  • [ ] Externe Funktionsaufrufe
  • [ ] Schleifenoperationen

EVM Gasgebührenoptimierung Best Practices

Basierend auf den oben genannten Grundkonzepten haben wir eine Liste bewährter Verfahren zur Optimierung der Gasgebühr für die Entwicklergemeinschaft zusammengestellt. Durch die Befolgung dieser Praktiken können Entwickler den Gasverbrauch von Smart Contracts reduzieren, Transaktionskosten senken und effizientere und benutzerfreundlichere Anwendungen erstellen.

1. Minimize Storage Usage

In Solidity, Speicher ist eine begrenzte Ressource, und sein Gasverbrauch ist deutlich höher als der von Memory. Jedes Mal, wenn ein Smart Contract aus dem Speicher liest oder in ihn schreibt, entsteht ein hoher Gasverbrauch.

Gemäß der Definition im Ethereum Yellow Paper ist der Speicheraufwand für Speicheroperationen mehr als 100-mal höher als der Speicheraufwand für Arbeitsspeicheroperationen. Zum Beispiel kosten Opcodes wie sload und sstore im besten Fall mindestens 100 Gas-Einheiten, während Arbeitsspeicheroperationen wie mload und mstore nur 3 Gas-Einheiten verbrauchen.

Methoden zur Begrenzung des Speicherverbrauchs umfassen:

  • [ ] Speichern Sie nicht-permanente Daten im Speicher
  • [ ] Reduzieren Sie die Anzahl der Speicheränderungen: Durch das Speichern von Zwischenergebnissen im Speicher und das Zuweisen des endgültigen Ergebnisses an Speichervariablen erst, wenn alle Berechnungen abgeschlossen sind.

2. Variable Verpackung

Die Anzahl der Speicherplätze, die in einem Smart Contract verwendet werden, und die Art und Weise, wie Entwickler Daten darstellen, können den Gasverbrauch erheblich beeinflussen.

Der Solidity-Compiler packt während des Kompilierungsprozesses aufeinanderfolgende Speichervariablen unter Verwendung von 32-Byte-Speicherslots als Grundlage für die Variablenspeicherung. Die Variablenverpackung bezieht sich auf die Praxis, Variablen so anzuordnen, dass mehrere Variablen in einen einzigen Speicherslot passen.

Links befindet sich eine weniger effiziente Implementierung, die 3 Speicherplätze verbraucht; rechts befindet sich eine effizientere Implementierung.

Durch diese Anpassung können Entwickler 20.000 Gas-Einheiten sparen (da das Speichern eines ungenutzten Speicherslots 20.000 Gas kostet), aber jetzt werden nur noch zwei Speicherslots benötigt.

Da jeder Speicherslot Gas verbraucht, optimiert die Variablenpackung den Gasverbrauch, indem die Anzahl der benötigten Speicherslots reduziert wird.

3. Optimieren von Datentypen

Eine Variable kann mit unterschiedlichen Datentypen dargestellt werden, aber die Betriebskosten variieren je nach Typ. Die Auswahl des geeigneten Datentyps hilft, die Gasnutzung zu optimieren.

Zum Beispiel können in Solidity Ganzzahlen in verschiedene Größen unterteilt werden: uint8, uint16, uint32, usw. Da die EVM in 256-Bit-Einheiten arbeitet, bedeutet die Verwendung von uint8, dass die EVM sie zuerst in uint256 konvertieren muss, und diese Konvertierung verursacht zusätzliche Gas-Kosten.

Wir können die Gas-Kosten von uint8 und uint256 mithilfe des Codes im Diagramm vergleichen. Die UseUint()-Funktion verbraucht 120.382 Gas-Einheiten, während die UseUInt8()-Funktion 166.111 Gas-Einheiten verbraucht.

Für sich genommen ist die Verwendung von uint256 günstiger als uint8. Wenn wir jedoch die zuvor vorgeschlagene Variable-Packing-Optimierung anwenden, macht es einen Unterschied. Wenn Entwickler vier uint8-Variablen in einen einzelnen Speicherplatz packen können, ist der Gesamtaufwand für die Iteration über sie niedriger als bei der Verwendung von vier uint256-Variablen. In diesem Fall kann der Smart Contract den Speicherplatz einmal lesen und schreiben und alle vier uint8-Variablen in einem einzigen Vorgang in den Speicher laden.

4. Verwenden Sie feste Variablen anstelle von dynamischen Variablen

Wenn die Daten auf 32 Bytes begrenzt werden können, wird empfohlen, anstelle von Bytes oder Strings den Datentyp bytes32 zu verwenden. Im Allgemeinen verbrauchen Variablen mit fester Größe weniger Gas als Variablen mit dynamischer Größe. Wenn die Byte-Länge begrenzt werden kann, versuchen Sie, die kleinste Länge von bytes1 bis bytes32 zu wählen.

5. Zuordnungen vs. Arrays

In Solidity können Datensammlungen mit zwei Datentypen dargestellt werden: Arrays und Mappings, von denen jeder eine eigene Syntax und Struktur aufweist.

Mappings sind in den meisten Fällen allgemein effizienter und kostengünstiger, während Arrays iterierbar sind und die Datenverpackung unterstützen. Daher wird empfohlen, beim Verwalten von Datenlisten die Verwendung von Mappings priorisiert, es sei denn, eine Iteration ist erforderlich oder der Gasverbrauch durch Datenverpackung optimiert werden kann.

6. Verwenden Sie calldata anstelle von Memory

Variablen, die in den Funktionsparametern deklariert sind, können entweder im calldata oder im Speicher gespeichert werden. Der Hauptunterschied besteht darin, dass der Speicher von der Funktion verändert werden kann, während calldata unveränderlich ist.

Behalten Sie dieses Prinzip im Hinterkopf: Wenn Funktionparameter schreibgeschützt sind, verwenden Sie bevorzugt calldata anstelle von memory. Dadurch werden unnötige Kopiervorgänge von Funktion calldata in memory vermieden.

Beispiel 1: Mit Speicher verwenden

Bei Verwendung des Speicherschlüsselworts werden die Werte des Arrays beim ABI-Decodieren aus dem codierten Calldaten in den Speicher kopiert. Die Ausführungskosten dieses Codeblocks betragen 3.694 Gas-Einheiten.

Beispiel 2: Verwendung von calldata

Beim direkten Lesen von Werten aus Calldata wird der Zwischenspeichervorgang übersprungen. Diese Optimierung reduziert die Ausführungskosten auf nur 2.413 Gas-Einheiten, was zu einer Verbesserung der Gas-Effizienz um 35 % führt.

7. Verwenden Sie bei Möglichkeit die Schlüsselwörter Constant/Immutable

Konstante/Unveränderliche Variablen werden nicht im Speicher des Vertrags gespeichert. Diese Variablen werden zur Kompilierzeit berechnet und im Bytcode des Vertrags gespeichert. Daher ist ihr Zugriffskosten viel niedriger im Vergleich zu Speichervariablen. Es wird empfohlen, die Schlüsselwörter Konstant oder Unveränderlich wann immer möglich zu verwenden.

8. Verwenden Sie Unchecked, wenn Überlauf/Unterlauf keine Rolle spielt

Wenn Entwickler sicher sein können, dass arithmetische Operationen nicht zu einem Überlauf oder Unterlauf führen, können sie das unchecked-Schlüsselwort, das in Solidity v0.8.0 eingeführt wurde, verwenden, um unnötige Überlauf- oder Unterlaufprüfungen zu vermeiden und so Gas-Kosten zu sparen.

In der folgenden Abbildung ist die bedingt eingeschränkte i

Darüber hinaus erfordern Compiler-Versionen 0.8.0 und höher nicht mehr die Verwendung der SafeMath-Bibliothek, da der Compiler selbst jetzt einen integrierten Schutz gegen Überlauf und Unterlauf enthält.

9. Optimieren Sie den Modifier

Der Code der Modifier ist in die Funktionen eingebettet, die sie modifizieren. Jedes Mal, wenn ein Modifier verwendet wird, wird sein Code dupliziert, was die Bytecode-Größe erhöht und den Gasverbrauch steigert. Hier ist eine Möglichkeit, die Gaskosten für Modifier zu optimieren:

Vor Optimierung:

Nach der Optimierung:

In diesem Beispiel wird durch die Umstrukturierung der Logik in eine interne Funktion _checkOwner(), die im Modifier wiederverwendet werden kann, die Bytecode-Größe reduziert und die Gas-Kosten gesenkt.

10. Kurzschluss-Optimierung

Für || (ODER) und && (UND) Operatoren werden logische Operationen mit Kurzschlussauswertung durchgeführt, was bedeutet, dass wenn die erste Bedingung ausreicht, um das Ergebnis des logischen Ausdrucks zu bestimmen, die zweite Bedingung nicht ausgewertet wird.

Um den Gasverbrauch zu optimieren, sollten Bedingungen mit geringeren Berechnungskosten zuerst platziert werden, damit potenziell teure Berechnungen übersprungen werden können.

Allgemeine Empfehlungen

1. Entfernen Sie nicht verwendeten Code

Wenn es ungenutzte Funktionen oder Variablen im Vertrag gibt, wird empfohlen, sie zu löschen. Dies ist der direkteste Weg, um die Bereitstellungskosten des Vertrags zu reduzieren und die Vertragsgröße klein zu halten.

Hier sind einige praktische Vorschläge:

Verwenden Sie die effizientesten Algorithmen für Berechnungen. Wenn der Vertrag direkt bestimmte Berechnungsergebnisse verwendet, sollten redundante Berechnungen entfernt werden. Grundsätzlich sollten alle ungenutzten Berechnungen gelöscht werden. In Ethereum können Entwickler Gasbelohnungen erhalten, indem sie Speicherplatz freigeben. Wenn eine Variable nicht mehr benötigt wird, sollte sie mit dem Lösch-Schlüsselwort gelöscht oder auf ihren Standardwert gesetzt werden.

Schleifenoptimierung: Vermeiden Sie teure Schleifenoperationen, versuchen Sie, Schleifen zu fusionieren und wiederholte Berechnungen aus dem Schleifenkörper zu verschieben.

2. Verwenden Sie vorcompilierte Verträge

Vorkompilierte Verträge bieten komplexe Bibliotheksfunktionen wie Kryptografie- und Hash-Operationen. Da der Code nicht auf dem EVM ausgeführt wird, sondern lokal auf dem Client-Node läuft, wird weniger Gas benötigt. Die Verwendung von vorkompilierten Verträgen kann Gas sparen, indem die Rechenlast reduziert wird, die zur Ausführung des Smart Contracts erforderlich ist.

Beispiele für vorcompilierte Verträge sind der Elliptic Curve Digital Signature Algorithm (ECDSA) und der SHA2-256-Hashing-Algorithmus. Durch die Verwendung dieser vorcompilierten Verträge in Smart Contracts können Entwickler die Gas-Kosten senken und die Effizienz der Anwendung verbessern.

Für eine vollständige Liste der von dem Ethereum-Netzwerk unterstützten vorkompilierten Verträge, siehe diesen Link [4].

3. Verwenden Sie Inline-Assembly

Inline-Assembly ermöglicht Entwicklern das Schreiben von Low-Level-, aber effizientem Code, der vom EVM direkt ausgeführt werden kann, ohne teure Solidity-Operationen zu verwenden. Inline-Assembly bietet auch eine präzisere Kontrolle über den Speicher- und Speichernutzung, was die Gas-Kosten weiter reduziert. Darüber hinaus kann Inline-Assembly einige komplexe Operationen durchführen, die mit Solidity allein schwer umzusetzen sind, was mehr Flexibilität für die Optimierung des Gasverbrauchs bietet.

Hier ist ein Beispiel für die Verwendung von Inline-Assembly, um Gas zu sparen:

Wie im obigen Beispiel zu sehen ist, hat der zweite Fall, der Inline-Assembly verwendet, eine höhere Gas-Effizienz im Vergleich zum Standardfall.

Die Verwendung von Inline-Assembly kann jedoch auch Risiken mit sich bringen und ist fehleranfällig. Daher sollte sie vorsichtig verwendet werden und wird nur erfahrenen Entwicklern empfohlen.

4. Verwenden Sie Layer 2-Lösungen

Layer 2 Lösungen können die Menge an Daten reduzieren, die auf der Ethereum-Hauptkette gespeichert und berechnet werden müssen.

Layer-2-Lösungen wie Rollups, Sidechains und State Channels entlasten die Transaktionsverarbeitung von der Haupt-Ethereum-Kette und ermöglichen schnellere und günstigere Transaktionen.

Durch das Bündeln einer großen Anzahl von Transaktionen reduzieren diese Lösungen die Anzahl der On-Chain-Transaktionen, was wiederum die Gasgebühren senkt. Die Verwendung von Layer-2-Lösungen verbessert auch die Skalierbarkeit von Ethereum, wodurch mehr Benutzer und Anwendungen am Netzwerk teilnehmen können, ohne dass es zu Überlastungen kommt.

5. Verwenden Sie Optimierungstools und -bibliotheken

Es gibt mehrere Optimierungstools zur Verfügung, wie der solc Optimierer, Truffles Build-Optimizer und Remixs Solidity-Compiler.

Diese Tools können die Bytecode-Größe minimieren, nicht verwendeten Code entfernen und die Anzahl der für die Ausführung von Smart Contracts erforderlichen Operationen reduzieren. In Kombination mit anderen Gas-Optimierungsbibliotheken wie „solmate“ können Entwickler die Gas-Kosten effektiv senken und die Effizienz von Smart Contracts verbessern.

Schlussfolgerung

Die Optimierung des Gasverbrauchs ist ein wichtiger Schritt für Entwickler, da dies nicht nur die Transaktionskosten minimiert, sondern auch die Effizienz von Smart Contracts in EVM-kompatiblen Netzwerken verbessert. Durch Priorisierung kostensparender Operationen, Reduzierung des Speicherplatzverbrauchs, Nutzung von Inline-Assembly und Befolgung anderer bewährter Verfahren, die in diesem Artikel erörtert werden, können Entwickler den Gasverbrauch von Verträgen effektiv senken.

Es ist jedoch wichtig zu beachten, dass Entwickler während des Optimierungsprozesses Vorsicht walten lassen müssen, um Sicherheitsanfälligkeiten zu vermeiden. Bei der Optimierung des Codes und der Reduzierung des Gasverbrauchs darf die inhärente Sicherheit des Smart Contracts niemals beeinträchtigt werden.

[1] https://ethereum.org/de/developers/docs/gas/
[2] https://ethereum.github.io/yellowpaper/paper.pdf
[3]https://www.evm.codes/
[4] https://www.evm.codes/precompiled

Haftungsausschluss:

  1. Dieser Artikel stammt aus [ PANewslab]. Das Urheberrecht liegt beim Originalautor [ CertiK]. Wenn Sie Einwände gegen den Nachdruck haben, kontaktieren Sie uns bitte.Gate LearnTeam, das Team wird es so schnell wie möglich gemäß den relevanten Verfahren bearbeiten.
  2. Haftungsausschluss: Die in diesem Artikel geäußerten Ansichten und Meinungen stellen ausschließlich die persönlichen Ansichten des Autors dar und stellen keine Anlageberatung dar.
  3. Andere Sprachversionen des Artikels werden vom Gate Learn-Team übersetzt. Sofern nicht anders angegeben, darf der übersetzte Artikel nicht kopiert, verteilt oder plagiiert werden.

Top 10 Best Practices für die Optimierung von Gas in Ethereum Smart Contracts

Fortgeschrittene1/3/2025, 11:25:57 AM
Dieser Artikel untersucht die Probleme mit den Gasgebühren im Ethereum-Hauptnetz und Methoden zur Optimierung. Er konzentriert sich auf den Gasmechanismus der EVM, Kernkonzepte zur Optimierung der Gas-Kosten und bewährte Verfahren zur Entwicklung von Smart Contracts. Dazu gehören die Reduzierung des Speicherbedarfs, die Variable-Packing, die Optimierung von Datentypen und die Verwendung von festen Variablen.

Durch die Befolgung dieser Praktiken können Entwickler den Gasverbrauch in Smart Contracts reduzieren, Transaktionskosten senken und effizientere und benutzerfreundlichere Anwendungen erstellen.

Gasgebühren auf dem Ethereum-Mainnet waren schon immer ein großes Problem, insbesondere während Zeiten von Netzwerküberlastung. Zu Spitzenzeiten müssen Benutzer oft extrem hohe Transaktionsgebühren zahlen. Daher ist die Optimierung der Gas-Kosten während der Entwicklung von Smart Contracts entscheidend. Die Gasoptimierung kann nicht nur die Transaktionskosten effektiv reduzieren, sondern auch die Transaktionseffizienz verbessern und den Benutzern ein wirtschaftlicheres und effizienteres Blockchain-Erlebnis bieten.

In diesem Artikel wird der Gasgebührenmechanismus der Ethereum Virtual Machine (EVM), die Kernkonzepte im Zusammenhang mit der Optimierung von Gasgebühren und bewährte Verfahren zur Optimierung von Gasgebühren bei der Entwicklung von Smart Contracts erläutert. Es wird gehofft, dass dieser Inhalt Entwickler inspiriert und unterstützt, während er auch gewöhnlichen Benutzern hilft, das Funktionieren des EVM-Gasgebührensystems besser zu verstehen und so die Herausforderungen im Blockchain-Ökosystem anzugehen.

Überblick über den EVM Gasgebührenmechanismus

In EVM-kompatiblen Netzwerken bezieht sich "Gas" auf die Einheit, die zur Messung der Rechenleistung erforderlich ist, um bestimmte Operationen auszuführen.

Die folgende Abbildung veranschaulicht die Struktur der EVM. In der Abbildung wird der Gasverbrauch in drei Teile aufgeteilt: Ausführung von Operationen, externe Nachrichtenaufrufe sowie Lese- und Schreibvorgänge des Arbeitsspeichers und des Speichers.

Quelle: Offizielle Ethereum-Website[1]

Seit der Aktivierung von EIP-1559 (London Hard Fork) werden die Gasgebühren mit folgender Formel berechnet:

Gasgebühr = verwendete Gaseinheiten * (Grundgebühr + Prioritätsgebühr)

Die Grundgebühr wird verbrannt, während die Prioritätsgebühr als Anreiz dient, die Validatoren dazu zu ermutigen, die Transaktion in die Blockchain aufzunehmen. Wenn Sie eine Transaktion mit einer höheren Prioritätsgebühr senden, erhöht sich die Wahrscheinlichkeit, dass die Transaktion im nächsten Block enthalten ist. Dies ähnelt einem „Trinkgeld“, das von Benutzern an die Validatoren gezahlt wird.

1. Verständnis der Gasoptimierung in EVM

Beim Kompilieren eines Smart Contracts mit Solidity wird der Vertrag in eine Reihe von "Betriebscodes" oder Opcodes umgewandelt.

Jeder Opcode (wie das Erstellen eines Vertrags, das Durchführen von Nachrichtenaufrufen, der Zugriff auf den Kontospeicher und das Ausführen von Operationen auf der virtuellen Maschine) hat eine zugehörige Gasverbrauchskosten, die im Ethereum Yellow Paper[2] dokumentiert sind.

Nach mehreren EIP-Änderungen wurden die Gasgebühren einiger Opcodes angepasst, die von den Werten im Yellow Paper abweichen können. Für detaillierte Informationen zu den neuesten Kosten von Opcodes, siehe diese Quelle[3].

2. Grundkonzepte der Gasoptimierung

Das Kernkonzept der Gasoptimierung besteht darin, kosteneffiziente Operationen auf der EVM-Blockchain zu priorisieren und Operationen zu vermeiden, die hohe Gas kosten verursachen.

Im EVM sind die folgenden Operationen vergleichsweise kostengünstig:

  • [ ] Lesen und Schreiben von Speichervariablen
  • [ ] Lesen von konstanten und unveränderlichen Variablen
  • [ ] Lesen und Schreiben von lokalen Variablen
  • Lesen von calldata-Variablen, wie zum Beispiel calldata-Arrays und Strukturen
  • [ ] Interne Funktionsaufrufe

Zu den kostspieligen Operationen gehören:

  • Lesen und Schreiben von Zustandsvariablen, die im Vertragspeicher gespeichert sind
  • [ ] Externe Funktionsaufrufe
  • [ ] Schleifenoperationen

EVM Gasgebührenoptimierung Best Practices

Basierend auf den oben genannten Grundkonzepten haben wir eine Liste bewährter Verfahren zur Optimierung der Gasgebühr für die Entwicklergemeinschaft zusammengestellt. Durch die Befolgung dieser Praktiken können Entwickler den Gasverbrauch von Smart Contracts reduzieren, Transaktionskosten senken und effizientere und benutzerfreundlichere Anwendungen erstellen.

1. Minimize Storage Usage

In Solidity, Speicher ist eine begrenzte Ressource, und sein Gasverbrauch ist deutlich höher als der von Memory. Jedes Mal, wenn ein Smart Contract aus dem Speicher liest oder in ihn schreibt, entsteht ein hoher Gasverbrauch.

Gemäß der Definition im Ethereum Yellow Paper ist der Speicheraufwand für Speicheroperationen mehr als 100-mal höher als der Speicheraufwand für Arbeitsspeicheroperationen. Zum Beispiel kosten Opcodes wie sload und sstore im besten Fall mindestens 100 Gas-Einheiten, während Arbeitsspeicheroperationen wie mload und mstore nur 3 Gas-Einheiten verbrauchen.

Methoden zur Begrenzung des Speicherverbrauchs umfassen:

  • [ ] Speichern Sie nicht-permanente Daten im Speicher
  • [ ] Reduzieren Sie die Anzahl der Speicheränderungen: Durch das Speichern von Zwischenergebnissen im Speicher und das Zuweisen des endgültigen Ergebnisses an Speichervariablen erst, wenn alle Berechnungen abgeschlossen sind.

2. Variable Verpackung

Die Anzahl der Speicherplätze, die in einem Smart Contract verwendet werden, und die Art und Weise, wie Entwickler Daten darstellen, können den Gasverbrauch erheblich beeinflussen.

Der Solidity-Compiler packt während des Kompilierungsprozesses aufeinanderfolgende Speichervariablen unter Verwendung von 32-Byte-Speicherslots als Grundlage für die Variablenspeicherung. Die Variablenverpackung bezieht sich auf die Praxis, Variablen so anzuordnen, dass mehrere Variablen in einen einzigen Speicherslot passen.

Links befindet sich eine weniger effiziente Implementierung, die 3 Speicherplätze verbraucht; rechts befindet sich eine effizientere Implementierung.

Durch diese Anpassung können Entwickler 20.000 Gas-Einheiten sparen (da das Speichern eines ungenutzten Speicherslots 20.000 Gas kostet), aber jetzt werden nur noch zwei Speicherslots benötigt.

Da jeder Speicherslot Gas verbraucht, optimiert die Variablenpackung den Gasverbrauch, indem die Anzahl der benötigten Speicherslots reduziert wird.

3. Optimieren von Datentypen

Eine Variable kann mit unterschiedlichen Datentypen dargestellt werden, aber die Betriebskosten variieren je nach Typ. Die Auswahl des geeigneten Datentyps hilft, die Gasnutzung zu optimieren.

Zum Beispiel können in Solidity Ganzzahlen in verschiedene Größen unterteilt werden: uint8, uint16, uint32, usw. Da die EVM in 256-Bit-Einheiten arbeitet, bedeutet die Verwendung von uint8, dass die EVM sie zuerst in uint256 konvertieren muss, und diese Konvertierung verursacht zusätzliche Gas-Kosten.

Wir können die Gas-Kosten von uint8 und uint256 mithilfe des Codes im Diagramm vergleichen. Die UseUint()-Funktion verbraucht 120.382 Gas-Einheiten, während die UseUInt8()-Funktion 166.111 Gas-Einheiten verbraucht.

Für sich genommen ist die Verwendung von uint256 günstiger als uint8. Wenn wir jedoch die zuvor vorgeschlagene Variable-Packing-Optimierung anwenden, macht es einen Unterschied. Wenn Entwickler vier uint8-Variablen in einen einzelnen Speicherplatz packen können, ist der Gesamtaufwand für die Iteration über sie niedriger als bei der Verwendung von vier uint256-Variablen. In diesem Fall kann der Smart Contract den Speicherplatz einmal lesen und schreiben und alle vier uint8-Variablen in einem einzigen Vorgang in den Speicher laden.

4. Verwenden Sie feste Variablen anstelle von dynamischen Variablen

Wenn die Daten auf 32 Bytes begrenzt werden können, wird empfohlen, anstelle von Bytes oder Strings den Datentyp bytes32 zu verwenden. Im Allgemeinen verbrauchen Variablen mit fester Größe weniger Gas als Variablen mit dynamischer Größe. Wenn die Byte-Länge begrenzt werden kann, versuchen Sie, die kleinste Länge von bytes1 bis bytes32 zu wählen.

5. Zuordnungen vs. Arrays

In Solidity können Datensammlungen mit zwei Datentypen dargestellt werden: Arrays und Mappings, von denen jeder eine eigene Syntax und Struktur aufweist.

Mappings sind in den meisten Fällen allgemein effizienter und kostengünstiger, während Arrays iterierbar sind und die Datenverpackung unterstützen. Daher wird empfohlen, beim Verwalten von Datenlisten die Verwendung von Mappings priorisiert, es sei denn, eine Iteration ist erforderlich oder der Gasverbrauch durch Datenverpackung optimiert werden kann.

6. Verwenden Sie calldata anstelle von Memory

Variablen, die in den Funktionsparametern deklariert sind, können entweder im calldata oder im Speicher gespeichert werden. Der Hauptunterschied besteht darin, dass der Speicher von der Funktion verändert werden kann, während calldata unveränderlich ist.

Behalten Sie dieses Prinzip im Hinterkopf: Wenn Funktionparameter schreibgeschützt sind, verwenden Sie bevorzugt calldata anstelle von memory. Dadurch werden unnötige Kopiervorgänge von Funktion calldata in memory vermieden.

Beispiel 1: Mit Speicher verwenden

Bei Verwendung des Speicherschlüsselworts werden die Werte des Arrays beim ABI-Decodieren aus dem codierten Calldaten in den Speicher kopiert. Die Ausführungskosten dieses Codeblocks betragen 3.694 Gas-Einheiten.

Beispiel 2: Verwendung von calldata

Beim direkten Lesen von Werten aus Calldata wird der Zwischenspeichervorgang übersprungen. Diese Optimierung reduziert die Ausführungskosten auf nur 2.413 Gas-Einheiten, was zu einer Verbesserung der Gas-Effizienz um 35 % führt.

7. Verwenden Sie bei Möglichkeit die Schlüsselwörter Constant/Immutable

Konstante/Unveränderliche Variablen werden nicht im Speicher des Vertrags gespeichert. Diese Variablen werden zur Kompilierzeit berechnet und im Bytcode des Vertrags gespeichert. Daher ist ihr Zugriffskosten viel niedriger im Vergleich zu Speichervariablen. Es wird empfohlen, die Schlüsselwörter Konstant oder Unveränderlich wann immer möglich zu verwenden.

8. Verwenden Sie Unchecked, wenn Überlauf/Unterlauf keine Rolle spielt

Wenn Entwickler sicher sein können, dass arithmetische Operationen nicht zu einem Überlauf oder Unterlauf führen, können sie das unchecked-Schlüsselwort, das in Solidity v0.8.0 eingeführt wurde, verwenden, um unnötige Überlauf- oder Unterlaufprüfungen zu vermeiden und so Gas-Kosten zu sparen.

In der folgenden Abbildung ist die bedingt eingeschränkte i

Darüber hinaus erfordern Compiler-Versionen 0.8.0 und höher nicht mehr die Verwendung der SafeMath-Bibliothek, da der Compiler selbst jetzt einen integrierten Schutz gegen Überlauf und Unterlauf enthält.

9. Optimieren Sie den Modifier

Der Code der Modifier ist in die Funktionen eingebettet, die sie modifizieren. Jedes Mal, wenn ein Modifier verwendet wird, wird sein Code dupliziert, was die Bytecode-Größe erhöht und den Gasverbrauch steigert. Hier ist eine Möglichkeit, die Gaskosten für Modifier zu optimieren:

Vor Optimierung:

Nach der Optimierung:

In diesem Beispiel wird durch die Umstrukturierung der Logik in eine interne Funktion _checkOwner(), die im Modifier wiederverwendet werden kann, die Bytecode-Größe reduziert und die Gas-Kosten gesenkt.

10. Kurzschluss-Optimierung

Für || (ODER) und && (UND) Operatoren werden logische Operationen mit Kurzschlussauswertung durchgeführt, was bedeutet, dass wenn die erste Bedingung ausreicht, um das Ergebnis des logischen Ausdrucks zu bestimmen, die zweite Bedingung nicht ausgewertet wird.

Um den Gasverbrauch zu optimieren, sollten Bedingungen mit geringeren Berechnungskosten zuerst platziert werden, damit potenziell teure Berechnungen übersprungen werden können.

Allgemeine Empfehlungen

1. Entfernen Sie nicht verwendeten Code

Wenn es ungenutzte Funktionen oder Variablen im Vertrag gibt, wird empfohlen, sie zu löschen. Dies ist der direkteste Weg, um die Bereitstellungskosten des Vertrags zu reduzieren und die Vertragsgröße klein zu halten.

Hier sind einige praktische Vorschläge:

Verwenden Sie die effizientesten Algorithmen für Berechnungen. Wenn der Vertrag direkt bestimmte Berechnungsergebnisse verwendet, sollten redundante Berechnungen entfernt werden. Grundsätzlich sollten alle ungenutzten Berechnungen gelöscht werden. In Ethereum können Entwickler Gasbelohnungen erhalten, indem sie Speicherplatz freigeben. Wenn eine Variable nicht mehr benötigt wird, sollte sie mit dem Lösch-Schlüsselwort gelöscht oder auf ihren Standardwert gesetzt werden.

Schleifenoptimierung: Vermeiden Sie teure Schleifenoperationen, versuchen Sie, Schleifen zu fusionieren und wiederholte Berechnungen aus dem Schleifenkörper zu verschieben.

2. Verwenden Sie vorcompilierte Verträge

Vorkompilierte Verträge bieten komplexe Bibliotheksfunktionen wie Kryptografie- und Hash-Operationen. Da der Code nicht auf dem EVM ausgeführt wird, sondern lokal auf dem Client-Node läuft, wird weniger Gas benötigt. Die Verwendung von vorkompilierten Verträgen kann Gas sparen, indem die Rechenlast reduziert wird, die zur Ausführung des Smart Contracts erforderlich ist.

Beispiele für vorcompilierte Verträge sind der Elliptic Curve Digital Signature Algorithm (ECDSA) und der SHA2-256-Hashing-Algorithmus. Durch die Verwendung dieser vorcompilierten Verträge in Smart Contracts können Entwickler die Gas-Kosten senken und die Effizienz der Anwendung verbessern.

Für eine vollständige Liste der von dem Ethereum-Netzwerk unterstützten vorkompilierten Verträge, siehe diesen Link [4].

3. Verwenden Sie Inline-Assembly

Inline-Assembly ermöglicht Entwicklern das Schreiben von Low-Level-, aber effizientem Code, der vom EVM direkt ausgeführt werden kann, ohne teure Solidity-Operationen zu verwenden. Inline-Assembly bietet auch eine präzisere Kontrolle über den Speicher- und Speichernutzung, was die Gas-Kosten weiter reduziert. Darüber hinaus kann Inline-Assembly einige komplexe Operationen durchführen, die mit Solidity allein schwer umzusetzen sind, was mehr Flexibilität für die Optimierung des Gasverbrauchs bietet.

Hier ist ein Beispiel für die Verwendung von Inline-Assembly, um Gas zu sparen:

Wie im obigen Beispiel zu sehen ist, hat der zweite Fall, der Inline-Assembly verwendet, eine höhere Gas-Effizienz im Vergleich zum Standardfall.

Die Verwendung von Inline-Assembly kann jedoch auch Risiken mit sich bringen und ist fehleranfällig. Daher sollte sie vorsichtig verwendet werden und wird nur erfahrenen Entwicklern empfohlen.

4. Verwenden Sie Layer 2-Lösungen

Layer 2 Lösungen können die Menge an Daten reduzieren, die auf der Ethereum-Hauptkette gespeichert und berechnet werden müssen.

Layer-2-Lösungen wie Rollups, Sidechains und State Channels entlasten die Transaktionsverarbeitung von der Haupt-Ethereum-Kette und ermöglichen schnellere und günstigere Transaktionen.

Durch das Bündeln einer großen Anzahl von Transaktionen reduzieren diese Lösungen die Anzahl der On-Chain-Transaktionen, was wiederum die Gasgebühren senkt. Die Verwendung von Layer-2-Lösungen verbessert auch die Skalierbarkeit von Ethereum, wodurch mehr Benutzer und Anwendungen am Netzwerk teilnehmen können, ohne dass es zu Überlastungen kommt.

5. Verwenden Sie Optimierungstools und -bibliotheken

Es gibt mehrere Optimierungstools zur Verfügung, wie der solc Optimierer, Truffles Build-Optimizer und Remixs Solidity-Compiler.

Diese Tools können die Bytecode-Größe minimieren, nicht verwendeten Code entfernen und die Anzahl der für die Ausführung von Smart Contracts erforderlichen Operationen reduzieren. In Kombination mit anderen Gas-Optimierungsbibliotheken wie „solmate“ können Entwickler die Gas-Kosten effektiv senken und die Effizienz von Smart Contracts verbessern.

Schlussfolgerung

Die Optimierung des Gasverbrauchs ist ein wichtiger Schritt für Entwickler, da dies nicht nur die Transaktionskosten minimiert, sondern auch die Effizienz von Smart Contracts in EVM-kompatiblen Netzwerken verbessert. Durch Priorisierung kostensparender Operationen, Reduzierung des Speicherplatzverbrauchs, Nutzung von Inline-Assembly und Befolgung anderer bewährter Verfahren, die in diesem Artikel erörtert werden, können Entwickler den Gasverbrauch von Verträgen effektiv senken.

Es ist jedoch wichtig zu beachten, dass Entwickler während des Optimierungsprozesses Vorsicht walten lassen müssen, um Sicherheitsanfälligkeiten zu vermeiden. Bei der Optimierung des Codes und der Reduzierung des Gasverbrauchs darf die inhärente Sicherheit des Smart Contracts niemals beeinträchtigt werden.

[1] https://ethereum.org/de/developers/docs/gas/
[2] https://ethereum.github.io/yellowpaper/paper.pdf
[3]https://www.evm.codes/
[4] https://www.evm.codes/precompiled

Haftungsausschluss:

  1. Dieser Artikel stammt aus [ PANewslab]. Das Urheberrecht liegt beim Originalautor [ CertiK]. Wenn Sie Einwände gegen den Nachdruck haben, kontaktieren Sie uns bitte.Gate LearnTeam, das Team wird es so schnell wie möglich gemäß den relevanten Verfahren bearbeiten.
  2. Haftungsausschluss: Die in diesem Artikel geäußerten Ansichten und Meinungen stellen ausschließlich die persönlichen Ansichten des Autors dar und stellen keine Anlageberatung dar.
  3. Andere Sprachversionen des Artikels werden vom Gate Learn-Team übersetzt. Sofern nicht anders angegeben, darf der übersetzte Artikel nicht kopiert, verteilt oder plagiiert werden.
Jetzt anfangen
Registrieren Sie sich und erhalten Sie einen
100
-Euro-Gutschein!