So erhalten Sie vertragsinterne Transaktionen

Ich möchte die vertragsinternen Transaktionen wie folgt abrufen: https://etherscan.io/address/0xd654bdd32fc99471455e86c2e7f7d7b6437e9179#internaltx

Ich verwende die web3-API. Gibt es eine Möglichkeit, dies zu tun? Wo erscheinen sie in der Blockchain?

hoffentlich erklärt die Antwort, was eine interne Transaktion ist
Sie sind die Transaktionen, die durch die Verträge ausgelöst werden.
sicher, aber immer noch nicht sicher, was es bedeutet. Ich erinnere mich nicht an ein Solidity-Schlüsselwort dafür. Verknüpfung?
@PaulS Es ist jede Transaktion, die über die address.send()oder address.call()-Funktionen in Solidity gesendet wird
Nein, es gibt andere Möglichkeiten, Ether zu „senden“, wie Selbstmord () oder wenn Sie einen neuen Vertrag erstellen

Antworten (13)

Derzeit gibt es keine Möglichkeit, dies mit der web3-API zu tun. Interne Transaktionen sind trotz des Namens (der nicht Teil des Yellowpapers ist; es ist eine Konvention, auf die sich die Leute geeinigt haben) keine tatsächlichen Transaktionen und werden nicht direkt in die Blockchain aufgenommen; sie sind Wertübertragungen, die durch die Ausführung eines Vertrages initiiert wurden.

Als solche werden sie nirgendwo explizit gespeichert: Sie sind die Auswirkungen der Ausführung der betreffenden Transaktion auf den Blockchain-Status. Blockchain-Explorer wie Etherscan erhalten sie, indem sie einen modifizierten Knoten mit einer instrumentierten EVM ausführen, die alle Wertübertragungen aufzeichnet, die im Rahmen der Transaktionsausführung stattgefunden haben, und sie separat speichert.

Ich habs! Wissen Sie, ob es einen Plan gibt, eine Art Mechanismus hinzuzufügen, um diese Transaktionen zu erhalten, oder ob ich eine instrumentierte EVM erstellen muss.
Mir ist keine laufende Arbeit zum Hinzufügen einer solchen API bekannt, obwohl es eine geben könnte; Wenn es Ihr Ziel ist, interne Überweisungen für eine bestimmte Transaktion zu erhalten, wäre dies praktisch. Wenn Ihr Ziel jedoch darin besteht, alle Überweisungen auf ein Konto zu bekommen, reicht dies nicht aus - und dafür gibt es einen Fehler .
Ich habe bereits die tx-Liste für Transaktionen ohne Vertrag, aber ich möchte die „internen Transaktionen“ zur Transaktionsliste hinzufügen. Glauben Sie, dass ein instrumentiertes EVM dafür funktionieren könnte?
@PabloYabo Das würde es, aber wenn Sie sich für "alle Transaktionen auf dieses Konto" interessieren, müssen Sie jede einzelne Transaktion ausführen, falls sie zu einer Überweisung auf das Konto führt, das Ihnen wichtig ist. Wenn Sie sich für „alle von dieser Transaktion initiierten Wertübertragungen“ interessieren, können Sie es nur für diese Transaktion ausführen.
Die Idee ist, eine Datenbank mit allen Transaktionen aller Konten zu haben, sodass die Ausführung aller Transaktionen in diesem Schema möglich ist. Wir bekommen jetzt alle Blöcke, Transaktionen und Quittungen.
@PabloYabo In diesem Fall würde eine solche hypothetische API wahrscheinlich Ihren Zwecken dienen - aber in der Zwischenzeit müssen Sie das EVM selbst instrumentieren.
@PabloYabo, bitte erklären Sie, wie Sie es geschafft haben, die TX-Liste für Transaktionen ohne Vertrag zu haben ?

Im Ethereum-Protokoll gibt es nur Transaktionen und Nachrichtenaufrufe. Eine Transaktion ist eine Art Nachrichtenaufruf.

