Was ist der empfohlene Weg, um ein address
in bytes
Solidity umzuwandeln?
Um noch effizienter zu sein:
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
}
}
Benötigt nur 695 Gas gegenüber 2500 für Gokulnaths Antwort und 5000 für Eths
Bearbeiten für Solidität ^ 0.5.0:
Dies ist fast genauso effizient und viel besser lesbar:
function toBytes(address a) public pure returns (bytes memory) {
return abi.encodePacked(a);
}
Hier ist mein winziger Einzeiler für address
die bytes32
Konvertierung:
bytes32(uint256(uint160(addr)) << 96);
Wenn Sie bytes
anstelle von benötigen bytes32
:
abi.encodePacked(addr)
bytes
sich von unterscheidet bytes32
.<< 96
Sie dazu einfach das aus.Es gibt keine aktuellen Verknüpfungen und Sie müssen Ihre eigene Funktion schreiben.
Hier ist die vom Autor von Solidity, Chriseth, vorgeschlagene Funktion:
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) konvertieren bytes32
, um es im bytes32
Format zu speichern? @ethbytes20
, was überall dort funktioniert, wo Sie es verwenden möchten bytes32
.bytes32
verwenden, könnte ich so etwas tun: bytes memory b = toBytes(a); assembly { result := mload(add(b, 32)) }
@ethHier ist eine einzeilige Lösung.
abi.encodePacked(addr)
Es ist einfach und kostet wenig
Dies ähnelt der oben gegebenen Antwort, ist jedoch gaseffizienter als bei der Montage.
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;
}
Anstatt zu versuchen, die Adresse in Rohbytes umzuwandeln, ist es oft einfacher, die ABI-Codierung zu verwenden. Die ABI-Codierung ist keine rohe Byte-zu-Byte-Übersetzung, sondern fügt ihre eigenen Markierungsbytes zu separaten Feldern hinzu. Sie können dies jedoch mit einer integrierten Funktion durchführen.
In Solidität
/**
* 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);
}
In 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());
Eamorr
Barrard
Tjaden Hess