¿Hay una manera fácil de convertir uint
a bytes
en Solidity?
Parece que ahora lo hay, desde la versión de solidity 0.4.24 puedes usar abi.encodePacked
P.EJ:
uint i = 0;
i_bytes = abi.encodePacked(i);
La alternativa a la respuesta de @eth es usar ensamblado:
function toBytes(uint256 x) returns (bytes b) {
b = new bytes(32);
assembly { mstore(add(b, 32), x) }
}
Esto es significativamente más eficiente en el consumo de gas, pero depende del diseño de la memoria interna que utilice el compilador de Solidity. En teoría, esto puede cambiar en el futuro, pero en la práctica debería ser bastante estable.
Aquí hay una comparación del gas utilizado en los tres métodos por @NickJohnson, @Eth y @k26dr. He agregado constant
a los modificadores de función ya que estas funciones no alteran la cadena de bloques:
pragma solidity ^0.4.2;
contract Test {
function toBytesNickJohnson(uint256 x) constant returns (bytes b) {
b = new bytes(32);
assembly { mstore(add(b, 32), x) }
}
function toBytesEth(uint256 x) constant returns (bytes b) {
b = new bytes(32);
for (uint i = 0; i < 32; i++) {
b[i] = byte(uint8(x / (2**(8*(31 - i)))));
}
}
function toBytesNicolasMassart(uint256 x) constant returns (bytes c) {
bytes32 b = bytes32(x);
c = new bytes(32);
for (uint i=0; i < 32; i++) {
c[i] = b[i];
}
}
}
Puede ver el costo de la gasolina para ejecutar estas funciones en Remix (Solidity Browser):
No hay formas fáciles de convertir nada a bytes
. Aquí hay una función:
function toBytes(uint256 x) returns (bytes b) {
b = new bytes(32);
for (uint i = 0; i < 32; i++) {
b[i] = byte(uint8(x / (2**(8*(31 - i)))));
}
}
Basado en el chat de Solidity Gitter.
Si está demasiado preocupado por la gasolina, también podemos mejorar la respuesta de @NickJohnson.
function toBytes(uint _num) returns (bytes _ret) {
assembly {
_ret := mload(0x10)
mstore(_ret, 0x20)
mstore(add(_ret, 0x20), _num)
}
}
Esto reducirá aproximadamente un 15 % adicional el costo de la gasolina, solo tenga cuidado de no usar esa memoria para otra cosa, ya que 0x10 es una referencia directa a la memoria.
Además, si desea copiar un int de 8 bits a un byte, aquí hay una alternativa que solo usa la mitad del costo del gas:
function toByte(uint8 _num) returns (byte _ret) {
assembly {
mstore8(0x20, _num)
_ret := mload(0x20)
}
}
Nuevamente, tenga en cuenta que 0x20 es otra referencia directa a la memoria y, con toda honestidad, me quedaría con esta.
function toByte(uint8 _num) returns (byte _ret) {
return byte(_num);
}
El precio del gas entre los dos era casi idéntico, pero el ASM funcional lo estaba rebajando en alrededor de 70 wei.
Editar: si le preocupa sobrescribir la memoria, puede usar:
let m_alloc := add(msize(),0x1)
En lugar de hacer referencia a la memoria usted mismo
Puede convertir a bytes32 y luego convertir a bytes:
uint u = 200;
bytes32 b = bytes32(u);
bytes memory c = new bytes(32);
for (uint i=0; i < 32; i++) {
c[i] = b[i];
}
Puede evitar rellenar la matriz de bytes con 0 con las toBytes
implementaciones determinando scriptNumSize
function scriptNumSize(uint256 i) public view returns (uint256) {
if (i > 0x7fffffff) { return 5; }
else if (i > 0x7fffff ) { return 4; }
else if (i > 0x7fff ) { return 3; }
else if (i > 0x7f ) { return 2; }
else if (i > 0x00 ) { return 1; }
else { return 0; }
}
function toBytes(uint256 x) public view returns (bytes memory b) {
uint a = scriptNumSize(x);
b = new bytes(a);
for (uint i = 0; i < a; i++) {
b[i] = byte(uint8(x / (2**(8*(a - 1 - i)))));
}
}
Por ejemplo, uint 1563384765 devolvería 0x5d2f5bbd no 0x00000000000000000000000000000000000000000000000000000000005d2f5bbd
Esto fue escrito específicamente para las marcas de tiempo. Si desea números más grandes, puede agregar más casos.
poliani
skgbanga
skgbanga
CJ42
bytes
tipo en Solidity se almacena en la memoria como: 1) primeros 32 bytes = longitud delbytes
valor, 2) luego elbytes
valor en sí. Elmstore
código de operación almacena 32 bytes, a partir de un cierto desplazamiento (en el valor de bytes para capturar) a una ubicación específica en la memoria. Entonces, la instrucciónmstore(add(b, 32), x)
se puede traducir en palabras simples como "almacena 32 bytes en la posición x en la memoria, comenzando desde el desplazamiento de 32 bytes enb
" (para omitir la longitud y simplemente almacenarseb
).