1

How to fetch value from dynamic array push function? Below is the code of pushing function, but how will I fetching that array values?

contract PushStruct {

  struct MyStruct {
    uint field1;
    uint field2;
  }

  MyStruct[] public myStructs;

  function pushStruct() 
    public

  {
    MyStruct memory m;
    m.field1 = 1;
    m.field2 = 2;
    myStructs.push(m);

  }
}

For Example:

function valuereturn() view public returns(uint){
    for(uint n=0;n<myStructs.length;n++){
        myStructs storage f = MyStruct[n];
        return (f.field2);
    }
}

When I am trying to run the above code, getting complilation error (Error : TypeError: Storage location can only be given for array or struct types..) Can you please explain how to figure out this issue? Help will be appreciated.

  • What is this return statement inside a for loop? What exactly are you expecting to happen??? The function will return at the end of the first iteration, hence the rest of the loop is meaningless! – goodvibration Mar 18 at 9:31
  • OK. sorry. Its my mistake. But can you explain how to return mystructs array values? – lekshmi Mar 18 at 9:35
  • Pass an index to the function. – goodvibration Mar 18 at 9:47
  • By the way, if you only need to call it from the off-chain (and not from another contract), then such function is already available to you implicitly as function myStructs(uint index) public view returns (uint, uint). So there's nothing for you to do. You can add a function to return myStructs.length, which will make it easier for you to handle things in an off-chain script. – goodvibration Mar 18 at 9:48
  • Should be myStructs[n] instead of MyStruct[n], and should be MyStruct storage f instead of myStructs storage f. And you method stops after returning value from the first struct. Is this desired? – Mikhail Vladimirov Mar 18 at 12:50
0

The question comments raise multiple concerns with the code. It need's a bit of a refactor. The pattern you're going for looks like this, so the details here may answer your questions: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a

You can also find some patterns to give you ideas over here: Are there well-solved and simple storage patterns for Solidity?

To answer your question more directly ...

How to fetch value from dynamic array push function?

There are a few options.

  1. Event emitters are instrumental for informating external software clients about what's going on inside the contract. Consider using events so clients already know the contents of the array and therefore have no good reason to ask.
  2. Use client-side iteration. Returning a complete array is a lot like SQL's "SELECT * FROM ...". It's not very Ethereum-like because gasCost is a factor of work, the work will increase scale (and therefore the cost) and it's seldom necessary because of suggestion #1. In this pattern, implement a function to return the count, function getCount() public view returns(uint) {return myStructs.length;}, and a function to return one row of struct members.function getStructAtIndex(uint row) public view returns(uint, uint) {return (myStructs[row].field1, myStructs[row].field2);}`
  3. For internal messages between functions you can return a storage pointer for the entire array. This gets it done efficiently. ...returns(MyStruct[] storage m) { return myStructs;}. Very important to know what you're doing with storage pointers: https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089
  4. For external clients, it's possible to return an array (but not an array of structs unless you use the experimental ABI, at this time). This is a bad idea unless you're certain the array can never grow to size that would make it impractical or impossible to use.

Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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