¿Cuál es la forma recomendada de convertir un address
a bytes
en Solidity?
Para ser aún más eficiente:
function toBytes(address a) public pure returns (bytes memory b){
assembly {
let m := mload(0x40)
a := and(a, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, a))
mstore(0x40, add(m, 52))
b := m
}
}
Toma solo 695 de gas contra 2500 para la respuesta de Gokulnath y 5000 para la de Eth
Editar para solidez ^ 0.5.0:
Esto es casi tan eficiente y mucho más legible:
function toBytes(address a) public pure returns (bytes memory) {
return abi.encodePacked(a);
}
Aquí está mi pequeña línea para address
la bytes32
conversión:
bytes32(uint256(uint160(addr)) << 96);
Si necesita bytes
en lugar de bytes32
:
abi.encodePacked(addr)
bytes
es diferente de bytes32
.<< 96
para hacer eso.No hay accesos directos actuales y necesita escribir su propia función.
Esta es la función sugerida por el autor de Solidity, chriseth:
function toBytes(address x) returns (bytes b) {
b = new bytes(20);
for (uint i = 0; i < 20; i++)
b[i] = byte(uint8(uint(x) / (2**(8*(19 - i)))));
}
string(b)
Error: Type string memory is not implicitly convertible to expected type string storage pointer.
bytes
(b) a bytes32
para almacenarlo en bytes32
formato? @ethbytes20
, que funcionará donde quiera usar bytes32
.bytes32
, podría hacer algo como: bytes memory b = toBytes(a); assembly { result := mload(add(b, 32)) }
@ethAquí hay una solución de una línea.
abi.encodePacked(addr)
Es simple y cuesta poco
Esto es similar a la respuesta dada anteriormente, pero es más eficiente con el gas, ya que está en el ensamblaje.
function addressToBytes(address i) returns (bytes by) {
by = new bytes(20);
assembly {
let count := 0
let byptr := add(by, 32)
loop:
jumpi(end, eq(count, 20))
mstore8(byptr, byte(add(count,12), i))
byptr := add(byptr, 1)
count := add(count, 1)
jump(loop)
end:
}
return by;
}
En lugar de intentar convertir la dirección en bytes sin procesar, a menudo es más fácil usar la codificación ABI. La codificación ABI no es una traducción sin procesar de byte a byte, sino que agrega sus propios bytes de marcador a campos separados. Sin embargo, puede realizar esto con una función integrada.
en solidez
/**
* A test method exposed to be called from clients to compare that ABI packing and hashing
* is same across different programming languages.
*
* Does ABI encoding for an address and then calculates KECCAK-256 hash over the bytes.
*
* https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
*
*/
function calculateAddressHash(address a) public pure returns (bytes32 hash, bytes memory data) {
// First we ABI encode the address to bytes.
// This is so called "tight packing"
// https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#soliditysha3
bytes memory packed = abi.encodePacked(a);
// Then we calculate keccak256 over the resulting bytes
bytes32 hashResult = keccak256(packed);
return(hashResult, packed);
}
En JavaScript/TypeScript
import { soliditySha3 } from 'web3-utils';
// Sign address
const { signature, v, r, s } = signAddress(user2);
// This is an address is a hexadecimal format
const ourData = user2.toLowerCase();
// https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#id23
// Convert address to bytes using "tight packing"
// and them calculates keccak-256 over the resulting bytes
const ourHash = soliditySha3({t: 'address', v: user2 });
// We hash data in similar in TypeScript and Solidity
const { hash, data } = await tokenSwap.calculateAddressHash(user2);
assert(ourData.toLowerCase() == data.toLowerCase());
assert(ourHash.toLowerCase() == hash.toLowerCase());
amor
Barrard
tjaden hess