Ist msg.data
gleich {from: addr1, data:something}
?
Wie geht man mit den Daten „etwas“ um?
bei Ausführung dieses Codes:
web3.eth.sendTransaction({from: ..., to: addressOfE, data: something});
Wie liest man die "Daten: etwas"? Zum Beispiel:data: web3.toHex('something')
Danke!
Aktualisierung 4, 7 2017
Demo: Ich habe eine Ereignisfunktion in die sendCoin-Funktion eingefügt.
"event LogMsgData(bytes calldata);"
when i call this,
meta.sendCoin(receiver, amount, {from: account, data:web3.toHex('test'), gas:500000});
die LogMsgData drucken dies:
//"0x90b98a11 -> MethodID
//000000000000000000000000f178589cf1ef5af554863d8cef601c9fc02ca2ed -> receiver address
//0000000000000000000000000000000000000000000000000000000000000002" -> the amount
und wo ist {from: account,data:web3.toHex('test'),gas:500000}
?
Für diese Funktion musste ich etwas tiefer in den Inhalt von msg.data eintauchen .
Ich dachte, es wäre erwähnenswert, dass Parameter mit variabler Länge wie Arrays, Bytes und Strings eine komplexere strukturierte msg.data erzeugen.
Bei folgender Methode:
function getMsgData(
address _address,
bytes _bytes,
uint _int,
uint[] _array,
string _string
)
external
returns (bytes)
{
return msg.data;
}
Wenn wir diese Methode aufrufen, haben die folgenden Parameter:
contract.getMsgData(
someAddress,
web3.toHex('my bytes'),
12,
[1, 4, 412],
'thisislargerthanthirtytwobytesstring'
);
Die Antwort würde wie folgt aufgeteilt werden:
0x
d1621754 // (1) methodId
000000000000000000000000c6e012db5298275a4c11b3e07d2caba88473fce1 // (2) "_address"
00000000000000000000000000000000000000000000000000000000000000a0 // (3) location of start of "_bytes" data (item 7) = 160 bytes
000000000000000000000000000000000000000000000000000000000000000c // (4) "_val" = 12
00000000000000000000000000000000000000000000000000000000000000e0 // (5) location of start of "_array" data (item 9) = 224 bytes
0000000000000000000000000000000000000000000000000000000000000160 // (6) location of start of "_string" data (item 13) = 352 bytes
0000000000000000000000000000000000000000000000000000000000000008 // (7) size of "_bytes" data in bytes (32 bytes)
6d79206279746573000000000000000000000000000000000000000000000000 // (8) "_bytes" data padded to 32 bytes
0000000000000000000000000000000000000000000000000000000000000003 // (9) length of "_array" data = 3
0000000000000000000000000000000000000000000000000000000000000001 // (10) _array[0] value = 1
0000000000000000000000000000000000000000000000000000000000000004 // (11) _array[2] value = 4
000000000000000000000000000000000000000000000000000000000000019c // (12) _array[3] value = 412
0000000000000000000000000000000000000000000000000000000000000024 // (13) size of "_string" data in bytes (64 bytes)
7468697369736c61726765727468616e74686972747974776f6279746573737472696e670..0 // (14) "_string" data padded to 64 bytes
Sie können sehen, dass Strings, Bytes und Arrays alle ihre Datengröße und Daten an das Ende von msg.data angehängt haben. Anstelle der Stelle, an der normalerweise die Parameterdaten erscheinen würden, haben Sie eine 32-Byte-Ganzzahl, die den Speicherort der Parameterdaten beschreibt.
Ja, in web3.eth.sendTransaction({from: ..., to: addressOfE, data: something});
, dann in Vertrag E, msg.data
wird das etwas sein.
Meistens wird ein Vertrag jedoch msg.data
indirekt und einfach abgewickelt.
Wenn Sie beispielsweise eine Vertragsinstanz in web3.js haben
// creation of contract object
var MyContract = web3.eth.contract(abi);
// initiate contract for an address
var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');
myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000}, function(err, result){ ... });
dann in Solidity, der Vertrag bei 0x78e9 ... hätte so etwas wie
function myStateChangingMethod(string someStr, uint someNumber)
und der Vertrag muss nicht analysiert werden msg.data
- weil someStr
er den Wert haben wird someParam1
und someNumber
den Wert haben wird 23
.
Hinweis: Verwechseln Sie #1 und #2 nicht. Zum Beispiel gibt es data
beim Aufrufen in #2 kein Objekt myStateChangingMethod
: Verwenden Sie stattdessen einen dritten Parameter.
call
. Zum Beispiel sendet ein Vertrag C eine Nachricht an D mit D.call(something)
, dann msg.data
wird das etwas sein.Hier ist ein "Beweis", den Sie in Remix ausprobieren können:
contract C {
// in Remix, pass bytes as an array like: // ["0x00","0xaa", "0xff"]
function test(address addressOfD, bytes bb) {
addressOfD.call(bb);
}
}
contract D {
event LogMsgData(bytes calldata);
function() {
LogMsgData(msg.data);
}
}
msg.data
wie in Punkt 3 zu protokollieren? (Ich kann den Punkt 1 der Antwort bearbeiten, um die Fallback-Funktion zu erwähnen.)myContractInstance.myStateChangingMethod('someParam1', 23, web3.toHex('test'), {value: 200, gas: 2000}, function(err, result){ ... });
anstatt myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000, data:web3.toHex('test') }, function(err, result){ ... });
ich werde der Antwort eine Notiz hinzufügen, und diese Kommentare sollten wahrscheinlich bereinigt werden, und bei Bedarf sollte eine weitere Frage gestellt werden.
Rob Hitchens
wecken