Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung

2. Februar 2023 Daejun-Park

Formale Verifizierung – der Prozess der Verwendung mathematischer Methoden zur „Inspektion“ eines Programms oder Smart Contracts über eine beliebige Anzahl von Eingaben hinweg – wird im Allgemeinen als die prägnantere, umfassendere Alternative zu herkömmlichen Tests angesehen, um qualitativ hochwertigeren und sichereren Code zu schreiben. Aber in Wirklichkeit ist die formale Verifizierung ein offener und interaktiver Prozess. Ähnlich wie beim Komponententest müssen Entwickler formale Spezifikationen dynamisch definieren und aufschichten und ihren Ansatz iterieren, wenn sich ihr Code und ihre Analysen weiterentwickeln. Darüber hinaus ist die formale Verifizierung nur so effektiv wie ihre Spezifikationen, deren Erstellung zeitaufwändig sein kann (und oft mit einer steilen Lernkurve einhergeht). 

Für viele Entwickler, die den Prozess entmutigend finden, sind Unit-Tests oft der kostengünstigere und zeiteffizientere Weg, um die Korrektheit eines Programms herauszufinden. Formale Verifikation ist in der Praxis keine umfassendere Alternative zum Unit Testing, sondern eine ergänzende. Diese Prozesse haben unterschiedliche Stärken und Einschränkungen und bieten eine noch größere Sicherheit, wenn sie zusammen verwendet werden. Entwickler müssen immer Komponententests schreiben – was wäre also, wenn wir dieselben Eigenschaften für die formale Verifizierung verwenden könnten?

Halmos, unser formelles Open-Source-Überprüfungstool, ermöglicht Entwicklern dies Wiederverwendung die gleichen Eigenschaften, die für Unit-Tests für formale Spezifikationen durch symbolisches Testen geschrieben wurden. Anstatt von Anfang an einen robusten Satz von Eigenschaften erstellen zu müssen, können Entwickler Doppelarbeit vermeiden und ihre Tests um einige Spezifikationen auf einmal verbessern, ohne bei Null anfangen zu müssen. Wir haben dieses Tool neben anderen im formalen Verifizierungsprozess als Einstieg in die formale Verifizierung entwickelt; Entwickler können mit minimalem Aufwand mit ein paar Analysen beginnen, bevor sie später im Prozess weitere hinzufügen.

In diesem Beitrag behandeln wir die Herausforderungen der formalen Verifikation und das Potenzial, die Lücke zwischen Unit-Tests und formaler Verifikation mit symbolischen Tests zu schließen. Anschließend führen wir eine Halmos-Demo mit vorhandenem Smart-Contract-Code durch und werfen einen kurzen Blick auf andere formale Verifizierungstools (viele Open Source), die Entwicklern zur Verfügung stehen.

Formale Verifizierung vs. Testen

Formale Überprüfung – im Allgemeinen von Blockchain-Entwicklern wegen seiner Strenge und Vollständigkeit bevorzugt – ist der Prozess des Nachweises der Korrektheit eines Programms, indem überprüft wird, ob es bestimmte Korrektheitseigenschaften erfüllt. Die programmspezifischen Eigenschaften werden in der Regel extern bereitgestellt und in einer formalen Sprache oder Notation ausgedrückt, die vom verwendeten Verifikationstool unterstützt wird. Entwickler nehmen die formale Verifizierung oft als eine Lösung auf Knopfdruck zum automatischen Testen von Eigenschaften in allen möglichen Szenarien wahr, aber in Wirklichkeit kann die formale Verifizierung ein arbeitsintensiver und hochgradig interaktiver Prozess sein.

Wie bei der formalen Verifizierung geht es beim Komponententest darum, zu bewerten, ob ein Programm wie erwartet funktioniert; Beim Testen wird jedoch nur das Verhalten des Programms überprüft einige Eingaben, während die formale Überprüfung sie überprüfen kann alle mögliche Eingänge. Sowohl das Testen als auch die formale Verifikation erfordern eine Beschreibung des erwarteten Verhaltens des Programms (mit Testfällen, die beim Testen verwendet werden, und formalen Spezifikationen, die bei der formalen Verifikation verwendet werden). Wenn sie jedoch zusammen verwendet werden, können sie eine gründlichere Untersuchung eines Programms ermöglichen. Testen ist zum Beispiel effektiv beim Auffinden einfacher Bugs und Fehler, ist aber im Allgemeinen schneller und einfacher durchzuführen. Die formale Verifizierung ist zwar umständlicher in der Anwendung, aber leistungsfähig genug, um die Abwesenheit von Fehlern zu beweisen oder subtile Fehler aufzudecken, die beim Testen oder Code-Reviews leicht zu übersehen sind.

