How do I initialize an array in a struct
Asked Answered
C

2

17

I have a struct Purchase in which I'm putting an array of payments. However, when I try to add the new payments array in my makePayment method I get an error back from the solidity compiler: "Internal compiler error: Copying of type struct Payment memory[] memory to storage not yet supported." When I change the mayment array to be storage or memory, I get the same error. I've added the relevant code below.

Is it possible to do what I'm trying to do in solidity? I don't see anything explicitly saying it's not possible in the documentation but I also don't see any examples doing what I'm trying to do. :|

  struct Payment {
    address maker;
    uint amount;
  }

  struct Purchase {
    uint product_id;
    bool complete;
    Payment[] payments;
  }
  Purchase[] purchases;

  function makePayment(uint product_id, uint amt, uint purchase_id) returns (bool) {

      Payment[] payments;
      payments[0] = Payment(address, amt);
      purchases[purchase_id] = Purchase(product_id, false, payments);
  }
Chert answered 2/3, 2016 at 10:1 Comment(2)
It's possible that this was happening because I wasn't using enough gas for the transaction.Chert
Did you see there is an Ethereum SE beta?Eastwards
C
12

You need to manually change the length of the payments array when setting it.

Either use:

  Payment[] payments;
  payments[payments.length++] = Payment(address, amt);

Or:

Payment[] payments;
payments.push(Payment(address, amt));

For setting the payments array in Purchase, instead of creating an array and trying to set it to the Purchase.payments you can do the following:

uint purchase_id = purchases.length++;
purchases[purchase_id].product_id = product_id;
purchases[purchase_id].complete   = false;
purchases[purchase_id].payments.push(Payment(msg.sender, amt));

Extending the purchases length will automatically create the new attributes. Then you can set them manually.

Chert answered 2/3, 2016 at 13:25 Comment(2)
Does payments need the memory keyword in this case?Ensign
In solidity 8 this solution won't work as length is read-only, but you can simply do Purchase p = purchases.push() instead, and instead of having index, you can do p.product_id = product_id and so onOutput
D
0

I found this as best solution.

  event OnCreateRoom(address indexed _from, uint256 _value);

   struct Room {
      address[] players;       
      uint256 whosTurnId;
      uint256 roomState;
   }  

   Room[] rooms;

   function createRoom() public{
       address[] adr;
       adr.push(msg.sender);
       Room memory room = Room(adr, 0, 0);   
       rooms.push(room);
       OnCreateRoom(msg.sender, 0);
   }
Digitalis answered 14/10, 2021 at 1:48 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Osterman

© 2022 - 2024 — McMap. All rights reserved.