Originaltext: „Vanity Addresses“ von foobar

Zusammenstellung: Overnight-Porridge, die Art von DeFi

160 Millionen US-Dollar verschwanden und Wintermute verlor die Gelder. Wintermute ist einer der klügsten Market-Making-Fonds der Branche. Eines Morgens im September, als der Verantwortliche von Wintermute aufwachte, fand er eine ihrer wichtigen Geldbörsen hatte 9 Zahlen verloren. Gelder. Was führte also dazu, dass Wintermute gestohlen wurde? Dies wird durch eine schlechte Zufälligkeit in einem Vanity-Adressgenerator verursacht. Black-Hat-Hacker erzwingen brutal das Paar aus privatem Schlüssel und öffentlicher Adresse und übertragen dann eine große Menge an Krypto-Assets.

Es gibt auch eine Geschichte über einen Hackerangriff auf Indexed Finance, bei dem im Oktober 2021 16 Millionen US-Dollar gestohlen wurden und die gestohlenen Gelder dann an Adressen verschoben wurden, die mit 0xba5ed beginnen…. Was sie nicht wussten, war, dass die Vanity-Adresse auch von der schlimmen Zufallsschwachstelle betroffen war, die Wintermute plagte, und im September 2022 das gesamte Geld erneut gestohlen wurde und an eine andere gehackte Wallet-Adresse ging. Diebe sind rücksichtslos.

Auf welche Probleme stießen diese talentierten Entwickler und was können wir von ihnen lernen?

Auf der linken Seite befindet sich die normale Adresse, die für den WETH-Vertrag verwendet wird. Rechts ist eine hübsche Adresse mit 14 führenden Nullen für die MEV-Roboteroptimierung. Die gebräuchlichste Art von Vanity-Adresse ist eine mit vielen führenden Nullen.

Was ist zunächst einmal eine Vanity-Adresse (auch Vanity-Adresse genannt)? Eine Vanity-Adresse bezieht sich auf eine öffentliche Adresse, die ein Benutzer absichtlich erstellt, um sie mit seinem Wallet oder Smart Contract zu verknüpfen. Vielleicht beginnt sie mit 0x0000000, vielleicht beginnt sie mit 0xdeadbeef, vielleicht ist es eine andere reguläre Adresse. Für ihre Beliebtheit gibt es mehrere Gründe:

1. Gasoptimierung: Wintermute sparte 15.000 US-Dollar durch die Verwendung einer EOA-Adresse mit mehreren führenden Nullen. Klingt albern? Viele Leute stimmen zu, aber so funktioniert die EVM. Wenn Ihre Adresse viele Nullen enthält, kann die Transaktionsgebühr sinken. Wenn Sie also eine Smart-Contract-Adresse mit vielen führenden Nullen verwenden, werden Benutzer zufrieden sein, wenn sie damit interagieren, weil sie dadurch Geld sparen.

Das Ethereum Yellow Paper beschreibt, wie führende Nulladressen günstigeres Gas ermöglichen können

2. Vereinbarungsmarke. Wussten Sie, dass der 1-Zoll-Token-Vertrag mit 0x111111111... beginnt?

1-Zoll-Token-Vertrag

3. Wiederholbarkeit mehrerer Stränge. Meiner Meinung nach hat dies oberste Priorität und ist der Grund, warum jedes Protokoll für seine Bereitstellung eine Vanity-Adresse verwenden sollte. Ihre Anwendung kann in 15 verschiedenen EVM-Ketten existieren und überall dieselbe Adresse haben! Wäre das für Entwickler und Benutzer nicht einfacher?

Wann ist eine hübsche Adresse sicher?

