Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I return an array of struct in solidity?

I am designing a solution for an ethereum smart contract that does bidding. The use-case includes reserving a name eg. "myName" and assigning to an address. And then, people can bid for that name (in this case myName). There can be multiple such biddings happening for multiple names.

struct Bid {
  address bidOwner;
  uint bidAmount;
  bytes32 nameEntity;
}

mapping(bytes32 => Bid[]) highestBidder;

So, as you can see above, Bid struct holds data for one bidder, similarly, the key (eg. myName) in the mapping highestBidder points to an array of such bidders.

Now, I am facing a problem when I try to return something like highestBidder[myName].

Apparently, solidity does not support returning an array of structs (dynamic data). I either need to rearchitect my solution or find some workaround to make it work.

If you guys have any concerns regarding the question, please let me know, I will try to make it clear.

I am stuck here any help would be appreciated.

like image 754
Suraj Kohli Avatar asked Feb 20 '18 04:02

Suraj Kohli


People also ask

Can you return structs in Solidity?

You can't return the struct directly, but can return a tuple of its properties.

How do you access an array of structs?

Array elements are accessed using the Subscript variable, Similarly Structure members are accessed using dot [.] operator. Structure written inside another structure is called as nesting of two structures. Nested Structures are allowed in C Programming Language.

How do you return a struct value in Solidity?

Now, with the new versions of solidity you can return a struct also by using memory keyword after writing struct name in return type.


2 Answers

Return an array of struct in solidity?
In below function getBid returns array of bid structure.

contract BidHistory {
  struct Bid {
    address bidOwner;
    uint bidAmount;
    bytes32 nameEntity;
  }
  mapping (uint => Bid) public bids;
  uint public bidCount;

  constructor() public {
    bidCount = 0;
    storeBid("address0",0,0);
    storeBid("address1",1,1);
  }
  function storeBid(address memory _bidOwner, uint memory _bidAmount, bytes32 memory _nameEntity) public  {
    bids[tripcount] = Bid(_bidOwner, _bidAmount,_nameEntity);
    bidCount++;
  }
  //return Array of structure
  function getBid() public view returns (Bid[] memory){
      Bid[] memory lBids = new Bid[](tripcount);
      for (uint i = 0; i < bidCount; i++) {
          Bid storage lBid = bids[i];
          lBids[i] = lBid;
      }
      return lBids;
  }
}
like image 144
Falansh Siddh Avatar answered Oct 22 '22 18:10

Falansh Siddh


As you mentioned, this is not yet supported in Solidity. The powers that be are planning on changing it so you can, but for now, you have to retrieve the number of elements and then retrieve the decomposed struct as a tuple.

function getBidCount(bytes32 name) public constant returns (uint) {
    return highestBidder[name].length;
}

function getBid(bytes32 name, uint index) public constant returns (address, uint, bytes32) {
    Bid storage bid = highestBidder[name][index];

    return (bid.bidOwner, bid.bidAmount, bid.nameEntity);
}

Edit to address question in comment regarding storage vs memory in this case

Local storage variables are pointers to state variables (which are always in storage). From the Solidity docs:

The type of the local variable x is uint[] storage, but since storage is not dynamically allocated, it has to be assigned from a state variable before it can be used. So no space in storage will be allocated for x, but instead it functions only as an alias for a pre-existing variable in storage.

This is referring to an example where the varable used is uint[] x. Same applies to my code with Bid bid. In other words, no new storage is being created.

In terms of cost:

getBid("foo", 0) using Bid memory bid:

enter image description here

getBid("foo", 0) using Bid storage bid:

enter image description here

In this case, storage is cheaper.

like image 8
Adam Kipnis Avatar answered Oct 22 '22 18:10

Adam Kipnis