Solidity: Fixing Member “push” is not available in struct MyContract.MyListStruct memory[] memory outside of storage.

Victor Yeo
2 min readAug 2, 2022

--

In a smart contract, I want to return an array of MyListStruct based on doc_code. I do NOT know in advance the length of the array. The code in this article is compiled using solidity 0.8.4 version compiler.

Here is MyListStruct declaration:

struct MyListStruct {
string title;
string doc_code;
uint32 version;
}

Here is the code:

function updateMyListByDept(string memory _doc_code) external returns (MyListStruct[] memory) {
MyListStruct memory docItem = MyListStruct(“”,””,0);
MyListStruct [] memory docList_;
for (uint16 i = 0; i < hashList.length; i++) {
if (compareStringsbyBytes(metadataMap[hashList[i]].doc_code, _doc_code)) {
// doc_code same, save the document data
docItem.title = metadataMap[hashList[i]].title;
docItem.doc_code = metadataMap[hashList[i]].doc_code;
docItem.version = metadataMap[hashList[i]].version;
docList_.push(docItem);
}
}
return docList_;
}

I am getting this error below:

Member “push” is not available in struct MyContract.MyListStruct memory[] memory outside of storage.

As a solidity limitation, i cannot use push function on memory scope array. (It is not possible to resize memory scope array.)

To fix it, i have to find out the length of the array in the same function.

function updateMyListByDept(string memory _doc_code) external view returns (MyListStruct[] memory) {
uint16 count = 0;
for(uint16 i=0; i < hashList.length; i++){
if(compareStringsbyBytes(metadataMap[hashList[i]].doc_code, _doc_code)) {
count += 1;
}
}
MyListStruct[] memory docList_ = new MyListStruct[](count);
uint16 count2 = 0;
for (uint16 i = 0; i < hashList.length; i++) {
if (compareStringsbyBytes(metadataMap[hashList[i]].doc_code, _doc_code)) {
// doc_code same, save the document data
docList_[count2] = metadataMap[hashList[i]];
count2 += 1;
}
}
return docList_;
}

Alternatively, i can use a global storage variable for the docList. The downside is there is modification of a global variable.

DocListStruct [] internal docList;function updateMyListByDept(string memory _doc_code) external returns (MyListStruct[] memory) {
MyListStruct memory docItem = MyListStruct(“”,””,0);
delete docList;
for (uint16 i = 0; i < hashList.length; i++) {
if (compareStringsbyBytes(metadataMap[hashList[i]].doc_code, _doc_code)) {
// doc_code same, save the document data
docItem.title = metadataMap[hashList[i]].title;
docItem.doc_code = metadataMap[hashList[i]].doc_code;
docItem.version = metadataMap[hashList[i]].version;
docList_.push(docItem);
}
}
return docList;
}

Basically, we cannot return a storage array inside a function (as below). This is solidity limitation. So we need to put the array as global variable.

function testStorage() external returns (uint[] memory) {
uint [] storage mety;
return mety;
}

If we do that, the error is:

This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.

That is it.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Responses (1)

Write a response