Es gibt zwei Arten von Ethereum-Adressen: External Owned Accounts (EOA) und Smart-Contract-Konten. Wenn Sie eine Wallet wie MetaMask verwendet haben, ist jede darin enthaltene Adresse eine EOA, die zum Signieren von Nachrichten und zum Verarbeiten von Transaktionen verwendet wird. Vergleichen Sie dies mit einem Smart-Contract-Konto wie dem Uniswap-Vertrag, mit dem Menschen interagieren können, der jedoch keine eigenen Aktionen ausführen kann, ohne ausgelöst zu werden. Zusammenfassend ist es ganz einfach: Adressen mit guten Nummern sind für EOA-Konten nicht sicher, aber für Smart-Contract-Konten sind sie sicher.

Warum ist das so? Wir werden dies im Folgenden genauer erläutern, es hängt jedoch davon ab, wie die Vanity-Adresse generiert wird. Bei EOA-Konten gehen Sie Millionen von privaten Schlüsseln durch, bis Sie einen finden, der einer gut aussehenden öffentlichen Adresse entspricht. Allerdings kontrolliert der private Schlüssel die Gelder innerhalb eines EOA-Kontos. Wenn also die Zufälligkeit, die Sie zum Durchlaufen des privaten Schlüssels verwenden, gefährdet wird, ist Ihr gesamtes Konto ruiniert. Andererseits erfordert die Erstellung von Smart-Contract-Vanity-Adressen nur das Durchqueren öffentlicher Seeds, die keine Verwaltungsrechte für den Smart Contract gewähren.

Aus diesem Grund schlägt Wintermute fehl und OpenSea ist erfolgreich – das Generieren privater Schlüssel im unsicheren Speicher mit unsicherer Software ist schlecht. Aber auf diese Weise öffentliches Saatgut zu generieren ist ziemlich schön! Daher ist eine gute EOA-Adresse der Weg zum Bankrott, während eine gute Smart-Contract-Adresse der Weg zum Erfolg ist.

Warum erfordert das Protokoll eine hübsche Adresse?

Einfachere Dokumentation! Sie können in allen Ketten auf eine Vertragsadresse verweisen;

Benutzerüberprüfbar! Dieselbe Vertragsadresse wird nur dann angezeigt, wenn der Bytecode Byte für Byte übereinstimmt.

Entwickler können es überprüfen! Da identische Vertragsadressen nur bei exakter Übereinstimmung auftreten, können Sie knifflige kleine Änderungen in Ihrem Bereitstellungsskript erkennen;

Einfachere Integration! Andere Protokolle können Ihre Vertragsadresse fest in ihren Multi-Chain-Code kodieren, ohne ChainId-basierte if-Anweisungen verwenden zu müssen.

HINWEIS: Wir werden uns gleich mit einer detaillierten Bedienungsanleitung befassen. Indem wir zum ersten Mal alle Teile zusammenfügen, tauchen wir tief in den technischen Bereich ein und richten uns an Smart-Contract-Entwickler mit Erfahrung in der Bereitstellung von Smart Contracts in der Kette. Wenn Sie interessiert sind, lesen Sie weiter, aber wenn es nichts für Sie ist, machen Sie sich keine Sorgen, mitzuhalten. Am Ende gibt es eine zusätzliche technische Herausforderung (mit Belohnungen).

Smart Contract, schöne Adresse

Es gibt eine Möglichkeit, Smart-Contract-Vanity-Adressen zu generieren, die 100 % sicher sind, egal welche Software Sie verwenden, es spielt keine Rolle, ob die iterative Technologie öffentlich durchgesickert ist. Es heißt „CREATE2-Factory-Methode“ und stellt nicht nur eine hübsche Adresse bereit, sondern ist auch eine narrensichere Möglichkeit, sicherzustellen, dass Sie in mehreren Ketten über dieselbe Vertragsbereitstellungsadresse verfügen. Es ermöglicht auch anderen, Code in Ihrem Namen vertrauenswürdig bereitzustellen, ohne dass private Schlüssel geteilt werden müssen oder Nonce-Annahmen erforderlich sind.

