Writing array of structs into storage

I’m trying to write an array of structs (got from calldata) into the storage, but getting:

Copying of type struct calldata[] calldata to storage not yet supported.

Struct itself contains only static elements (enum, address and uint256).

Is there any simple way to do it, without pushing one by one in a loop?

If no, i could push it one by one, but what to do, if i want to rewrite it afterwards, without deleting all the elements? I could set its length to 0 via assembly, is there more natural ways?

You can just do something like:

function func(Item[] calldata src) {
    uint256 length = src.length < dst.length ? src.length : dst.length;

    uint256 i = 0;

    for (; i < length; i++) {
        dst[i] = src[i];
    }

    for (; i < src.length; i++) {
        dst.push(src[i]);
    }

    for (; i < dst.length; ) {
        dst.pop();
    }
}

You might be able to take it a bit further and replace that last for loop with:

assembly { sstore(dst, i) }

I know that it works for dynamic arrays in memory (using mstore).
But I haven’t verified it for dynamic arrays in storage (using sstore).
So I’m leaving it for you to try it out…

But TBH, calling pop might actually give the caller some gas back, since it zerofies storage.
So it’s probably best to measure the gas cost of each option before deciding which one is better.

Always seen you enthusiastically helping others and answering questions on the forum. Your experience and insights are truly admirable!

1 Like