Eine Transaktion kann andere Nachrichtenaufrufe ausführen, aber dies sind keine Transaktionen (auch wenn Blockchain-Explorer sie möglicherweise fälschlicherweise als „interne Transaktionen“ bezeichnen). Diese (internen) Nachrichtenaufrufe werden nicht auf der Blockchain veröffentlicht. Um die internen Aufrufe zu finden , muss die Transaktion über die EVM verarbeitet werden (z. B. https://github.com/ethereumjs/ethereumjs-vm ).

Zur Veranschaulichung sieht eine Transaktion in Javascript so aus:

{
  from: ...,
  to: "C1",
  value: ...,
  gas: ...,
  data: ...,
  gasPrice: ...,
  nonce: ...
}

Dies ist, was Sie auf der Blockchain sehen werden. Interne Anrufe sind die Auswirkungen der Übernahme des dataTeils, der Eingabe todes Vertrags C1 und der Ausführung der Ethereum Virtual Machine. Das datasagt C1, dass es einen anderen Vertrag C2 aufrufen soll: Es gibt kein separates {from:C1, to:C2,...}Objekt in der Blockchain, das benötigt wird.

Die dataist gemäß einer ABI kodiert, die beispielsweise sagt, welche Funktion aufgerufen werden soll und was die Argumente sind.

Hinweis: Bei der Antwort von @Nick sind alle Wertübertragungen ein Nachrichtenaufruf. Aber nicht alle Nachrichtenaufrufe sind Wertübertragungen. Eine Wertübertragung liegt vor, wenn ein Vertrag einfach mit etwas Ether/Wei bezahlt wird (Daten sind Null), aber Verträge können sich gegenseitig anrufen, ohne sich gegenseitig zu bezahlen (Daten sind ungleich Null, Wert ist Null).

Ist es möglich, all diese Protokolle zu erhalten?
Ja, die Ausführung der EVM umfasst alle LOG-Opcodes.

Glücklicherweise verfügt Geth EVM über neue Tools, um dies zu erreichen. Es ist möglich, debug_traceTransaction mit der RPC-API zu verwenden.

In NodeJS:

var web3 = require('web3').web3;
web3.currentProvider.sendAsync({
    method: "debug_traceTransaction",
    params: ['0x3fac854179691e377fc1aa180b71a4033b6bb3bde2a7ef00bc8e78f849ad356e', {}],
    jsonrpc: "2.0",
    id: "2"
}, function (err, result) {
    ...
});

Dann müssen Sie die Opcodes 'CREATE', 'CALL', 'CALLCODE' und 'DELEGATECALL' ausführen und den Stapel verfolgen. Sie können die ausführliche Erklärung von Nick Johnson lesen : Instrumenting EVM

Wenn ich es endlich implementiere, werde ich einen vollständigen Artikel mit dem Code schreiben.

Das Problem hierbei ist, dass jeder Vertrag jederzeit den Vertrag aufrufen kann, an dem Sie interessiert sind. Wenn Sie möchten, dass jede interne Transaktion an Ihren Vertrag gesendet wird, besteht die einzige Möglichkeit darin, die Spuren jeder Transaktion zu durchsuchen, die seitdem stattgefunden hat Ihr Vertrag wurde bereitgestellt. Eine Halbverknüpfung besteht darin, Ereignisse zu filtern, aber dies ignoriert „interne Transaktionen“, die keine Ereignisse generieren. Ich habe vor ein paar Tagen hier Code in C++ gepostet: github.com/Great-Hill-Corporation/ethrpc
Ja, ich weiß, es war nur ein Beispiel. Dann müssen Sie dasselbe für jede Transaktion tun. Meine Idee ist, alles zu indizieren und die Informationen dann in eine Datenbank zu stellen.
Ich arbeite an genau derselben Idee. Indexieren Sie alles und legen Sie es in einer Datenbank ab. Das Problem, das ich dabei sehe, ist, dass dies diese Daten zentralisiert. Wenn ich diese Daten erstelle, woher weißt du, dass ich sie nicht gefälscht habe? Ich habe versucht, einen Weg zu finden, es zu indizieren und die "Indexierungsberechnung" zu dezentralisieren. Ich weiß, wie man den Speicher (IPFS) dezentralisiert, aber nicht, wie man die Indizierungsberechnung dezentralisiert. Hast du irgendwelche Gedanken dazu? Hast du ein Github, das ich mir ansehen kann? Ein sehr grober Start von mir ist bei github.com/Great-Hill-Corporation/ethrpc . Vielleicht erlaubt Golem, die Berechnung zu dezentralisieren.
Warum es web3.web3 gibt, anstatt nur web3 zu verwenden. ?

Mit neueren Versionen von Parity (getestet auf 1.8.3) ist dies ebenfalls möglich. Die RPC-Methode ist trace_replayTransaction. Der entsprechende Code ist so etwas wie

web3.currentProvider.sendAsync({
    method: "trace_replayTransaction",
    params: [desiredTransactionHash, ['trace']],
    jsonrpc: "2.0",
    id: "1"
}, function (err, out) {
    console.log(out);
}

Die Dokumentation befindet sich im Paritäts-Github-Repository.

Sie können callTracerden in geth 1.8 eingeführten https://github.com/ethereum/go-ethereum/pull/15516 verwenden

$ nc -U /work/temp/rinkeby/geth.ipc
{"id": 1, "method": "debug_subscribe", "params": ["traceChain", "0x0", "0xffff", {"tracer": "callTracer"}]}

Die API streamt eine IPC-Benachrichtigung pro nicht leerem Block zurück. Eine Ausnahme ist der allerletzte Block, der gemeldet wird, auch wenn er leer ist, damit der Benutzer weiß, dass der Stream fertig ist.

{"jsonrpc":"2.0","id":1,"result":"0xe1deecc4b399e5fd2b2a8abbbc4624e2"}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0x37","hash":"0xdb16f0d4465f2fd79f10ba539b169404a3e026db1be082e7fd6071b4c5f37db7","traces":[{"from":"0x31b98d14007bdee637298086988a0bbd31184523","gas":"0x0","gasUsed":"0x0","input":"0x","output":"0x","time":"1.077µs","to":"0x2ed530faddb7349c1efdbf4410db2de835a004e4","type":"CALL","value":"0xde0b6b3a7640000"}]}}}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0xf43","hash":"0xacb74aa08838896ad60319bce6e07c92edb2f5253080eb3883549ed8f57ea679","traces":[{"from":"0x31b98d14007bdee637298086988a0bbd31184523","gas":"0x0","gasUsed":"0x0","input":"0x","output":"0x","time":"1.568µs","to":"0xbedcf417ff2752d996d2ade98b97a6f0bef4beb9","type":"CALL","value":"0xde0b6b3a7640000"}]}}}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0xf47","hash":"0xea841221179e37ca9cc23424b64201d8805df327c3296a513e9f1fe6faa5ffb3","traces":[{"from":"0xbedcf417ff2752d996d2ade98b97a6f0bef4beb9","gas":"0x4687a0","gasUsed":"0x12e0d","input":"0x6060604052341561000c57fe5b5b6101828061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063230925601461003b575bfe5b341561004357fe5b61008360048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506100c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600185858585604051806000526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000866161da5a03f1151561014257fe5b50506020604051035190505b9493505050505600a165627a7a7230582054abc8e7b2d8ea0972823aa9f0df23ecb80ca0b58be9f31b7348d411aaf585be0029","output":"0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063230925601461003b575bfe5b341561004357fe5b61008360048080356000191690602001909190803560ff1690602001909190803560001916906020019091908035600019169060200190919050506100c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600185858585604051806000526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000866161da5a03f1151561014257fe5b50506020604051035190505b9493505050505600a165627a7a7230582054abc8e7b2d8ea0972823aa9f0df23ecb80ca0b58be9f31b7348d411aaf585be0029","time":"658.529µs","to":"0x5481c0fe170641bd2e0ff7f04161871829c1902d","type":"CREATE","value":"0x0"}]}}}
{"jsonrpc":"2.0","method":"debug_subscription","params":{"subscription":"0xe1deecc4b399e5fd2b2a8abbbc4624e2","result":{"block":"0xfff","hash":"0x254ccbc40eeeb183d8da11cf4908529f45d813ef8eefd0fbf8a024317561ac6b"}}}

