3

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). – goodvibration Aug 20 '18 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. – goodvibration Aug 20 '18 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 Aug 20 '18 at 17:57
2

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 Aug 22 '18 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 Aug 22 '18 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 Aug 22 '18 at 18:01
  • BTW shouldn't it be bytes16 b? as 128 is 16 bytes – 4ntoine Aug 22 '18 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 Aug 22 '18 at 19:54

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.