For example, for two uint16 values, is it possible to concatenate them into one uint32 value and also retrieve the original value later (bitwise operators)?

Please note that I do not mean addition by typecasting the 16 bit value to a 32 bit value and adding them together (+). But packing two 16 bit values into a 32 bit value.

So that instead of this:

           A                  B
           |                  |
mapping (uint16 => mapping (uint16 => bool)) data;

I can do this:

    (A << 16) | B 
mapping (uint32 => bool) data;

You need to use bit shifting operations:

pragma solidity^0.4.11;

contract Packing {

    function pack(uint16 a, uint16 b) public pure returns(uint32) {
        return (uint32(a) << 16) | uint32(b);

    function unpack(uint32 c) public pure returns(uint16 a, uint16 b) {
        a = uint16(c >> 16);
        b = uint16(c);

Note however that the Solidity compiler will do packing of state variables for you if you use the --optimize flag for solc. For example, in the following contract the compiler will generate the code that uses a single storage slot although there are 4 state variables (64 * 4 = 256bits = 32 bytes):

pragma solidity ^0.4.11;

contract C {
    uint64 a;
    uint64 b;
    uint64 c;
    uint64 d;

    function C() {
      a = 0xaaaa;
      b = 0xbbbb;
      c = 0xcccc;
      d = 0xdddd;

You can test if the compiler will also do packing for mappings as in your case.

  • Thanks. Is there a reason why you use the + instead of the | operator? Yes, I will have to analyze whether packing for a mapping index is actually more efficient. – Elias Feb 7 '18 at 10:20
  • 1
    @Elias No reason. In this case both can be used and they are equally efficient in terms of gas as they cost 3 gas. I believe | is more efficient in terms of cpu cycles so I changed my answer. – medvedev1088 Feb 7 '18 at 10:34

Yes you can do. If you want to add to 16 bytes integers there might be a chance of overflow of values which may leads to be unexpected results.

Then solution is convert uint16 bytes to 32 bytes or grater than 16 bytes just by adding uint18 or more. I'll prefer to convert 32 bytes.

Converting uint12 bytes to X bytes is uintX(value) now replace x with 32. so final result is uint32(value)

pragma solidity ^0.4.19;

contract Example {

    uint16 a = 256;
    uint16 b = 256;

    function add() external view returns (uint32 c) {
        c = uint32(a) + uint32(b); //uint18(a)+uint18(b)

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.