# Strange behaviour with assembly and storage slot

**URL:** <https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127>\
**Category:** Smart Contracts\
**Created:** [May 10, 2023, 10:00am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127 "2023-05-10T10:00:40Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![youtpout](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/youtpout/32/13137_2.png) [@youtpout](https://forum.openzeppelin.com/u/youtpout)\
**Post date:** [May 10, 2023, 10:00am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/1 "2023-05-10T10:00:40Z")

</div>

Hello,

I'm rewriting uniswap v2 in inline assembly, i'm trying to update reserve0 and reserve1 info :

```auto
   uint112 private reserve0; // uses single storage slot, accessible via getReserves
    uint112 private reserve1; // uses single storage slot, accessible via getReserves
    uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves

 function _testSave(uint256 balance0, uint256 balance1) private {
        uint256 slot0;
        uint256 slot1;
        assembly {
            // require(balance0 <= type(uint112).max && balance1 <= type(uint112).max,"UniswapV2: OVERFLOW");
            if gt(balance0, 0xfffffffffffffffffffffffffff) {
                mstore(0x80, shl(229, 4594637))
                mstore(0x84, 32)
                mstore(0xA4, 30)
                mstore(0xC4, "OVE")
                revert(0x80, 0x64)
            }
            if gt(balance1, 0xfffffffffffffffffffffffffff) {
                mstore(0x80, shl(229, 4594637))
                mstore(0x84, 32)
                mstore(0xA4, 30)
                mstore(0xC4, "OVE")
                revert(0x80, 0x64)
            }

            //reserve0 = uint112(balance0);
            sstore(reserve0.slot, balance0)
            sstore(reserve1.slot, balance1)
           
            slot0 := sload(reserve0.slot)
            slot1 := sload(reserve1.slot)
        }

        console.log("balance 0 %s balance 1 %s", balance0, balance1);
        console.log("reserve 0 %s reserve 1 %s", slot0, slot1);

        // reserve0 = uint112(balance0);
        // reserve1 = uint112(balance1);
        //reserve.blockTimestampLast = blockTimestamp;

        assembly {
            // emit Sync(uint112(balance0), uint112(balance1));
            mstore(0x100, balance0)
            mstore(add(0x100, 0x20), balance1)
            log1(0x100, 0x40, syncTopic)
        }
    }

```

My log show

balance 0 150000000000000000000000 balance 1 500000000000000000000  
reserve 0 500000000000000000000 reserve 1 500000000000000000000

I think it's because these data share the same storage slot but how correctly update it in assembly ?

---

<div class="post-metadata">

**Author:** ![barakman](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/barakman/32/855_2.png) [@barakman](https://forum.openzeppelin.com/u/barakman)\
**Post date:** [May 10, 2023, 10:51am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/2 "2023-05-10T10:51:00Z")

</div>

> [@youtpout](#):
>
> ```auto
> uint112 private reserve0; // uses single storage slot, accessible via getReserves
> uint112 private reserve1; // uses single storage slot, accessible via getReserves
> uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
> 
> ```

Unless there are other state variables in this contract, these 3 should all be within the same slot.

---

<div class="post-metadata">

**Author:** ![youtpout](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/youtpout/32/13137_2.png) [@youtpout](https://forum.openzeppelin.com/u/youtpout)\
**Post date:** [May 10, 2023, 12:11pm UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/3 "2023-05-10T12:11:25Z")

</div>

Yes, but how do I update each setting?

---

<div class="post-metadata">

**Author:** ![helio.rosa](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/helio.rosa/32/15562_2.png) [@helio.rosa](https://forum.openzeppelin.com/u/helio.rosa)\
**Post date:** [May 10, 2023, 6:05pm UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/4 "2023-05-10T18:05:21Z")

</div>

you need to retrieve the value in the slot, then use logical operations to change the bits corresponding to each variable and finally write it back to the slot

---

<div class="post-metadata">

**Author:** ![youtpout](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/youtpout/32/13137_2.png) [@youtpout](https://forum.openzeppelin.com/u/youtpout)\
**Post date:** [May 10, 2023, 6:51pm UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/5 "2023-05-10T18:51:02Z")

</div>

Can you write me an exemple in code please

---

<div class="post-metadata">

**Author:** ![helio.rosa](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/helio.rosa/32/15562_2.png) [@helio.rosa](https://forum.openzeppelin.com/u/helio.rosa)\
**Post date:** [May 10, 2023, 10:39pm UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/6 "2023-05-10T22:39:58Z")

</div>

my yul is a bit rusty, but i think it would look something like this:

to set reserve0

```auto
masked := and(sload(n_slot), sub(exp(2, 144), 1))
new_v := add(shl(new_r0, 144), masked)
sstore(n_slot, new_v)

```

to set reserve1:

```auto
masked := and(sload(n_slot), add(shl(sub(exp(2, 112), 1), 144), sub(exp(2, 32), 1)))
new_v := add(shl(new_r1, 32), masked)
sstore(n_slot, new_v)

```

to set blockTimestampLast:

```auto
masked := and(sload(n_slot), sub(exp(2, 32), 1))
new_v := add(new_btl, masked)
sstore(n_slot, new_v)

```

---

<div class="post-metadata">

**Author:** ![youtpout](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/youtpout/32/13137_2.png) [@youtpout](https://forum.openzeppelin.com/u/youtpout)\
**Post date:** [May 11, 2023, 4:47am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/7 "2023-05-11T04:47:04Z")

</div>

> [@helio.rosa](#):
>
> ```auto
> masked := and(sload(n_slot), add(shl(sub(exp(2, 112), 1), 144), sub(exp(2, 32), 1)))
> new_v := add(shl(new_r1, 32), masked)
> sstore(n_slot, new_v)
> 
> ```

thanks, I think I'm doing some shit the reserve seems to equal block timestamp :

```auto
            let masked := and(sload(reserve0.slot), sub(exp(2, 144), 1))
            let new_v := add(shl(balance0, 144), masked)
            sstore(reserve0.slot, new_v)

            masked := and(
                sload(reserve1.slot),
                add(shl(sub(exp(2, 112), 1), 144), sub(exp(2, 32), 1))
            )
            new_v := add(shl(balance1, 32), masked)
            sstore(reserve1.slot, new_v)

            masked := and(sload(blockTimestampLast.slot), sub(exp(2, 32), 1))
            new_v := add(timestamp(), masked)
            sstore(blockTimestampLast.slot, new_v)

```

---

<div class="post-metadata">

**Author:** ![barakman](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/barakman/32/855_2.png) [@barakman](https://forum.openzeppelin.com/u/barakman)\
**Post date:** [May 11, 2023, 8:20am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/8 "2023-05-11T08:20:04Z")

</div>

FYI, you can just compile the original code with `--asm`, and then look into the output `.asm` file.

---

<div class="post-metadata">

**Author:** ![helio.rosa](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/helio.rosa/32/15562_2.png) [@helio.rosa](https://forum.openzeppelin.com/u/helio.rosa)\
**Post date:** [May 11, 2023, 10:34am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/9 "2023-05-11T10:34:06Z")

</div>

`--asm` outputs some sort of assembly, `--opcodes` outputs the opcodes and `--ir` outputs ir/yul code. @youtpout is writing code in Yul.

---

<div class="post-metadata">

**Author:** ![helio.rosa](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/helio.rosa/32/15562_2.png) [@helio.rosa](https://forum.openzeppelin.com/u/helio.rosa)\
**Post date:** [May 11, 2023, 10:47am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/10 "2023-05-11T10:47:20Z")

</div>

sorry. was writing this out of the top of my head and didn't do a second check. the masking for `blockTimestampLast` is wrong.  
The idea is to AND the value in the slot with a mask to set the variable to all 0's and then `slh()` then new value and ADD them together.

`masked := and(sload(blockTimestampLast.slot), sub(exp(2, 32), 1))` does the opposite of the intended (144 0's and 32 1's)

it should be : `masked := and(sload(blockTimestampLast.slot), shl(sub(exp(2, 144), 1), 32))` 144 1's and 32 0's

---

<div class="post-metadata">

**Author:** ![youtpout](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/youtpout/32/13137_2.png) [@youtpout](https://forum.openzeppelin.com/u/youtpout)\
**Post date:** [May 11, 2023, 11:36am UTC](https://forum.openzeppelin.com/t/strange-behaviour-with-assembly-and-storage-slot/36127/11 "2023-05-11T11:36:32Z")

</div>

Thanks I compile to yul, analyse the result and update my code to match and it's work

```auto
        assembly {
            // update reserve0
            let value := sload(reserve0.slot)
            let mask := 0xffffffffffffffffffffffffffff
            // uint256 to uint112
            let bal0 := and(balance0, mask)
            let bal1 := and(balance1, mask)

            value := and(value, not(mask))
            let result := or(value, and(bal0, mask))
            sstore(reserve0.slot, result)

            // update reserve1 (the slot remains the same)
            value := sload(reserve0.slot)
            mask := 0xffffffffffffffffffffffffffff0000000000000000000000000000
            let toInsert := shl(112, bal1)
            value := and(value, not(mask))
            result := or(value, and(toInsert, mask))
            sstore(reserve1.slot, result)
        }

```