Spezifikationsaufwand

Eine der größten Herausforderungen bei der formalen Verifikation ist der Aufwand für das Schreiben und Pflegen formaler Spezifikationen. Dieser Prozess beinhaltet oft die zeitaufwändige Aufgabe, die Spezifikationen manuell in einer spezialisierten Sprache zu schreiben (die viele Entwickler erst lernen müssen). Der Prozess ist auch inkrementell und beginnt normalerweise damit, einfache Eigenschaften zu schreiben und sie zuerst zu verifizieren, und dann nach und nach komplexere Eigenschaften hinzuzufügen. Wie das Testen ist es ein offener Prozess ohne klaren Endpunkt, und man kann nur so viele Eigenschaften wie möglich innerhalb des verfügbaren Zeitrahmens hinzufügen. Wenn Entwickler den Code während der Überprüfung ändern, müssen sie außerdem ihre vorhandenen Spezifikationen aktualisieren, was zu zusätzlichem Wartungsaufwand führt. Diese Faktoren können die formale Verifizierung zu einer entmutigenden Aufgabe für einige Entwickler machen, die zögern, sich auf den zusätzlichen Aufwand einzulassen.

Und obwohl Testen und formale Verifikation die Codequalität verbessern können, wenn sie zusammen verwendet werden, erfordern beide (manchmal ähnliche) Beschreibungen des erwarteten Verhaltens eines Programms in verschiedenen Sprachen und Formaten. Das Schreiben und Pflegen dieser Beschreibungen ist arbeitsintensiv, und die Pflege von zwei verschiedenen Formen derselben Beschreibung kann sich wie doppelter Aufwand anfühlen. Dies wirft die folgende Frage auf: Ist es möglich, das erwartete Verhalten so zu beschreiben, dass Entwickler es sowohl zum Testen als auch zum Verifizieren verwenden können?

Überbrückung der Lücke zwischen Testen und formaler Verifikation mit symbolischem Testen und Halmos

Symbolisches Testen, das Ausführen von Tests mit symbolischen Eingaben, ist eine effektive formale Verifizierungsmethode, die den Spezifikationsaufwand reduziert. Dieser Ansatz ermöglicht die Verwendung derselben Testfälle sowohl für das Testen als auch für die formale Verifikation. Im Gegensatz zum herkömmlichen Testen, bei dem überprüft wird, ob ein Programm für eine begrenzte Anzahl von Eingaben korrekt funktioniert, wird beim symbolischen Testen das Programm auf alle möglichen Eingaben überprüft. Daher kann ein Programm, das den symbolischen Test besteht, als formal verifiziert angesehen werden.

Halmos ist ein formales Verifikationstool, das für symbolisches Testen entwickelt wurde. Anstatt separate Spezifikationen zu verlangen oder eine neue Sprache zu lernen, verwendet Halmos bestehende Tests als formale Spezifikationen. Durch das Ausführen von Tests über Halmos wird automatisch überprüft, ob sie für alle möglichen Eingaben bestanden werden, oder es werden Gegenbeispiele bereitgestellt. Dies macht nicht nur das Schreiben zusätzlicher Spezifikationen überflüssig, sondern ermöglicht auch die Wiederverwendung von Tests, die für Unit-Tests oder Fuzzing geschrieben wurden, für formale Verifizierungszwecke.

Entwickler haben somit eine größere Flexibilität bei der Auswahl aus einer Reihe von Qualitätssicherungsoptionen, einschließlich Unit-Tests, Fuzzing und formaler Verifizierung, je nach ihren aktuellen Anforderungen. Beispielsweise können Tests einfache Fehler schnell identifizieren, möglicherweise mit Hilfe eines Fuzzers, der zufällige Eingaben generiert, und dann kann Halmos das Vertrauen in die Korrektheit des Programms über alle Eingaben hinweg weiter erhöhen.

Beispiel: Testen der isPowerOfTwo() Funktion

