What is the recommended way to convert an address
to bytes
in Solidity?
6 Answers
To be even more efficient:
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
}
}
Takes just 695 gas vs 2500 for Gokulnath's answer and 5000 for Eth's
Edit for solidity ^0.5.0:
This is almost as efficient and much more readable:
function toBytes(address a) public pure returns (bytes memory) {
return abi.encodePacked(a);
}
Here is my tiny one-liner for address
to bytes32
conversion:
bytes32(uint256(uint160(addr)) << 96);
If you need bytes
instead of bytes32
:
abi.encodePacked(addr)
-
2This answers a different question because
bytes
is different frombytes32
.– eth ♦Mar 11, 2018 at 9:45 -
3Also, note that this will pad the bytes32 to the right. Normally, in Ethereum, we pad to the left. Just omit the
<< 96
to do that. Feb 27, 2019 at 16:27 -
This answer does not work today. It says cannot convert address type to uint.– YulePaleJul 20, 2021 at 5:08
-
1
There are no current shortcuts and you need to write your own function.
Here's the function suggested by Solidity's author, 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)))));
}
-
1If you want to convert an address to a string, you can then convert the bytes to a string just using explicit conversion, as
string(b)
– MrChicoMar 22, 2016 at 15:14 -
Getting this error in browser solidity:
Error: Type string memory is not implicitly convertible to expected type string storage pointer.
Aug 26, 2016 at 23:27 -
1@koampapapa I looked into it and answered your question ethereum.stackexchange.com/questions/8346/… If really needed, consider doing conversions in the UI/frontend/Javascript instead of Solidity to save gas.– eth ♦Aug 27, 2016 at 2:01
-
Later can we convert
bytes
(b) tobytes32
to store it inbytes32
format? @eth– alperMar 1, 2019 at 7:54 -
@alper It would be better to directly cast the address to a
bytes20
, which will work wherever you wanted to usebytes32
.– eth ♦Mar 1, 2019 at 8:41
Here is an one-line solution.
abi.encodePacked(addr)
It's simple and costs little
-
1Welcome to the Ethereum Stack Exchange! It is tempting to write a short answer, but too short is not helpful. For example, what does "costs little" mean? Is there a comparison of gas compared to the accepted answer? Which versions of Solidity can this be used for?– eth ♦Nov 10, 2018 at 23:46
This is similar to the answer given above but is more gas efficient as it is in assembly.
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;
}
-
3There's really no need for a loop at all, since we're dealing with < 32 bytes Mar 29, 2017 at 5:09
-
Instead of trying to convert address to raw bytes, it is often easier to use ABI encoding. ABI encoding is not raw byte-to-byte translation, but it adds its own marker bytes to separate fields. However you can perform this with one built-in function.
In Solidity
/**
* 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());
-
This may be clear to those who already know what you're doing, but adding some examples would help make this clearer to those who don't.– eth ♦Mar 17, 2020 at 9:48