1

I have a User struct and in it I want to have an array with the users posts. But every way I tried to add an empty array it threw an error. So i want to init an empty array but be able to push things to it later.

address payable public Owner;

mapping(address => User) public users;

struct User {
    address useraddress;
    Post[] posts;
}

struct Post {
    string contentlink;
    uint likes;
    uint dislikes;
}

constructor() {
    Owner = payable(msg.sender);
}

function login() public {
    require(users[msg.sender].useraddress != msg.sender, "Already have account");
    users[msg.sender] = User(msg.sender, new Post());
}

3 Answers 3

0

I encountered the exact same problem when I was trying to implement a very similar smart contract. Ultimately, I ended up changing my design pattern. Solidity doesn't yet support initialization of a struct array from memory when trying to write to a storage array in a struct. Hopefully this will be supported in the future because it's quite limiting.

My workaround was opting for this design pattern, where the array of structs is declared outside of the struct itself. I then just map each address to that struct array. It's not pretty, but it does work.

address[] internal addresses;
mapping(string => address) internal names;
mapping(address => Profile) public profiles;
mapping(address => mapping(address => Profile)) internal followers;
mapping(address => mapping(address => Profile)) internal following;
mapping(address => Post[]) internal posts;

// Profile
struct Profile {
    address owner;
    string name;
    uint timeCreated;
    uint id;
    uint postCount;
    uint followerCount;
    uint followingCount;
    address[] followers;
    address[] following;
}

// Post
struct Post {
    address author;
    string content;
    uint timeCreated;
    uint id;
}

You can find my full implementation here:

https://gist.github.com/charlesalexanderlee/c97d6169c9d65d03d74bb25a07d442e1

0

User(msg.sender) wants 2 arguments rather than 1 because it needs to initialise "posts". But if you try user(msg.sender, new Post[](0)) that will also fail because you can't initialise a storage array with a memory array.

However, all storage in the EVM is zero initialised, so you can just do:

User storage user = users[msg.sender];
user.useraddress = msg.sender;
5
  • Thank you for your answer but thats not what im looking for.
    – robinnlmn
    Commented Dec 3, 2021 at 13:45
  • I want to init a empty array and later want to be able to push Post into it.
    – robinnlmn
    Commented Dec 3, 2021 at 13:45
  • That's exactly what this code does. Zeroed memory is the same as an empty array.
    – Joe
    Commented Dec 4, 2021 at 14:43
  • Oh sorry I copied it wrong, but how can i push an object to it I tried: users[msg.sender].posts[0] = Post("TEST", 1, 1); But it doesn't work
    – robinnlmn
    Commented Dec 4, 2021 at 15:16
  • users[msg.sender].posts.push(Post("Test", 1, 1));
    – Joe
    Commented Dec 4, 2021 at 18:07
0

By default, if you create an array in solidity, it initializes a new array with a length of 0. the new array, is used when you want to initialize a new array on an array object that already has objects in it. For your case try;

users[msg.sender].posts = new address[](0);
1
  • That won't work, you can't initialise a storage array with a memory array
    – Joe
    Commented Dec 4, 2021 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.