I want to create a function that receives two addresses and saves them into a bytes array. later a matching function will receive this bytes array and parse the two addresses.

function addressesToBytes(address add1, address add2) public view returns(bytes combined) {
    combined = new bytes(40); //since each address is 20 bytes
    //store the two addresses in the bytes array

function bytesToAddresses(bytes combined) returnes(address add1, address add2) {
     // here set add1 and add2 values from combined bytes array

I saw this answer. but it was not enough :(.

  • May I ask what you need this for? There won’t be any gas savings with this since each storage slot on the Ethereum chain has only 256 bits. Therefore, two slots will have to be occupied either way... Jul 19, 2019 at 21:33
  • Hi @LucasAschenbach reason is the bytes array is a generic parameter that is used to return different data to the user. The Bytes array is already part of the user API and I don't want to change the API. So at this stage I am checking how to use it for addresses. Jul 20, 2019 at 18:53

1 Answer 1


This will get the job done:

pragma solidity ^0.5.1;

contract Encoding {

    function encode(address _address1, address _address2) public pure returns (bytes memory output) {
        return abi.encodePacked(_address1, _address2);

    function decode(bytes memory _encoded) public pure returns (address x, address y) {
        assembly {
            x := mload(0x94)
            y := mload(0xa8)

These functions are also pretty efficient. The encoding function takes around 900 gas for execution and the decoding function only around 670.

  • Thank you May I ask. How come first address at 0x94. What is the leading data? Jul 20, 2019 at 18:55
  • When calling the function, the memory slots until 0x50 are reserved by default (I'm not sure why...). In the succeeding memory slots, some part of the call data is loaded. There is some prefix which fills the remaining slots until 0x90. Therefore, our function parameter, which occupies two 256-bit slots due to its size, is starting at 0xa0. Because we only want the first 20 bytes and the mload operation will return mem[p...(p+32)], we have to start reading in the preceding slot at 0xa0 - C = 0x94. Hope it helps! Jul 20, 2019 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.