Zunächst ein kurzer Überblick über die Auswahl einer Smart-Contract-Adresse. Es gibt zwei Bereitstellungsoptionen: CREATE und CREATE2. Wenn Sie einen Smart Contract direkt von EOA aus bereitstellen, ist der Standardprozess CREATE. Die Adresse wird durch Hashing der Adresse des Vertragserstellers mit der Nonce des Vertragserstellers ermittelt. Diese Nonce bezieht sich darauf, wie viele Transaktionen eine Adresse gesendet hat, sodass ein neues Wallet bei 0 beginnt und jedes Mal, wenn eine neue Transaktion gesendet wird, um 1 erhöht wird. Hier ist die Zauberformel für die von CREATE bereitgestellte Smart-Contract-Adresse:

neue_Adresse = Hash(Absender, Nonce)

Weniger verbreitet, aber interessanter ist die mit CREATE2 bereitgestellte Smart-Contract-Adresse. Hier ist die Formel:

neue_Adresse = Hash(0xFF, Absender, Salt, Bytecode)

Ersteres scheint einfacher zu sein, oder? Lassen Sie uns jedoch ein Beispiel dafür geben, wo diese Einfachheit im Vergleich zum robusteren CREATE2-Prozess nachteilig sein kann.

Airy Alice: Es gibt ein Problem mit Multi-Chain

Stellen Sie sich vor, eine Krypto-Entwicklerin namens Alice erstellt zwei Smart Contracts: einen Uniswap-Fork namens GriddleSwap und ein NFT-Projekt namens ph00ts. Sie sind alle unveränderliche, unabhängige Grundelemente, was bedeutet, dass keine externen Abhängigkeiten oder Cross-Chain-Bridge-Risiken bestehen. Alice stellt GriddleSwap mit Nonce 0 für Ethereum bereit und stellt dann ph00ts mit Nonce 1 für Ethereum bereit. Leider hat Alice eine kurze Aufmerksamkeitsspanne und war einige Minuten lang auf Krypto-Twitter abgelenkt, bevor sie ihre Arbeit bei Binance Smart Chain (BSC), der zweitgrößten Smart-Contract-Plattform, einsetzte.

Ups, ich habe die Einsatzreihenfolge durcheinander gebracht!

Aber warten Sie! Sie hat die Bereitstellungsreihenfolge durcheinander gebracht und ph00ts vor GriddleSwap bereitgestellt. Da die Smart-Contract-Adresse nur auf der Erstelleradresse basiert, hat Ethereum Gridleswap in der bereitgestellten Blockchain genau dieselbe Adresse wie BSC ph00ts. Erschwerend kommt hinzu, dass die Adresse von Ethereum ph00ts mit der Adresse von BSC GriddleSwap identisch ist. Zu glauben, dass die Endbenutzer verwirrt sein werden, ist eine Untertreibung. Tatsächlich kann es von böswilligen Deployern missbraucht werden, um Menschen zu der Annahme zu verleiten, dass das Vertragsverhalten in der Kette dasselbe ist – was angesichts der gleichen Adresse eine berechtigte Annahme ist!

Vorsicht Alice: Es wird immer noch Probleme geben

Auch wenn Alice beim Einsatz vorsichtig ist und die Reihenfolge ihrer Nonces nie durcheinander bringt, gibt es andere Probleme. Wenn Alice korrekt auf Ethereum und BSC bereitgestellt wird, dann aber eine unabhängige Transaktion auf Polygon durchführt, ist Nonce 0 aufgebraucht. Sie kann GriddleSwap dort nie bereitstellen, da ihre Nonce erhöht wurde. Daher müssen die privaten Schlüssel des Bereitstellers unbedingt geschützt werden. Wenn Alice es preisgibt, kann ein böswilliger Saboteur Transaktionen durchführen, die nichts damit zu tun haben. Wenn Alice es verliert, verliert sie auch die Fähigkeit, diese Adresse erneut in einer neuen Kette bereitzustellen. Hierbei handelt es sich um eine permanente Schwachstelle, die darauf angewiesen ist, dass eine ehrliche Person den privaten Schlüssel schützt. Wenn nicht einmal Bitcoin-Core-Entwickler das können, wie soll es dann der Rest von uns schaffen?