Die individuelle Blockablaufverfolgung erfolgt gleichzeitig in den Transaktionen (begrenzt auf Anzahl Kerne) und macht auch die Kettenablaufverfolgung gleichzeitig in den Blöcken (begrenzt auf Anzahl Kerne).

Wie identifiziert man also den Werttransfer für einen ERC-20 in diesem Stream?

Um Informationen über interne Transaktionen zu erhalten, können Sie die Methode debug_traceTransaction verwenden. Die Methode gibt eine vollständige Ablaufverfolgung der Transaktion zurück. Durch die Opcodes und Parameter jedes Schritts können Sie die Informationen erhalten, die Sie benötigen.

Es gibt 2 Hauptprobleme: 1. Identifizieren Sie das Arbeitsprinzip der Opcodes, da beispielsweise CALL nicht immer zu einer internen Transaktion führt. 2. Bei einer großen Anzahl von Schritten im Trace passt die Antwort möglicherweise nicht in den Puffer

Das zweite Problem kann gelöst werden, indem der zweite Parameter an die Methoden zur Verarbeitung der Schritte auf der Geth-Seite übergeben wird. Weitere Details finden Sie hier - https://github.com/ethereum/go-ethereum/wiki/Management-APIs#debug_tracetransaction

Die Logik zum Umgang mit Opcodes finden Sie hier https://github.com/Arachnid/etherquery/blob/master/etherquery/trace.go#L102 (für die Go-Implementierung) oder hier https://github.com/tet32 /etherscanner/blob/master/traceStepFunction.js (für die nodejs-Implementierung)

