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);
  }
unflores
  • 1,764
  • 2
  • 15
  • 35

2 Answers2

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.

unflores
  • 1,764
  • 2
  • 15
  • 35
  • 2
    Does `payments` need the `memory` keyword in this case? – Blake Regalia Nov 15 '17 at 07:23
  • 1
    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 on – Gall Annonim Jul 18 '22 at 12:14
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);
   }
Seth x
  • 9
  • 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](/help/how-to-answer). – Community Oct 14 '21 at 05:44