Lösung: CREATE2

Glücklicherweise gibt es eine bessere Möglichkeit, konsistente Adressen über Ketten hinweg zu erhalten – eine, die nicht auf geheime private Schlüssel angewiesen ist, nicht auf einen einzelnen Deployer angewiesen ist und auf dem Weg resistent gegen Deployer-Fehler ist. Denken Sie an die Formel zum Ermitteln der Adresse eines mit CREATE2 bereitgestellten Smart Contracts:

neue_Adresse = Hash(0xFF, Absender, Salt, Bytecode)

Der erste Parameter 0xFF ist ein konstanter Wert, der ignoriert werden kann. Der zweite Parameter (Absenderadresse) kann durch Auswahl der CREATE2Factory-Bereitstellung 0x0000000000FFe8B47B3e2130213B802212439497 von z0age in den meisten EVM-Ketten konsistent gemacht werden. Der dritte Parameter ist ein vom Benutzer ausgewählter Salt, mit dem wir eine gute Adresse finden und diese dann unverändert in der Kette belassen können. Der vierte ist der Vertragsbytecode, der als nützliche Plausibilitätsprüfung dient, um sicherzustellen, dass wir genau die gleiche Funktionalität in der Kette bereitstellen. Alle vier Parameter können gleich bleiben, unabhängig davon, was ein einzelner Bereitsteller tut.

Warum ist das besser? Im Gegensatz zum privaten Schlüssel kann der vom Bereitsteller ausgewählte Salt öffentlich gemacht werden. Wenn Sie den Salt kennen, können Sie den Vertrag bereitstellen, haben jedoch keinerlei Kontrolle über die Vertragswerte oder -funktionen. Da keine geheimen Informationen gebunden sind, kann jeder den Vertrag in der neuen Kette bereitstellen, ohne den privaten Schlüssel preiszugeben oder weiterzugeben. Der Bytecode-Parameter stellt außerdem sicher, dass diese neuen erlaubnislosen Bereitstellungen genau dann dieselbe Adresse haben, wenn der Bytecode derselbe ist. Daher erhalten Endbenutzer stärkere Garantien, ohne detaillierte Codeunterschiede vornehmen zu müssen.

Einen ausführlicheren Überblick finden Sie im populärwissenschaftlichen Artikel von OpenZeppelin‌.

Erstellen Sie Ihre eigene schöne Adresse

Denken Sie, dass Proof of Work (PoW) nach der Ethereum-Fusion nutzlos sein wird? Denk nochmal! Die gleichen GPU-Fähigkeiten, die beim Auffinden von Hash-Vorbildern mit einer großen Anzahl führender Nullen für Bitcoin-Blöcke helfen, eignen sich auch hervorragend zum Auffinden von Hash-Vorbildern mit einer großen Anzahl führender Nullen für EVM-Smart Contracts. z0age von OpenSea (dank seiner Erklärung für diesen Beitrag) hat ein einfaches Setup zum Erstellen einer eigenen Vanity-Adresse gefunden.

1. Verwenden Sie broad.ai‌, um eine GPU-Beispielinstanz zu starten, die etwa 2 Milliarden Mal pro Sekunde versucht und etwa 25 Cent/Stunde kostet:

Bild: nvidia / opencl

Grafikkarte: 1x RTX 3090

Zuzuweisender Speicherplatz: 1,83 GB

2. SSH und installiere rust + create2crunch

sudo apt install build-essential -y; curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; Quelle "$HOME/.cargo/env"; git clone https://github.com/0age/create2crunch && cd create2crunch; sed -i ‚s/0x4/0x40/g‘ src/lib.rs

