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?
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.
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 data
Teils, der Eingabe to
des Vertrags C1 und der Ausführung der Ethereum Virtual Machine. Das data
sagt 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 data
ist 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).
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.
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 callTracer
den 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).
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.
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!
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
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
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
Paul S
Pablo Jabo
Paul S
Tjaden Hess
address.send()
oderaddress.call()
-Funktionen in Solidity gesendet wirdPablo Jabo