Wie kann ich überprüfen, ob ein Vertrag auf der Blockchain mit dem Quellcode übereinstimmt?

Gibt es angesichts des (Solidity-)Quellcodes eines Smart Contracts eine Möglichkeit, den Code deterministisch zu kompilieren und mit dem Code auf der Blockchain zu vergleichen? Ich möchte überprüfen, ob der Vertrag das tut, was der Quellcode behauptet, und der Autor ihn nicht manipuliert hat.

Eine verwandte Frage bei der IT Security SE.

Antworten (7)

AFAIK, der beste Weg, dies im Moment zu tun, besteht darin, den Quellcode erneut mit genau derselben Compiler-Version zu kompilieren, die der Autor verwendet hat (also muss dies offengelegt werden) und den Bytecode vergleichen.

Die Übereinstimmung, die Sie überprüfen sollten, ist also der kompilierte Bytecode mit den Daten der Vertragserstellungs-TX .

Nicht 100%, immer noch problematisch github.com/trufflesuite/truffle-compile/issues/77
Ich danke dir sehr! Der Vertrag wurde auf v5.17.0 erstellt, aber ich habe v5.0.0 gewählt, um den Vertragscode zu überprüfen, sodass Fehler ausgegeben wurden. Schließlich ändere ich die Version so, dass sie mit dem gebauten Compiler v5.17.0 identisch ist.

Um die Antwort von @thomas-bertani zu ergänzen, hat etherchain.org heute ein Überprüfungstool für Ethereum-Verträge veröffentlicht

Hier der Text von der Seite:

Die Verifizierung des Quellcodes bietet Transparenz für Benutzer, die mit Smart Contracts interagieren. Durch das Hochladen des Quellcodes gleicht Etherscan den kompilierten Code mit dem auf der Blockchain ab. Genau wie Verträge sollte ein „intelligenter Vertrag“ den Endbenutzern mehr Informationen darüber geben, wofür sie „digital signieren“, und den Benutzern die Möglichkeit geben, den Code zu prüfen, um unabhängig zu überprüfen, ob er tatsächlich das tut, was er tun soll.

Der Link funktioniert nicht. Hat es sich geändert?
Link funktioniert nicht, ist down.
Die neue URL lautet etherscan.io/verifyContract
Ich habe die Antwort bearbeitet, um den Link und den Text zu aktualisieren.

Aktuell ist der Workflow ziemlich nervig. Sie müssen den Vertrag mit der gleichen Compiler-Version und der gleichen Einstellung kompilieren (achten Sie auf das Flag „optimization=true“ ).

Beachten Sie nun, dass der resultierende Bytecode NICHT mit dem Bytecode übereinstimmt, der auf der Adresse gespeichert ist. Der Grund dafür ist, dass der kompilierte Vertrag einen Initialisierungsteil enthält, der nur einmal ausgeführt wird, wenn der Vertrag an die Kette gesendet wird. Der in der Blockchain gespeicherte Bytecode ist also der Code ohne den Initialisierungsteil.

Um den Code zu verifizieren, haben Sie zwei Möglichkeiten:

  1. Senden Sie den kompilierten Code an eine (virtuelle) Blockchain und überprüfen Sie dann mit dem getCode- Befehl den resultierenden Code.
  2. Vergleichen Sie den kompilierten Code mit der Nutzlast der Transaktion, die den Vertrag erstellt hat.

Etherchain hilft bei diesem Prozess.

Prinzipiell könnten Mustervergleichstechniken angewendet werden, um einen Kontakt zu identifizieren, selbst wenn nicht genau derselbe Compiler verwendet wird. Ein Projekt, das dies tut und im Allgemeinen hochrangige Verträge (Serpent/Solidity) mit Ethereum-Adressen verknüpft, ist: Etherscrape

https://etherscan.io/verifyContract ist ein Verifizierungstool. Durch die Bereitstellung des Solidity-Quellcodes wird überprüft, ob der generierte Bytecode mit dem Vertrags-Bytecode (unter der angegebenen Adresse) übereinstimmt. Benutzer sollten denselben Compiler wählen und die Optimierung aktivieren oder deaktivieren.