3. Führen Sie eine Seed-Suche durch. Für Umgebungsvariablen ist INIT_CODE_HASH der keccak256 des Vertragserstellungscodes. Einen Ausdruck eines Beispiel-Foundry-Tests finden Sie hier ‌ – überprüfen Sie ihn unbedingt, bevor Sie große Mengen an Rechenressourcen verbrauchen! LEADING sollte die gewünschte Anzahl führender Nullbytes sein, und TOTAL sollte die Gesamtanzahl der gewünschten Nullbytes in der Vertragsadresse sein.

export FACTORY="0x000000000ffe8b47b3e2130213b802212439497"; export CALLER="0x0000000000000000000000000000000000000000000"; export INIT_CODE_HASH="0xabc...def"; export LEADING=5; export TOTAL=7; Frachtlauf --Release $FACTORY $CALLER $INIT_CODE_HASH 0 $LEADING $TOTAL

Als z0age sein Repo zum ersten Mal veröffentlichte, war es in der Lage, 1,9 Milliarden Versuche pro Sekunde auf der oben genannten VastAI-Hardware auszuführen. Seitdem ist die Vektorisierung auf einigen OpenGL-Kernen verrückt geworden und ich habe 2,15 Milliarden Versuche pro Sekunde beobachtet. Das bedeutet, dass das Finden einer Adresse mit 5 führenden Null-Bytes 256^5/(2150000000 * 60) ~= 8 Minuten und das Finden einer Adresse mit 6 führenden Null-Bytes 256^6/(2150000000 * 3600) ~= 36 Stunden dauern würde . Eine 7 führende Null-Byte-Adresse dauert 256^7/(2150000000 * 86400) ~= 387 Tage. Beachten Sie, dass ein Byte zwei hexadezimalen Zeichen entspricht, sodass eine Adresse mit 5 führenden Bytes 10 Nullen enthält. Natürlich kann diese Suche vollständig parallelisiert werden und die tatsächliche Erfolgswahrscheinlichkeit im Zeitverlauf folgt einer Poisson-Verteilung.

Stellen Sie die CREATE2-Factory bereit

Aufmerksamen Lesern ist vielleicht aufgefallen, dass die CREATE2-Factory bereits bei 0x0000000000FFe8B47B3e2130213B802212439497 in allen Ketten existiert. Es ist ein bisschen ein Henne-Ei-Problem: Wie hängt eine konsistente Adressbereitstellung von einer konsistenten Adressbereitstellung ab?

Als ich zum ersten Mal von diesem Ansatz erfuhr, dachte ich, es sei nur ein privater Schlüssel, der von jemandem gehalten wird, der schlauer ist als ich (das Szenario der „aufmerksamen Alice“ oben). Aber es ist tatsächlich viel robuster! Der „schlüssellose Transaktionen“-Ansatz des ENS-Gründers Nick Johnson nutzt die Tatsache aus, dass man die öffentliche Adresse aus jeder Transaktionssignatur wiederherstellen kann, ohne den entsprechenden privaten Schlüssel zu kennen, der sie signiert hat. Daher ist es möglich, eine Transaktion zu erstellen („eine create2-Factory bereitstellen“) und dann eine gefälschte Signatur dafür zu erfinden, beispielsweise eine, die nur aus 2 besteht. Der private Schlüssel für diese gefälschte Signatur existiert, aber niemand weiß, was er ist. Aber wir können die öffentliche Adresse, die der „schlüssellosen Signatur“ entspricht, wiederherstellen, ihr etwas ETH schicken und dann die signierte Transaktion an den Mempool übermitteln. Trotz der Unklarheit dieser Methode handelt es sich um eine gültige Transaktion und tatsächlich um die einzige gültige Transaktion, die von dieser öffentlichen Adresse gesendet werden kann.

Das Ergebnis: Jeder kann eine Fabrik ohne proprietäre Informationen in einer neuen Kette bereitstellen und gleichzeitig verhindern, dass böswillige Akteure Schaden anrichten. Das Erstellen einer EOA für einen einzigen Zweck, die nur eine Transaktion bereitstellen kann, ist eine sehr clevere Technik.