Betrachten Sie als Beispiel das Folgende isPowerOfTwo() Funktion, die bestimmt, ob eine gegebene Zahl eine Zweierpotenz ist. Diese Funktion verwendet a Bit-Manipulationsalgorithmus für die Effizienz, aber es kann schwierig sein, seine Korrektheit zu beweisen, insbesondere in dem Fall, in dem die Eingabe keine Zweierpotenz ist.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Stellen Sie sich den folgenden Test für die vor isPowerOfTwo() Funktion: Sie vergleicht die tatsächliche Ausgabe der Funktion mit der erwarteten Ausgabe für eine gegebene Eingabe. Dies ist ein parametrisierter Test (auch als eigenschaftsbasierter Test bekannt), was bedeutet, dass Sie ihn problemlos mit unterschiedlichen Eingabewerten ausführen können, möglicherweise mit Fuzzing-Tools wie Foundry.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Mit diesem Test können Sie das überprüfen isPowerOfTwo() Funktion durch Unit-Tests oder Fuzz-Tests, die mit einer Auswahl von Eingaben ausgeführt werden. Tests wie diese können die Korrektheit der Funktion nicht formal beweisen, da es rechnerisch unmöglich ist, den Test für jede mögliche Eingabe durchzuführen.

Halmos ermöglicht es Entwicklern jedoch, diese bereits vorhandenen Tests mit nur geringem zusätzlichen Aufwand für die formale Verifizierung wiederzuverwenden. Das Tool prüft, ob Tests für alle möglichen Eingaben bestanden werden, indem es eine symbolische Ausführung des Tests durchführt und dann überprüft, ob die Assertion niemals verletzt wird (oder, falls die Assertion is verletzt, durch Angabe eines Gegenbeispiels). Das heißt, wenn der Test Halmos besteht, ist die Korrektheit der Funktion formal verifiziert, d. h. der Algorithmus ist korrekt implementiert und wurde vom Compiler korrekt in Bytecode übersetzt.

Einschränkung: Begrenzte symbolische Ausführung

Ein vollautomatisches, vollständiges symbolisches Testen ist im Allgemeinen nicht möglich, da dies das Lösen der erfordern würde Problem zu stoppen, was bekanntlich ist unentscheidbar. Ein Grund dafür ist, dass oft nicht automatisch bestimmt werden kann, wie oft eine Schleife symbolisch durchlaufen werden soll. Dadurch ist eine vollautomatische formale Verifikation in der Regel unentscheidbar.

Angesichts dieser grundlegenden Einschränkungen gibt Halmos der Automatisierung Vorrang vor der Vollständigkeit. Zu diesem Zweck ist Halmos so konzipiert, dass es begrenzte symbolische Argumentation für unbegrenzte Schleifen (wobei die Anzahl der Iterationen von Programmeingaben abhängt) oder Arrays mit variabler Länge (einschließlich Zeichenfolgen) durchführt. Dies opfert etwas Vollständigkeit, erlaubt es Halmos jedoch zu vermeiden, dass der Benutzer zusätzliche Anmerkungen wie Schleifeninvarianten bereitstellen muss.

Betrachten Sie beispielsweise die folgende iterative Version von isPowerOfTwo() Funktion, die eine unbegrenzte While-Schleife enthält, bei der die Anzahl der Schleifeniterationen durch die Mindestanzahl von Bits bestimmt wird, die zur Darstellung der Eingabezahl erforderlich sind.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Halmos wiederholt diese unbegrenzte Schleife symbolisch nur bis zu einer bestimmten Grenze. Wenn die Grenze beispielsweise auf 3 gesetzt ist, wird Halmos die Schleife höchstens dreimal durchlaufen und keine Eingabewerte berücksichtigen, die dazu führen würden, dass die Schleife mehr als dreimal durchlaufen wird (dh alle Werte größer oder gleich 3^3 ). In diesem speziellen Fall würde das Festlegen der Grenze auf 2 oder höher ermöglichen, dass Halmos vollständig ist.

Demo: Formale Verifikation von ERC721A mit Halmos

