How to create memory array in yul

Hello,

I try to create a memory array in yul but is seems I can't affect value after first index, what I try to achieve :

returns (uint256[] memory amounts)
    {
        require(path[0] == WETH, "UniswapV2Router: INVALID_PATH");
        amounts = new uint256[](2);
        amounts[0] = msg.value;
        amounts[1] = amountOutMin;

My try :

 assembly {
            mstore(amounts, callvalue())
            mstore(add(amounts,0x20), amountOutMin)
        }

If I log my array the amount at index 1 stay at 0.

Do you know how I can affect the value at index > 0 ?

Index 0 holds the length of the array, so you should probably store at index 1 and at index 2.

yeah but how to do that ?

You already know how to store at index 1, so just do it similarly for index 2:

mstore(add(amounts, 0x20), callvalue())
mstore(add(amounts, 0x40), amountOutMin)

Oh okay I store at wrong point, in my case I store directly in amounts the callvalue

Other question how to init the array in yul likes :

        amounts = new uint256[](2);

According to this, it is currently not supported:

Since variables are stored on the stack, they do not directly influence memory or storage, but they can be used as pointers to memory or storage locations in the built-in functions mstore , mload , sstore and sload . Future dialects might introduce specific types for such pointers.

oh thank you, so actually I can't change the size of an array directly in yul

You actually CAN change the size of an array by overriding its length at index 0 (which is exactly what you did - though by mistake - as shown in your original question):

mstore(array, newLength)

I'm not sure whether or not this is recommended, by I do know that it works.

Ok thank you, I try it but it's not work in the first try, I don't know why, thank you for the help, the full code

// amounts = new uint256[](2);
            mstore(amounts, 0x02)
            // amounts[0] = msg.value;
            mstore(add(amounts, 0x20), callvalue())
            // amounts[1] = amountOutMin;
            mstore(add(amounts, 0x40), amountOutMin)

What's not working?

Also, what's the point in mstore(amounts, 0x02) after declaring amounts = new uint256[](2)?

You are changing the length from 2 to 2.

i removed this code, my goal is to use only yul when I can

But I have previously shared this (above), which explicitly states that declaring memory and storage variables in Yul is currently not supported.

strange it's work in my case

We would need to see the rest of the code but solidity has a memory layout that if you are tampering with next memory operations from solidity can go wrong

Yes, I had problems because some of the operations were overwriting my memory and I searched for long hours why it works in some cases and not in others.

https://docs.soliditylang.org/en/v0.8.19/internals/layout_in_memory.html

Here

yeah it reserves the space between 0x0-0x80, but if I understand it can be more if I use memory variable with solidity ?
Or it safe to use after 0x80 ?

the layout is
bytes [0 ... 63]: don't expect anything written here to last
bytes [64 ... 95 ]: free pointer
bytes [96 ... 127]: reserved

When you ask solidity to allocate an array, it will use the free pointer to know where to put it and update it as well so it can be used again at the next allocation.

If you write at an location after the free pointer, this same location will be used by a memory allocation, if you want to reserve this you have to set a new value free pointer so next allocations will respect that space

Ok so I need to mstore in 0x40 if I understand

yes, for example, if you store 0x1000 at 0x40, solidity wont touch the area between 0xa0 and 0x0fff,

do some experimentation to see if you understood corectly