Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copying of type struct memory[] memory to storage not yet supported #3446

Closed
EasonWang01 opened this issue Jan 29, 2018 · 11 comments
Closed

Comments

@EasonWang01
Copy link

If we have the following:

    Student[] public students;
    
    struct Student {
        string name;
        uint weight;
        uint height;
        uint age;
    }

    function remove_student(uint id) public onlyTeacher returns (Student[] ) {
        Student[] memory _students = students;
        while (id < _students.length-1) {
            _students[id] = _students[id + 1];
            id++;
        }
        students.length--;
        students = _students;
    }

It will got some error

Copying of type struct memory[] memory to storage not yet supported

When will this being support in the future in order for saving gas for array manipulate.

@OliviaSong
Copy link

Without this function, arrays of structures can hardly be used.

@chriseth
Copy link
Contributor

Note that an extremely high amount of gas is hidden behind this simple assignment. We recommend using a loop to perform the assignment anyway. An even more efficient way to write the function above is to not use a memory array at all and directly work on storage.

@OliviaSong
Copy link

@chriseth
I mean, when will the storage return be formally supported?
The present structure can only record state, and it is of little use in function.

@chriseth
Copy link
Contributor

@hunjixin you can copy employing a loop. We are actually considering removing copy operations that require unbounded costs alltogether from the language.

@leonardoalt
Copy link
Member

Closing since it seems answered. Please feel free to reopen with more questions.

@CrackerHax
Copy link

Would be nice to get a line number from this error.

@cameel
Copy link
Member

cameel commented Aug 5, 2020

Some extra info for anyone annoyed by this not being allowed: we do plan to make expensive copy operations like this possible and easy but we want the user to be aware the this is not something to be done lightly. The copyof operator (#2435) would be a solution for this.

@PaulRBerg
Copy link
Contributor

PaulRBerg commented May 4, 2023

Would be nice to get a line number from this error.

Seconded! I just ran into this issue in a Foundry repo with 250+ Solidity files and I've no idea where to start debugging.

@lucaslee129
Copy link

lucaslee129 commented Jan 15, 2024

@Reopening.

@lucaslee129
Copy link

Hi, Team. Thanks for your kind answers. But I have not found answers yet.

Please consider this code bases.

// IBlueprintData.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface IBlueprintData{
struct ERC20Data {
address tokenAddress;
uint256 amount;
}

struct ERC721Data {
    address tokenAddress;
    uint256 tokenId;
}

struct ERC1155Data {
    address tokenAddress;
    uint256 tokenId;
    uint256 amount;
}

struct BlueprintData {
    ERC20Data[] erc20Data;
    ERC721Data[] erc721Data;
    ERC1155Data[] erc1155Data;
}

struct BlueprintNFT {
    uint256 id;
    string name;
    uint256 amount;
    address creator;
    string uri;
    uint256 mintPrice;
    uint256 mintLimit;
    BlueprintData data;
}

}

// BluePrint.sol(Method 1)
...
BlueprintNFTs[newTokenID] = BlueprintNFT(newTokenID, name, 1, creator, uri, mintPrice, mintLimit, newBlueprintData);
...

This codebase occured this error: "Copying of type struct IBlueprintData.ERC20Data memory[] memory to storage not yet supported."

So I modified like this.

// BluePrint.sol(Method 2)
BlueprintNFT memory newBlueprint;
newBlueprint.id = newTokenID;
newBlueprint.name = name;
newBlueprint.amount = 1;
newBlueprint.creator = creator;
newBlueprint.uri = uri;
newBlueprint.mintPrice = mintPrice;
newBlueprint.mintLimit = mintLimit;

for(uint256 i = 0; i < data.erc20Data.length; i++) {
  newBlueprint.data.erc20Data.push(data.erc20Data[i]);
}

for(uint256 i = 0; i < data.erc721Data.length; i++) {
  newBlueprint.data.erc721Data.push(data.erc721Data[i]);
}

for(uint256 i = 0; i < data.erc1155Data.length; i++) {
  newBlueprint.data.erc1155Data.push(data.erc1155Data[i]);
}

BlueprintNFTs[newTokenID] = newBlueprint;

And this code base is occured this error: "Member "push" is not available in struct IBlueprintData.ERC20Data[] memory outside of storage." Also I cannot find the solution this error.

Please help me.

@cameel
Copy link
Member

cameel commented Feb 2, 2024

Just to clarify, since my comment above is quite outdated and I was not aware of this at the time: this is actually already implemented, but only in the IR codegen. It won't be implemented in the legacy codegen, but if you're running into this, you can get around it by compiling with --via-ir, which will become the default in a few months. Just be aware of semantic differences between legacy and IR pipelines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants