# How to concatenate two bytes16 to bytes32

I'am trying to concatenate tow bytes16 to form a bytes32

``````    func concat(bytes16 t1, bytes16 t2) public returns (bytes32)
``````

I'am not finding anything in solidity documentation! Is anyone have an idea about this?

• How about `return bytes32((uint256(t1) << 16) | uint256(t2))`? Commented Jun 28, 2019 at 10:17
• no it doesn't work: it shows TypeError: Explicit type conversion not allowed from "bytes16" to "uint256"
– MS B
Commented Jun 28, 2019 at 10:30
• Then cast it to `bytes32` first. Commented Jun 28, 2019 at 11:00

## 2 Answers

I would do it this way:

``````function concat (bytes16 a, bytes16 b) public pure returns (bytes32) {
return bytes32 (uint256 (uint128 (a)) << 128 | uint128 (b));
}
``````

Explanation:

`uint128 (a)` reinterprets `a` as 128-bit unsigned integer. As long as 128 bit = 16 bytes, there is no data loss here.

`uint256 (uint128 (a))` widens 128-bit integer obtained at previous step to 256-bit integer by adding 128 zero bits to it from the left.

`uint256 (uint128 (a)) << 128` shifts 256-bit integer obtained at previous step to the left by 128 bit, so it removes 128 zero bits from the left and adds 128 zero bits to the right.

`uint128 (b)` reinterprets `b` as 128-bit unsigned integer. As long as 128 bit = 16 bytes, there is no data loss here.

`uint256 (uint128 (a)) << 128 | uint128 (b)` computes bitwise “or” operation on `a` shifted left by 128 bits and `b`. Bitwise “or” produces “one” bit at certain position if either argument has “one” at this position, and zero bit, if both arguments has zeros at this position. As long as left argument has zeros at 128 rightmost bits, and right argument is only 128 bit long, so it has zeros at 128 leftmost positions, so effectively we concatenate `a` and `b` here.

Now `bytes32 (...)` just reinterprets 256-bit integer obtained at previous step as `bytes32`. As long as 256 bit is 32 bytes, there is no data loss here.

With assembly:

``````function concatenate(bytes16 _a, bytes16 _b) public pure returns (bytes32) {
assembly {
let ptr := mload(0x40)

mstore(ptr,_a)
mstore(add(ptr,0x10),_b)

return(ptr,0x20)
}
}
``````

Test:

``````decoded input
{
"bytes16 _a": "0x15458ef540ade6068dfe2f44e8fa733c",
"bytes16 _b": "0x15458ef540ade6068dfe2f44e8fa733f"
}
decoded output
{
"0": "bytes32: 0x15458ef540ade6068dfe2f44e8fa733c15458ef540ade6068dfe2f44e8fa733f"
}
``````