How to Return an Array of Structs in Solidity

An array is a data structure where multiple values of similar data types can be stored.

In contrast, a struct works as a container of a group of elements of different data types. A struct can then also be considered as a new data type.

Hence we can create an array of structs comprising those new data types.

Most Solidity programmers eventually wonder: How to return an array of structs from a function?

Today, we will create an array of structs and find a way to return it from a function.

Creating a Struct and Adding Features

let’s create a contract named SavingsAccount for Finxter committee members.

pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
contract SavingsAccount {
  struct Member{
    uint id;
    string name;
    uint balance;
  }
  mapping (uint => Member) public members;
  event savingsEvent(uint indexed _memberId);
  uint public memberCount;
  • The standard ABI encoder specification does not permit arrays of dynamic types, structs, or nested variables between the Solidity contract and the dApp. That’s why we used an experimental version ABIEncoderV2, that allows structs, nested, and dynamic variables to be used as parameters into functions.
  • We have created a struct for each member of the committee. It consists of the member’s ID, name and balance.
  • We have created a mapping with key type “uint” and value type β€œMember” to store the values. The mapping works like a dictionary in Python or a map in Javascript. Unlike Python, we can’t iterate through mapping or quickly get its size. We have to do some extra coding for iteration.
  • An event named β€œsavingsEvent” is added to monitor any state changes occurring inside the contract continuously. The smart contract will automatically get notifications when a new member is added to the committee.
  • β€œindexed” keyword is used as a parameter inside the savingsEvent to get the specific events where the parameter equals to _memberId.
constructor() public {
    memberCount = 0;
    addMember("chris",9000);
    addMember("yassin",6000);
  }
  function addMember(string memory _name, uint _balance) public {
    members[memberCount] = Member(memberCount,_name,_balance);
    memberCount++;
  }
  • A constructor is created to count the number of members from zero. Two new members have already been added to the constructor. We can make as many members as we like from the constructor.
  • The addMember() function takes the new member’s name and balance as arguments and adds it to the constructor. It also increases the number of members when a new member joins the committee.

Let’s add a new member to check if all the functions are working correctly. We will add a new member named “adam” and set his balance to 8000.

We deployed the contract and added a member named β€œadam”. Then we clicked the “memberCount” button to check how many members were on the committee. It came up with a result “3” since we have added a new member in the committee with β€œchris” and β€œyassin”. So, all are working fine.

How to Return a Single Structure?

It is possible to return a member’s information using the following function. we can use the _memberID as the id of the member and let it return the information of that structure as a tuple.

function get(uint _memberId) public view returns(Member memory) {
    return members[_memberId];
  }
  • The get() function takes the _memberId as an argument and returns the structure information of that member as a tuple.

As we tried to return the information of the id number 1, it returns the info of Yassin because the member count starts from 0. From the tuple, we can see member id is 1, member name is yassin, and the balance is 6000.

How to Return the Value of a Structure?

If we want to return individual arrays of ID, name and balance from the structure information that is also possible with another function. let’s jump in:

function getMember() public view returns (uint[] memory, string[] memory,uint[]
  memory){
      uint[]    memory id = new uint[](memberCount);
      string[]  memory name = new string[](memberCount);
      uint[]    memory balance = new uint[](memberCount);
      for (uint i = 0; i < memberCount; i++) {
          Member storage member = members[i];
          id[i] = member.id;
          name[i] = member.name;
          balance[i] = member.balance;
      }
      return (id, name,balance);
  }
  • The getMember() function returns each field of the member as an individual array
  • We have declared three new memory arrays with β€œmemberCount”, representing the length of each memory array. As the memberCount increases with the addition of a new member, we can consider it as the array’s length.
  • Using the for loop, we iterate through the “members” array and populate it with the member’s id, name, and balance.
  • The β€˜return’ expression returns individual arrays of the member’s id, name and balance.

When we deployed the contract and clicked the “getMember” button, we got three arrays of id, name, and balance for all the members of the finxter committee.

How to Return an Array of Structures?

We have got the information of all the members in multiple arrays from the above method. But what happens if we try to return all the information of the members in a single array. Is it possible in Solidity?

It’s a bit tricky, but it’s possible in a way. The getMembers() function allows us to achieve that.

function getMembers() public view returns (Member[] memory){
      Member[]    memory id = new Member[](memberCount);
      for (uint i = 0; i < memberCount; i++) {
          Member storage member = members[i];
          id[i] = member;
      }
      return id;
  }
}
  • The getMembers() function returns all the info of the structs in an array
  • A new memory array named β€œid” is created with β€œnew Member[](memberCount)”.
  • For loop iterates through each struct of the “members” array and gathers the information in a single array.
  • The β€œreturn” keyword returns an array with all the member’s info included

As we clicked the “getMembers” button, we got all the member’s info in an array. It shows the id, name, and balance in a sequence.

For your convenience I published the code on GitHub. You may get it here:

That’s all for today. There are other methods available on the web to get the desired answer. But I found the above a good fit. If you are interested in some more solutions like this, you can check the following links of StackOverflow.

References:

Programmer Humor

❓ Question: Why do programmers always mix up Halloween and Christmas?
❗ Answer: Because Oct 31 equals Dec 25.

(If you didn’t get this, read our articles on the oct() and int() Python built-in functions!)