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.

--

--

Responses (1)