Um die Fähigkeiten von Halmos zu demonstrieren, haben wir es verwendet, um es symbolisch zu testen und formal zu verifizieren ERC721A, eine stark gasoptimierte Implementierung des ERC721-Standards, die eine Stapelprägung zu fast den gleichen Kosten wie eine Einzelprägung ermöglicht. ERC721A enthält mehrere innovative Optimierungen um diese Effizienz zu erreichen; Beispielsweise kann Gas eingespart werden, indem Aktualisierungen der Token-Besitzdaten verzögert werden, bis der Token übertragen wird, nicht zum Zeitpunkt der Prägung. Dies erfordert die Verwendung komplexer Datenstrukturen und Algorithmen, um Eigentumsinformationen effizient aus der faulen Datenstruktur abzurufen. Und obwohl diese Optimierung die Gaseffizienz verbessert, erhöht sie auch die Codekomplexität und macht es schwierig, die Korrektheit der Implementierung zu beweisen. Dies macht ERC721A zu einem guten Kandidaten für eine formelle Verifizierung, da es das Vertrauen in die Implementierung stärken und potenziellen Benutzern zugute kommen kann.

Symbolische Testeigenschaften

Da die bestehenden Tests für ERC721A in JavaScript mit Hardhat geschrieben wurden (was derzeit nicht von Halmos unterstützt wird), haben wir neue Tests in Solidity für die wichtigsten Einstiegspunktfunktionen geschrieben: mint(), burn() und transfer(). Diese Tests überprüften, ob jede Funktion den Token-Besitz und das Guthaben korrekt aktualisiert und nur die relevanten Benutzer betrifft, ohne das Guthaben oder den Besitz anderer Benutzer zu ändern. Letzteres ist aufgrund der Verwendung des Lazy-Data-Structure-Algorithmus in ERC721A nicht trivial zu beweisen. Der folgende Test überprüft beispielsweise, ob die transfer() -Funktion aktualisiert den Besitz des angegebenen Tokens korrekt:

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Ein weiterer Test prüft, ob die transfer() Die Funktion ändert nicht das Gleichgewicht für andere Adressen, was wie bereits erwähnt schwierig zu beweisen ist:

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Symbolisches Testen mit Halmos: Nutzung bestehender Tests zur formalen Verifizierung von PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Verifizierungsergebnisse

Wir haben ein Verifizierungsexperiment mit Halmos auf dem Smart Contract ERC721A durchgeführt, indem wir insgesamt geschrieben haben 19-Tests. Die Tests wurden durch Halmos mit einer Schleifenentrollungsgrenze von 3 durchgeführt, was 16 Minuten dauerte. Die Aufschlüsselung der Verifizierungszeit ist der folgenden Tabelle zu entnehmen. Das Experiment wurde auf einem MacBook Pro mit M1 Pro Chip und 16 GB Speicher durchgeführt.

Test Zeit (en)
testBurnBalanceUpdate 6.67
testBurnNextTokenIdUnchanged 1.40
testBurnOtherBalancePreservation 5.69
testBurnOwnershipPreservation 189.70
testBurnOwnershipUpdate 3.81
testBurnAnforderungen 71.95
testMintBalanceUpdate 0.20
testMintNextTokenIdUpdate 0.18
testMinzeSonstigesBalanceErhaltung 0.26
testMinzeSonstigesEigentumErhaltung 5.74
testMintOwnershipUpdate 1.38
testMintAnforderungen 0.09
testTransferBalanceUnverändert 9.03
testTransferBalanceUpdate 53.53
testTransferNextTokenIdUnchanged 4.47
testTransferOtherBalancePreservation 19.57
testTransferOtherOwnershipPreservation 430.61
testTransferOwnershipUpdate 18.71
testTransferAnforderungen 149.18

Während die meisten Tests in Sekundenschnelle abgeschlossen waren, dauerten einige von ihnen mehrere Minuten. Diese zeitaufwändigen Tests waren aufgrund der Komplexität der zu berücksichtigenden Fälle schwierig zu überprüfen und standen in engem Zusammenhang mit der Korrektheit des Lazy-Data-Structure-Algorithmus.

Insgesamt zeigen die Ergebnisse dieses Experiments, dass Halmos in der Lage ist, die Korrektheit des Smart Contract Codes effektiv zu überprüfen. Es bietet trotz der Komplexität und potenziellen Grenzfälle des Smart Contracts ein erhöhtes Vertrauen in die Integrität des Codes.

Experimentieren Sie mit injizierten Fehlern

