I can bit shift uint_n_
easily but I don't manage to bit shift a bytes memory myBytes
.
When doing myBytes << i
I have a compile error and when using assembly I receive 0.
See my MWE for assembly and test:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library BytesShift {
function shiftLeft(bytes memory x, uint256 n)
public
pure
returns (bytes memory)
{
bytes memory tmp;
assembly {
tmp := shl(n, x)
}
return tmp;
}
}
describe("BytesShift", function () {
describe("shiftLeft", () => {
it(`Should shift bytes to the left`, async function () {
const BytesShift = await ethers.getContract("BytesShift");
const res = await BytesShift.shiftLeft("0xff", 1);
expect(res).to.equal("0xfe");
});
});
});
failing with received value :
AssertionError: expected '0x' to equal '0xfe'
+ expected - actual
-0x
+0xfe
Best Answer
The shift operation is only available for value types not for reference types (see https://docs.soliditylang.org/en/v0.8.11/types.html#value-types)
Value types exist on stack and there can be passed to the shift opcode.
The
bytes memory
only stores the location of the data in memory on stack. So in you assembly example youtmp
just points to an invalid memory location and therefore returns 0.If you want to shift a bytes you need to process the whole bytes data word by word and also handle overflows between the words.