Ein anderer Ansatz wäre, den Bytecode zu dekompilieren und mit der Quelle zu vergleichen.

Es gibt ein Tool namens Porosity , das genau das tut.

Ich bin ziemlich zuversichtlich, dass dies nicht effizient funktionieren kann, insbesondere bei größeren Verträgen. Die Namen der Variablen werden nicht im Bytecode gespeichert, daher muss der Decompiler seine eigenen Namen erstellen. Zu versuchen, zu sehen, ob der dekompilierte Code derselbe ist wie die dargestellte Quelle, wäre sehr schwierig, würde ich denken.
Die Vertrags-ABI enthält alle Variablennamen.
Nicht immer. Ich habe viele gesehen, die das nicht tun.
Notiert. Dies würde eine Dekompilierung für komplexe Verträge in der Tat unpraktisch machen.
Ich wusste nicht, dass der Decompiler die ABI verwendet. Das macht es natürlich viel einfacher.

Empfehlen Sie die Verwendung des gerade veröffentlichten Open-Source- Befehlszeilentools bytecode - verifier von ConsenSys bzw. des jeweiligen npm-Pakets

Bytecode Verifier ist ein praktisches Befehlszeilentool zum Überprüfen des lokal kompilierten Bytecodes eines Ziel-Solidity-Vertrags mit seinem tatsächlichen Bytecode, der in Etheruem Blockchain gespeichert ist, vorausgesetzt, seine Vertragsadresse.

  • Integrität/Korrektheit des Bytecodes : Was tatsächlich in der Kette gespeichert wird, wird korrekt aus einem bestimmten Vertrag zusammengestellt, was im Falle einer nicht trivialen potenziellen Bereitstellung von Verträgen mit hohem Wert (z. B. MultiSig Wallet) hilfreich sein kann, insbesondere wenn der Vertrag über einen Dritten bereitgestellt wird Partei Plattform.

  • Minimaler Aufwand, einfach zu bedienen : Der Solidity-Compiler erfordert Überstunden mit kleineren und einigen größeren Änderungen, was die Überprüfung des Bytecodes erschwert. (da wiederkehrende "Bytecode stimmt nicht überein"-Fragen, die auf Ethereum Stack Exchange gestellt werden). Bytecode Verifier wurde mit der neuesten Version bis zurück zu einigen der ältesten eingesetzten Verträge getestet.

  • Testnet-freundlich : Die meisten Projekte starten im Testnet, bevor das Vertragssystem im Mainnet bereitgestellt wird. Dieses Tool unterstützt Rinkeby, Kovan und Ropsten Testnet, die drei aktive, gut gepflegte Testnets darstellen, die die meisten Ethereum-Entwickler verwenden.

Ich hoffe es hilft!

So mache ich es in einem web3-Skript.

Kompilieren Sie zuerst den Code.

const solc = require('solc');

//contract sources
const contractPath = "../contracts/";

const input = {
  "ContractName.sol" : fs.readFileSync(contractPath + 'contractName.sol', 'utf8'),
}

let solcOutput = await solc.compile({ sources: input }, 1);

Vergleichen Sie jetzt byteCode

let blockCode = await web3.eth.getCode(contractAddress);
let solcCode = '0x' + (solcOutput.contracts["contractName.sol:contracName"].runtimeBytecode);}
Dies funktioniert nicht, Ihnen fehlen Konstruktorparameter und Hilfsdaten
Wie hast du es getestet? es funktioniert für mich bei allen kyber-netzwerkverträgen.
@mdv Benötigen Sie übereinstimmende Konstruktorparameter? Ich sehe widersprüchliche Antworten, aber ich vermute nein, da der Konstruktor dafür ausgelegt ist, Werte zu speichern und nicht das Vorhandensein von Funktionen oder Zustandsvariablen zu bestimmen.