I know that it's possible to return a struct through argument destructing:

contract Test {
    struct Point {
        int x;
        int y;
    }

    Point point;

    function getPoint() returns (int x, int y) {
        x = point.x;
        y = point.y;
    }
}

The problem is that I need to return an array of structs:

contract Test {
    struct Point {
        int x;
        int y;
    }

    Point[] allPoints;

    function getPoints() returns (???) {
        ???
    }
}

Is it possible?

From what I've tested and read, you cannot return dynamic arrays from Solidity functions yet, but the developers are planning to include this functionality sometime. References cryptic type error for multiple return values #164 and Return an array from a Solidity function.

In the meantime, you could create a function getNumberOfPoints() to return the number of points, and modify getPoint() to take an index and return the (x, y) of the point in the array pointed to by the index.

  • LOL. This means I'm screwed. Thank you very much. I'll leave the question open so you might be able to update your answer when/if this feature is released. – Henrique Barcelos May 4 '16 at 15:28
  • @Henrique Check my answer below, hope that helps. – Susmit Jun 30 '17 at 13:52

Simply keep track of the indicies, for example by address

Struct[] public objects;
mapping(address => uint256[]) private indicies;
function getIndicies() constant returns (uint256[]) {
  return indicies[msg.sender];
}

Then you can use the following (written as test):

it('should return objects', async () => {
  const indicies = await contract.getIndicies.call({ from: address });
  for (let i in indicies) {
    const index = indicies[i].toNumber();
    //call public abi function of objects
    const object = await contract.objects.call(index);
    console.log(object);
  }
  assert(true, 'balance should be zero');
});
  • It will require a trade off, since it will require an state variable which willl cost more gas, also your function to return should be view type to not behave like a transaction – Eduardo Pereira Feb 11 at 21:02

Given certain conditions on how you've implemented your data structure it is possible to do so. For example look at the code below for contract and javascript:

contract Y{
   string head;
   struct Temp{
      address addr;
      string next;
      string current;
   }
mapping (string => Temp) _temp;
function Y(){
    _temp['root'].addr = 0;
    _temp['root'].next = 'root';
    _temp['root'].current = 'root';
    head = 'root';
}
function addNodes(string _current, address _addr){
    string memory _curr = _current;
    _temp[_current].current = _curr;
    _temp[_current].next = head;
    _temp[_current].addr = _addr;
    head = _curr;
}

function getHead() constant returns(string){
    return head;
}

function getNodes(string _current) constant returns (string,string,address){
    string temp1 = _temp[_current].next;
    address _addr = _temp[_current].addr;
    string temp2 = _temp[_current].current;
    return (temp1,temp2,_addr);
}

}

getList.js

 var Head = y.getHead();
 var tempCurrent="";
 var tempAddress="";
 var next="";
 var arr="";
 var length="";
 var temp="";
 var t_Current="";
 var t_Address="";
 for(;next!='root';){
   temp = y.getNodes(Head);
   length = temp.lenght;
   temp = temp +  "";
   arr = temp.split(",");
   next = arr[0];
   tempCurrent = arr[1];
   tempAddress = arr[2];
   Head = next;
   t_Current = t_Current + tempCurrent + ";";
   t_Address = t_Address + tempAddress + ";";
}
var arr_Current = t_Current.split(";");
console.log(arr_Current);
//console.log(t_Current);

Once you have deployed contract and have added data to contract you can simply call getList.js using loadScript("getList.js") from geth and bingo you will have data from all nodes in list .

PS: This is just a demo you can do much more with your contract.

Here is the way I came up with to return dynamic local arrays from a method. Am sure using this, one can come up with various ways to get data using arrays.

Solidity Contract Method

function getArrayData() constant returns (bytes32[] _data1, bytes32[] _data2) {

    bytes32[] memory arrData1 = new bytes32[](5);
    bytes32[] memory arrData2 = new bytes32[](5);

    arrData1[0]='Data 1 - 1';
    arrData1[1]='Data 1 - 2';
    arrData1[2]='Data 1 - 3';
    arrData1[3]='Data 1 - 4';
    arrData1[4]='Data 1 - 5';

    arrData2[0]='Data 2 - 1';
    arrData2[1]='Data 2 - 2';
    arrData2[2]='Data 2 - 3';
    arrData2[3]='Data 2 - 4';
    arrData2[4]='Data 2 - 5';

    return (arrData1, arrData2);
 }

NodeJS Call

contractInstance.getArrayData.call((err, res) =>{
      console.log('Data 1: ' + web3.toAscii(res[0][0])); 
      console.log('Data 1: ' + web3.toAscii(res[0][1])); 
      console.log('Data 1: ' + web3.toAscii(res[0][2])); 
      console.log('Data 1: ' + web3.toAscii(res[0][3])); 
      console.log('Data 1: ' + web3.toAscii(res[0][4])); 

      console.log('Data 2: ' + web3.toAscii(res[1][0])); 
      console.log('Data 2: ' + web3.toAscii(res[1][1])); 
      console.log('Data 2: ' + web3.toAscii(res[1][2])); 
      console.log('Data 2: ' + web3.toAscii(res[1][3])); 
      console.log('Data 2: ' + web3.toAscii(res[1][4])); 
    });

Hope this helps!

With Solidity 0.4.18, I was able to return a dynamic array of structs from a function but wasn't able to deal with it when I called this function from another contract.

  • can you please share an example? – Ajay Jadhav Jan 20 at 12:20
  • struct Qryp{ address sender; string senderName; uint created; string message; } Qryp[] qryps; function Qrypper() public { qryps.push(Qryp(0, "ulu", now, "hi")); } function getQryps() public constant returns (Qryp[]){ return qryps; } – ulu Jan 23 at 10:06
  • 1
    Showing TypeError: This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. Using pragma version greater than 0.4.18 – Amit Sharma Jun 18 at 2:08
  • Yes, I used this pragma header. – ulu Jun 19 at 19:42

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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