Um die Wirksamkeit von Halmos' Bounded Reasoning zu demonstrieren, haben wir es verwendet, um Fehler in einer früheren Version des ERC721A-Vertrags zu erkennen. Diese Version hatte ein Problem, das einen arithmetischen Überlauf falsch handhabte und möglicherweise das Batch-Minting einer großen Anzahl von Token ermöglichte, was die Integrität der faulen Datenstruktur brechen und dazu führen könnte, dass einige Benutzer ihren Token-Besitz verlieren (ein Problem entschlossen in der aktuellen Version). Wir haben den gleichen Satz von 19 Tests für ERC721A auf der Buggy-Version durchgeführt, und Halmos konnte ein Gegenbeispiel für die Eigenschaften des finden mint() Funktion. Insbesondere lieferte Halmos Eingabewerte, die zu dem oben beschriebenen Exploit-Szenario führten. Die Ergebnisse dieses Experiments zeigen, dass die begrenzte Argumentation von Halmos trotz ihrer Unvollständigkeit ein wirksames Mittel sein kann, um ausnutzbare Fehler in Smart Contracts zu erkennen und zu verhindern.

Verwandte Arbeit

Formale Verifizierungstools für den Bytecode des Smart Contract von Ethereum wurden von verschiedenen Teams entwickelt. Diese Tools, einschließlich Halmos, können verwendet werden, um die Sicherheit und Korrektheit von Smart Contracts zu gewährleisten. Der Vergleich und das Verständnis der verschiedenen Funktionen, Fähigkeiten und Einschränkungen dieser Tools kann Entwicklern helfen, das für ihre individuellen Anforderungen am besten geeignete auszuwählen.

Während Halmos eine wertvolle Ergänzung des Toolsets ist, das für die Smart Contract Verifizierung verfügbar ist, soll es bestehende Tools ergänzen (nicht ersetzen). Entwickler können Halmos mit anderen Tools kombinieren, um ein höheres Maß an Sicherheit in ihren Verträgen zu erreichen. Im Folgenden vergleichen wir Halmos mit einigen ausgewählten formalen Tools, die EVM-Bytecode unterstützen.

  • K ist ein leistungsfähiges formales Verifikations-Framework, das deduktive Verifikation und interaktives Beweisen von Theoremen ermöglicht. Seine zugrunde liegende Theorie und Implementierung bieten eine hohe Aussagekraft und eignen sich daher für die Verifikation komplexer Programme und Algorithmen. Es sollte jedoch beachtet werden, dass K nicht mit starkem Schwerpunkt auf automatisierter Verifizierung entwickelt wurde und bestimmte Automatisierungsfunktionen fehlen, die während des Verifizierungsprozesses mehr manuellen Aufwand erfordern können. Um das K-Framework zu verwenden, werden formale Spezifikationen in der K-Sprache geschrieben, die vor der Verwendung erlernt werden muss. Seine Stärke ist besonders nützlich bei der Verifizierung komplexer Systeme, deren Analyse mit automatisiertem Denken schwierig sein kann.
  • Certora ist ein formales Verifizierungstool für Smart Contracts, das sich auf die automatisierte Verifizierung konzentriert und ähnlich wie Halmos eine begrenzte Modellprüfung unterstützt. Um Certora verwenden zu können, müssen Entwickler ihre neue Sprache lernen, CVL, um Spezifikationen zu schreiben. Diese Sprache ermöglicht die präzise Beschreibung vieler kritischer Eigenschaften durch Vertragsinvarianten, eine Funktion, die Halmos derzeit nicht unterstützt. Obwohl Certora ein proprietäres Closed-Source-Tool ist, bietet es robuste formale Verifizierungstools mit laufender Entwicklung und guter Benutzerunterstützung.

    Halmos hingegen ist ein kleineres Open-Source-Tool, dem derzeit einige von Certora bereitgestellte Funktionen fehlen, aber es soll als öffentliches Gut dienen und als Nischenlösung für die schnelle Überprüfung von Smart Contracts ohne die Notwendigkeit einer umfangreichen Einrichtung und Wartung.
  • HEVM ist ein weiteres formales Überprüfungstool, das Halmos ähnelt. Es war zuvor Teil von DappTools, einem Vorläufer von Foundry. Sowohl HEVM als auch Halmos haben das Merkmal, dass sie keine separate Spezifikation erfordern und existierende Tests symbolisch ausführen können, um Behauptungsverletzungen zu identifizieren. Dies ermöglicht Benutzern, beide Tools austauschbar zu verwenden oder sie parallel für dieselben Tests auszuführen, was ihnen mehrere Optionen für symbolisches Testen bietet.

    Es ist erwähnenswert, dass HEVM und Halmos trotz ihrer Ähnlichkeiten unabhängig voneinander entwickelt wurden und sich in ihren Implementierungsdetails unterscheiden; insbesondere in Bezug auf Optimierungen und symbolische Argumentationsstrategien. Darüber hinaus ist HEVM in Haskell geschrieben, während Halmos in Python geschrieben ist, was einen Einblick in das reichhaltige Python-Ökosystem bietet. Die Möglichkeit, beide Tools zu verwenden, gibt Benutzern mehr Flexibilität und Optionen, um die Sicherheit und Korrektheit von Smart Contracts zu gewährleisten.

