¿Cómo hacer una función de firma? ERC223 ContratoReceptor

Hola, ¿qué significan estas líneas?

function tokenFallback(address _from, uint _value, bytes _data) {
    ...
    uint32 u = uint32(_data[3]) + (uint32(_data[2]) << 8) + (uint32(_data[1]) << 16) + (uint32(_data[0]) << 24);
    tkn.sig = bytes4(u);
}

Sé que tkn.sig es la firma de función de 4 bytes. Pero, ¿podría alguien explicar cómo funcionan esas dos líneas?

Respuestas (2)

tokenFallbackrecibe un tercer parámetro, _dataque puede ser cualquier dato arbitrario. La forma en que se interpreta en el contrato es muy específica del contrato. El código que pegó parece estar convirtiendo los primeros cuatro bytes _dataen un bytes4para almacenar en tkn.sig. No puedo especular por qué sin ver el resto del código. (Por ejemplo, sería interesante ver cómo tknse está utilizando).

EDITAR

Parece que el código proviene de https://github.com/Dexaran/ERC223-token-standard/blob/Recommended/Receiver_Interface.sol#L17 . El resto de la función, incluido el comentario, es esclarecedor:

function tokenFallback(address _from, uint _value, bytes _data){
    TKN memory tkn;
    tkn.sender = _from;
    tkn.value = _value;
    tkn.data = _data;
    uint32 u = uint32(_data[3]) + (uint32(_data[2]) << 8) + (uint32(_data[1]) << 16) + (uint32(_data[0]) << 24);
    tkn.sig = bytes4(u);

    /* tkn variable is analogue of msg variable of Ether transaction
    *  tkn.sender is person who initiated this token transaction   (analogue of msg.sender)
    *  tkn.value the number of tokens that were sent   (analogue of msg.value)
    *  tkn.data is data of token transaction   (analogue of msg.data)
    *  tkn.sig is 4 bytes signature of function
    *  if data of token transaction is a function execution
    */
}

Supongo que _dataaquí se está tratando como en un escenario sin token, donde los primeros cuatro bytes son un selector de función (los primeros cuatro bytes del hash keccak256 de la firma de la función). Presumiblemente, esto es para que el receptor del token pueda invocar una función para manejar los tokens entrantes, al igual que una payablefunción maneja las transacciones entrantes.

http://solidity.readthedocs.io/en/develop/types.html#fixed-size-byte-arrays
Matrices de bytes de tamaño fijo
bytes1, bytes2, bytes3, …, bytes32. byte es un alias para bytes1.
----------------==
http://solidity.readthedocs.io/en/develop/types.html#dynamically-sized-byte-array
Bytes de matriz de bytes de tamaño dinámico: Matriz de bytes de tamaño dinámico, consulte Matrices. ¡No es un tipo de valor!
----------------==
http://solidity.readthedocs.io/en/develop/types.html#arrays
Las variables de tipo bytes y string son matrices especiales. Un byte es similar a byte[], pero está empaquetado de forma compacta en calldata. cadena es igual a bytes pero no permite acceso de longitud o índice (por ahora). Por lo tanto, los bytes siempre deben preferirse a los bytes [] porque es más barato.
----------------==
Entonces, el argumento bytes _data significa: _data es una matriz de bytes de tamaño dinámico, y cada elemento es del tipo byte1
_data[3], _data[2], _data[1], _data[0] son ​​los primeros 4 elementos de _data
uint32 (_data[3]) es convertir _data[3] en un número de uint32
----------------==
http://solidity.readthedocs.io/en/develop/ tipos.html#integers
** (exponenciación), << (desplazamiento a la izquierda), >> (desplazamiento a la derecha)
La expresión x << y es equivalente a x * 2**y, y x >> y es equivalente a x / 2**y
----------------==
Entonces uint32(_data[2]) << 8 es equivalente a uint32(_data[2]) * 2**8
lo mismo para _data[1] y _data[0]
luego agréguelos todos juntos para hacer uint32 u
luego convierta u en bytes4 por bytes4(u)
Wow, eso es complicado... Espero no haber cometido ningún error :)

Todo parece correcto.