Is there any more gas-efficient way to convert msg.data to int128?

Here is some suggested impl:

function bytesToBytes16(bytes b, uint offset) private pure returns (bytes16) {
  bytes16 out;

  for (uint i = 0; i < 16; i++) {
    out |= bytes16(b[offset + i] & 0xFF) >> (i * 8);
  return out;

int128 id = int128(bytesToBytes16(msg.data, 0));

Any assembler alternative available?

  • I think that even without assembly you could (at least slightly) improve this, by converting to int128 directly. First, declare out as such. Second, on every iteration do out |= int128(b[offset + i]) << (i * 8). Commented Aug 20, 2018 at 14:00
  • Though I haven't tested this to make sure that Solidity compiler can handle the casting of a bytes entry into int128. Commented Aug 20, 2018 at 14:02
  • int128(msg.data) does not work: TypeError: Explicit type conversion not allowed from "bytes calldata" to "int128". int128 k = int128(msg.data);
    – 4ntoine
    Commented Aug 20, 2018 at 17:57

1 Answer 1


This should work

function foo(bytes m) public pure returns (uint128) {
    bytes32 b;
    assembly {
         b := mload(add(m, 0x10))
    return uint128(b);

The idea is to load the 16 bytes preceding our data, and use the truncation from bytes32 to uint128 to discard those first bytes.

Also be aware that msg.data includes the function signature and is encoded using the solidity ABI.

  • is it correct that if transaction is sent using mist or myetherwallet.com with data typed manually there will be no function signature (i believe) - just data. So how should your code snippet be changed then?
    – 4ntoine
    Commented Aug 22, 2018 at 4:26
  • 1
    I tried invoking a function from remix and it includes the function signature. If you are just sending to the contract in the 'extra data' field and processing in the fallback function then yes, it will be just your data, because you are not calling a function directly.
    – Ismael
    Commented Aug 22, 2018 at 14:10
  • in your code snippet you don't skip first 4 bytes for function? so it will work for direct transfer (what i need), right?
    – 4ntoine
    Commented Aug 22, 2018 at 18:01
  • BTW shouldn't it be bytes16 b? as 128 is 16 bytes
    – 4ntoine
    Commented Aug 22, 2018 at 18:40
  • 1
    @4ntoine My snippet do not skip over the first 4 bytes, mload() return 32 bytes I don't know if it is safe to assign it to a bytes16.
    – Ismael
    Commented Aug 22, 2018 at 19:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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