Halmos ist Open Source und derzeit in der Beta-Phase. Wir arbeiten aktiv an neuen Funktionen und Funktionalität, einschließlich Foundry-Cheat-Codes und mehrere andere wichtige Funktionen zur Benutzerfreundlichkeit. Wir würden uns sehr über Ihre Gedanken darüber freuen, welche Funktionen am wichtigsten sind, und freuen uns über Feedback, Vorschläge und Beiträge, um Halmos zu einem besseren Tool für alle zu machen.

**

Die hier geäußerten Ansichten sind die der einzelnen zitierten Mitarbeiter von AH Capital Management, LLC („a16z“) und nicht die Ansichten von a16z oder seinen verbundenen Unternehmen. Bestimmte hierin enthaltene Informationen stammen aus Drittquellen, einschließlich von Portfoliounternehmen von Fonds, die von a16z verwaltet werden. Obwohl sie aus als zuverlässig erachteten Quellen stammen, hat a16z solche Informationen nicht unabhängig überprüft und macht keine Zusicherungen über die aktuelle oder dauerhafte Genauigkeit der Informationen oder ihre Angemessenheit für eine bestimmte Situation. Darüber hinaus kann dieser Inhalt Werbung von Drittanbietern enthalten; a16z hat solche Anzeigen nicht überprüft und unterstützt keine darin enthaltenen Werbeinhalte.

Dieser Inhalt wird nur zu Informationszwecken bereitgestellt und sollte nicht als Rechts-, Geschäfts-, Anlage- oder Steuerberatung angesehen werden. Sie sollten diesbezüglich Ihre eigenen Berater konsultieren. Verweise auf Wertpapiere oder digitale Vermögenswerte dienen nur der Veranschaulichung und stellen keine Anlageempfehlung oder ein Angebot zur Erbringung von Anlageberatungsdiensten dar. Darüber hinaus richtet sich dieser Inhalt nicht an Anleger oder potenzielle Anleger und ist nicht für die Verwendung durch diese bestimmt, und es darf unter keinen Umständen darauf vertraut werden, wenn eine Entscheidung getroffen wird, in einen von a16z verwalteten Fonds zu investieren. (Ein Angebot zur Investition in einen a16z-Fonds wird nur durch das Privatplatzierungsmemorandum, den Zeichnungsvertrag und andere relevante Unterlagen eines solchen Fonds abgegeben und sollte vollständig gelesen werden.) Alle erwähnten, erwähnten oder erwähnten Investitionen oder Portfoliounternehmen oder Portfoliounternehmen Die beschriebenen Investitionen sind nicht repräsentativ für alle Investitionen in von a16z verwaltete Vehikel, und es kann nicht garantiert werden, dass die Investitionen rentabel sind oder dass andere Investitionen in der Zukunft ähnliche Merkmale oder Ergebnisse aufweisen werden. Eine Liste der Investitionen von Fonds, die von Andreessen Horowitz verwaltet werden (mit Ausnahme von Investitionen, für die der Emittent a16z keine Genehmigung zur öffentlichen Offenlegung erteilt hat, sowie unangekündigte Investitionen in öffentlich gehandelte digitale Vermögenswerte) ist unter https://a16z.com/investments verfügbar /.

Die darin bereitgestellten Diagramme und Grafiken dienen ausschließlich zu Informationszwecken und sollten bei Anlageentscheidungen nicht als verlässlich angesehen werden. Die Wertentwicklung in der Vergangenheit ist kein Hinweis auf zukünftige Ergebnisse. Der Inhalt spricht nur zum angegebenen Datum. Alle Prognosen, Schätzungen, Prognosen, Ziele, Aussichten und/oder Meinungen, die in diesen Materialien geäußert werden, können ohne Vorankündigung geändert werden und können von den Meinungen anderer abweichen oder ihnen widersprechen. Weitere wichtige Informationen finden Sie unter https://a16z.com/disclosures.

Zeitstempel:

Mehr von Andreessen Horowitz