Spezifische Adressen und Verträge, die bei schlüssellosen Transaktionen erstellt werden

Dies kann mit drei einfachen „Forge Cast“-Befehlen erreicht werden. Der Bytecode ist zu lang, um ihn hier zu kopieren, aber Sie können den Anweisungen unter https://github.com/ProjectOpenSea/seaport/blob/main/docs/Deployment.md‌ ohne Erlaubnis in einer beliebigen Kette Ihrer Wahl folgen. Stellen Sie CREATE2 Factory einfach bereit!

Wenn es bereits bereitgestellt wurde, ist es natürlich nicht erforderlich, es erneut bereitzustellen.

Randbemerkung: Die EIP-155-Anforderungen sind schrecklich

Ein kurzer Versuch, meine L1-Governance-Abenteuer zu unterstützen. Sie können gerne weitermachen. EIP-155‌ ist ein Vorschlag von Vitalik aus dem Jahr 2016, der das Konzept der „Chain-ID“ einführt, um Replay-Angriffe zu verhindern. Jede Kette hat ihre eigene eindeutige Kennung – 1 für Ethereum, 56 für BSC und 137 für Polygon – die in signierten Transaktionen enthalten sein wird, um Wiederholungsangriffe zu verhindern, was von Ethereum schnell übernommen wurde, und alle anderen EVM-Ketten sind diesem Vorschlag gefolgt. Das ist großartig, aber das Problem tritt auf, wenn ein paar Ketten ausgewählt werden, wie zum Beispiel Evmos, das kürzlich beschlossen hat, Transaktionen vor EIP-155 ausdrücklich zu verbieten, was aus seltsamen Gründen einen Betriebsfehler verhindert, bei dem Optimism 20 Millionen OP-Token an ein Multisig gesendet hat (Ja, sie schon wieder) weisen darauf hin, dass Wintermute nicht existiert, behauptet, es zu besitzen, aber nie initialisiert wurde. Die Deaktivierung von Transaktionen vor 155 würde jedoch eine ganze Reihe kettenübergreifender Bereitstellungen, wie etwa die CREATE2-Fabrik und führende Projekte wie Seaport, erheblich zum Scheitern bringen. Diese Governance-Vorschläge sollten sofort zurückgenommen werden, und Schutzdetails wie diese sollten aus der Wallet und nicht aus der Konsensschicht stammen. Wenn Multi-Chain die Zukunft ist, werden diese unnötigen Einschränkungen ein großes Hindernis für die Bereitstellung von Top-Projekten in Ihrer Blockchain darstellen.

Lustige Sache: Kopfgelder einsetzen

Heute wird https://delegate.cash auf 7 verschiedenen EVM-Ketten (Ethereum, Polygon, Optimism, Celo, Avalanche, Fantom und Arbitrum) und 7 diesen Ketten entsprechenden Testnetzen eingesetzt. Die Vertragsadresse für alle ist dieselbe: 0x00000000000076A84feF008CDAbe6409d2FE638B.

Reicht das also? Nein, wir brauchen mehr Ketten. Da es sich bei Delegatecash um ein unabhängiges Grundelement mit null Abhängigkeiten handelt, bedeutet dies, dass das Risiko mehrerer Ketten praktisch null ist. Das ist purer Gewinn! Deshalb werde ich den ersten 5 Personen, die den Delegatecash-Smart-Vertrag in der neuen Kette und dem entsprechenden Testnetz bereitstellen und verifizieren, einen Bonus von 100 USDC gewähren!

Hier müssen Sie das Bereitstellungsskript aus dem Open-Source-Repository verwenden. Dies erfordert möglicherweise die Bereitstellung der CREATE2 Factory, falls diese nicht vorhanden ist, und vergessen Sie nicht die Etherscan-Überprüfung! Viel Spaß beim Einsatz und viel Spaß beim erlebnisorientierten Lernen!