Laut Versionsankündigung 1.1 von Parity könnte man es damit machen, wenn man auf diesen Client umsteigt. Zitat:

Neue JSONRPC-APIs zum Verfolgen, Verfolgen und Überprüfen aller Nachrichtenaufrufe und Kontostandsübertragungen, einschließlich derjenigen, die als „interne Transaktionen“ erfolgen;

Habe es aber noch nicht getestet.

Das sieht interessant aus, konnte aber kein gut dokumentiertes Beispiel finden, obwohl die Paritäts-FAQ eine Wiki-Seite dafür erwähnt. Gepostet auf github als Parity issue #1969
@Paul: Das gibt jetzt einen 404 aus, wurde es woanders hin migriert?

Derzeit gibt es keine Möglichkeit, dies mit der Web3-API zu tun. Ihre beiden Optionen sind (a) das Ausführen eines Parity-Knotens (kann teuer sein und bis zu Wochen dauern, um es zu synchronisieren) oder (b) die Verwendung von Adressaktivitäts-Tracking (z. B. interne Transaktionen) von Alchemy Notify.

Ich kann die Verwendung von Alchemy Notify sehr empfehlen, es war kostenlos und ich war in weniger als 5 Minuten einsatzbereit. Hier ist ein Link zu ihren Dokumenten: https://docs.alchemyapi.io/alchemy/guides/using-webhooks#address-activity

Viel Glück!

Die Benachrichtigungs-Webhooks sind großartig 💙
+1 für diese Benachrichtigungs-Webhooks

Während interne Transaktionen echte Auswirkungen auf Kontostände haben, werden die internen Transaktionen selbst überraschenderweise nicht in der Kette gespeichert. Um interne Transaktionen anzuzeigen, müssen Sie die Transaktion ausführen und die von ihr getätigten Aufrufe nachverfolgen. Während einige Verträge Ereignisse in der Kette protokollieren, die interne Aktivitäten aufzeichnen, tun dies viele nicht, weil dies zusätzliches Gas erfordert.

^ aus dem Blocknative.com-Blog — https://blog.blocknative.com/blog/eth-internal-transactions

Ihr Notify-System unterstützt jetzt interne Transaktionen. Sie können über ihre API ein Update erhalten, wenn Ihre Brieftasche oder Ihr Vertrag an einer internen Transaktion beteiligt ist

Ab dem 20.05.2021 ist es nicht auf BSC verfügbar, sondern nur im Ethereum Mainnet.

Mit der API von Etherscan können Sie die Arbeit erledigen.

Weitere Informationen zum Konzept finden Sie in dieser ausführlichen Antwort .

Eine einfache Möglichkeit, dies zu tun, besteht darin, den Block herauszufinden, in dem die Transaktion stattgefunden hat. Zu wissen, dass Sie einen Web3-Aufruf an einen vollständig archivierten Knoten tätigen. web3.eth.getBalance(address, block)als 1 Block subtrahieren und es erneut tun. Subtrahieren Sie die Differenz und Sie erhalten Ihren Wert.

Ich denke, Sie schauen sich nur die Transaktionsprotokolle an. Wenn es eine "interne Transaktion" gibt, sollte diese Transaktion eines der Protokolle im Transaktionsempfangsobjekt sein. Aber ich könnte mich auch irren. @vitalikbuterin

Das stimmt nicht, ein Log wird nur erstellt, wenn ein Vertrag ein Event ausgibt. Wenn ein Vertrag kein Ereignis ausgibt, gibt es keinen Protokolleintrag.

Wenn Sie den Block der Transaktion kennen, können Sie den übertragenen Wert kennen:

                let tx;
                const txs = await web3.eth.getPastLogs({
                    fromBlock: block,
                    toBlock: block,
                    address: contractAddress
                });

                if(txs){
                    for(let i=0;i<txs.length;i++){
                        const tx_ = await web3.eth.getTransaction(txs[i].transactionHash);
                        if(tx_ && tx_.from === from){
                            tx = tx_;
                            break;
                        }
                    }
                }

Um den Wert zu erhalten, rufen Sie auf:tx.value