es msg.data
igual a {from: addr1, data:something}
?
¿Cómo manejar los datos 'algo'?
al ejecutar este código:
web3.eth.sendTransaction({from: ..., to: addressOfE, data: something});
¿Cómo leer los "datos: algo"? Por ejemplo:data: web3.toHex('something')
¡gracias!
actualización 4, 7 2017
demostración: puse una función de evento en la función sendCoin.
"event LogMsgData(bytes calldata);"
when i call this,
meta.sendCoin(receiver, amount, {from: account, data:web3.toHex('test'), gas:500000});
LogMsgData imprime esto:
//"0x90b98a11 -> MethodID
//000000000000000000000000f178589cf1ef5af554863d8cef601c9fc02ca2ed -> receiver address
//0000000000000000000000000000000000000000000000000000000000000002" -> the amount
y donde esta {from: account,data:web3.toHex('test'),gas:500000}
?
Tuve que profundizar un poco más en el contenido de msg.data para esta característica .
Pensé que valdría la pena señalar que los parámetros de longitud variable, como matrices, bytes y cadenas, producen un msg.data estructurado más complejo.
Dado el siguiente método:
function getMsgData(
address _address,
bytes _bytes,
uint _int,
uint[] _array,
string _string
)
external
returns (bytes)
{
return msg.data;
}
Si llamamos a este método los siguientes parámetros:
contract.getMsgData(
someAddress,
web3.toHex('my bytes'),
12,
[1, 4, 412],
'thisislargerthanthirtytwobytesstring'
);
La respuesta se dividiría así:
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
Puede ver que las cadenas, los bytes y las matrices tienen su tamaño de datos y datos adjuntos al final de msg.data. En lugar de donde normalmente aparecerían los datos de parámetros, tiene un entero de 32 bytes que describe la ubicación de los datos de parámetros.
Sí, en web3.eth.sendTransaction({from: ..., to: addressOfE, data: something});
, luego en el contrato E, msg.data
será el algo.
Sin embargo, la mayoría de las veces un contrato se maneja msg.data
indirecta y fácilmente.
Por ejemplo, si tiene una instancia de contrato en web3.js
// 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){ ... });
luego en Solidity, el contrato en 0x78e9... tendría algo como
function myStateChangingMethod(string someStr, uint someNumber)
y el contrato no tiene que analizarse msg.data
, porque someStr
tendrá el valor someParam1
y someNumber
tendrá el valor 23
.
Nota: No mezcle #1 y #2. Por ejemplo, no hay ningún data
objeto cuando se invoca myStateChangingMethod
en el n.° 2: use un tercer parámetro en su lugar.
call
. Por ejemplo, un contrato C envía un mensaje a D usando D.call(something)
, entonces msg.data
será el algo.Aquí hay una "prueba" para probar en Remix:
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
como se hace en el punto 3? (Puedo editar el punto 1 de la respuesta para mencionar la función de respaldo).myContractInstance.myStateChangingMethod('someParam1', 23, web3.toHex('test'), {value: 200, gas: 2000}, function(err, result){ ... });
en lugar de myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000, data:web3.toHex('test') }, function(err, result){ ... });
agregar una nota a la respuesta, y estos comentarios probablemente deberían limpiarse y se debe hacer otra pregunta si es necesario.
Rob Hitchens
despertador