Ich habe einen ABI und den input
Wert der Transaktion und möchte wissen, welche Funktion für einen Vertrag aufgerufen wurde und mit welchen Argumenten (einem oder mehreren unterschiedlichen Typen), vorzugsweise mit geth
und JSON-RPC
etwas Pseudocode, den ich dann in Ruby übersetzen kann.
Es gibt ein paar ähnliche Fragen zu SO, aber keine davon hat die Frage wirklich auf eine Weise beantwortet, die für jemanden verständlich ist, der neu bei Ethereum ist.
Als Beispiel verwende ich den MetaCoin
von Truffle generierten Vertrag . Ich rufe die Methode getBalance('0xfd46f749f9d916122fe958d7f8d5ad033b187472')
auf und erhalte die Eingabe 0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472
.
truffle(development)> web3.eth.getTransaction('0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff') {Hash: '0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff', einmal: 5, blockHash: '0xd150b520eb69a621a7218722c0de5b270c9abc499a90a81ca96340e274599c28', Blocknummer: 6, Transaktionsindex: 0, aus: '0xfd46f749f9d916122fe958d7f8d5ad033b187472', zu: '0x8dec2f9cccbe718c7c51e9154f223eb226bb7942', Wert: { [String: '0'] s: 1, e: 0, c: [ 0 ] }, Benzin: 4712388, gasPrice: { [String: '100000000000'] s: 1, e: 11, c: [ 100000000000 ] }, Eingabe: '0xf8b2cb4f00000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472' }
Der ABI lautet wie folgt:
[ { "Konstante": falsch, "Eingänge": [ { "name": "adr", "Typ": "Adresse" } ], "name": "getBalanceInEth", "Ausgänge": [ { "Name": "", "Typ": "uint256" } ], "zahlbar": falsch, "Typ": "Funktion" }, { "Konstante": falsch, "Eingänge": [ { "Name": "Empfänger", "Typ": "Adresse" }, { "Name": "Betrag", "Typ": "uint256" } ], "name": "sendCoin", "Ausgänge": [ { "name": "ausreichend", "typ": "boolesch" } ], "zahlbar": falsch, "Typ": "Funktion" }, { "Konstante": falsch, "Eingänge": [ { "name": "adr", "Typ": "Adresse" } ], "name": "getBalance", "Ausgänge": [ { "Name": "", "Typ": "uint256" } ], "zahlbar": falsch, "Typ": "Funktion" }, { "Eingaben": [], "zahlbar": falsch, "Typ": "Konstruktor" }, { "anonym": falsch, "Eingänge": [ { "indiziert": wahr, "name": "_von", "Typ": "Adresse" }, { "indiziert": wahr, "name": "_to", "Typ": "Adresse" }, { "indiziert": falsch, "name": "_wert", "Typ": "uint256" } ], "name": "Überweisung", "Typ": "Ereignis" } ]
Wie kann ich jede Eingabe dekodieren, um zu wissen, welche Methode aufgerufen wurde und welche Argumente übergeben wurden?
Aktualisieren
Ich habe alle Daten des Blocks mit dem Eingabefeld ganz unten in den Logs hinzugefügt.
{"number"=>"0x09",
"hash"=>"0xf543eba0c80d49beea1f934c0f0ad9f0babe272a8318312545d43e6b612e4006",
"parentHash"=>
"0xde7a61e8dd84b5e080da8e16430951f7f138347c77ed263d0093e367c9d30775",
"nonce"=>"0x0",
"sha3Uncles"=>
"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom"=>
"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"transactionsRoot"=>
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot"=>
"0x269cfa04ca1fe73202f788397ece62c520c64d5da7225ba2af2d673a2e9892f2",
"receiptRoot"=>
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"miner"=>"0x0000000000000000000000000000000000000000",
"difficulty"=>"0x0",
"totalDifficulty"=>"0x0",
"extraData"=>"0x0",
"size"=>"0x03e8",
"gasLimit"=>"0x47e7c4",
"gasUsed"=>"0x5a3e",
"timestamp"=>"0x58c83fda",
"transactions"=>
[{"hash"=>
"0xce1eaf03dd1dfa5898243711ebcc1dc5c6357701f5a6c19f0b1f84130cb651fa",
"nonce"=>"0x08",
"blockHash"=>
"0xf543eba0c80d49beea1f934c0f0ad9f0babe272a8318312545d43e6b612e4006",
"blockNumber"=>"0x09",
"transactionIndex"=>"0x0",
"from"=>"0xfd46f749f9d916122fe958d7f8d5ad033b187472",
"to"=>"0x8dec2f9cccbe718c7c51e9154f223eb226bb7942",
"value"=>"0x0",
"gas"=>"0x47e7c4",
"gasPrice"=>"0x174876e800",
"input"=>
"0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472"}],
"uncles"=>[]}
Sie können auf ein von Consensys entwickeltes Paket verweisen https://github.com/ConsenSys/abi-decoder
getBalance
), den Namen jedes in ( receiver
) übergebenen Arguments und den in ( ) übergebenen Wert 0xfd46f749f9d916122fe958d7f8d5ad033b187472
für jedes Argument zurück. Es gibt jedoch nicht den Typ des Arguments zurück?Ah ok, ich verstehe was du fragst. Sie können dies tun web3.toAscii(transactionID.input)
, um ein für Menschen lesbares Format zu erhalten.
Siehe web3.toAscii
https://github.com/ethereum/wiki/wiki/JavaScript-API#web3toascii
Also mit deinem Code wäre es:
transaction = web3.eth.getTransaction('0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff')
input = web3.toAscii(transaction.input)
console.log(input)
'ø²ËO\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000ýF÷IùÙ\u0016\u0012/éX×øÕ\u0003;\u0018tr'
. Ich kenne mich mit Ascii nicht aus und weiß nicht, wie ich aus diesem String ableiten könnte, dass die Methode getBalance(address)
mit dem Argument aufgerufen wurde 0xfd46f749f9d916122fe958d7f8d5ad033b187472
.Sie können die web3.eth.abi.decodeLog
Funktion jetzt verwenden (web3 1.0).
Beispiel aus der Dokumentation:
web3.eth.abi.decodeLog([{
type: 'string',
name: 'myString'
},{
type: 'uint256',
name: 'myNumber',
indexed: true
},{
type: 'uint8',
name: 'mySmallNumber',
indexed: true
}],
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000748656c6c6f252100000000000000000000000000000000000000000000000000',
['0x000000000000000000000000000000000000000000000000000000000000f310', '0x0000000000000000000000000000000000000000000000000000000000000010']);
> Result {
'0': 'Hello%!',
'1': '62224',
'2': '16',
myString: 'Hello%!',
myNumber: '62224',
mySmallNumber: '16'
}
Sie können das Tool ethereum-input-data-decoder zum Decodieren von Transaktionseingabedaten verwenden, wenn Sie die ABI haben.
Beispiel:
const InputDataDecoder = require('ethereum-input-data-decoder');
const decoder = new InputDataDecoder(`${__dirname}/abi.json`);
const data = `0x67043cae0000000000000000000000005a9dac9315fdd1c3d13ef8af7fdfeb522db08f020000000000000000000000000000000000000000000000000000000058a20230000000000000000000000000000000000000000000000000000000000040293400000000000000000000000000000000000000000000000000000000000000a0f3df64775a2dfb6bc9e09dced96d0816ff5055bf95da13ce5b6c3f53b97071c800000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000`;
const result = decoder.decodeData(data);
console.log(result);
{
"name": "registerOffChainDonation",
"types": [
"address",
"uint256",
"uint256",
"string",
"bytes32"
],
"inputs": [
<BN: 5a9dac9315fdd1c3d13ef8af7fdfeb522db08f02>,
<BN: 58a20230>,
<BN: 402934>,
"BTC",
<Buffer f3 df ... 71 c8>
]
}
Auf dem neuen web3.js 1.0 müssen Sie Folgendes verwenden: web3.utils.toAscii(transaction.input)
.
Manchmal sollten Sie eine tun let input = transaction.input.replace(/^0x/, ``);
, um diese nutzlosen Zeichen vom Anfang der Zeichenfolge zu entfernen.
Siehe Dokumente .
Samuel Hawksby-Robinson
migu