Solidity Contract Debugging – How to Initialize and Push Items into an Array Inside a Function

arrayscontract-debuggingmemorysoliditystorage

How to initialize an array inside the function and push items into it? I'm not gonna initialize outside the function.

Here's my code:

function tokenOfOwner(address owner) public virtual returns (uint256[] memory) 
{
    uint256[] storage _ownerAmount;
    uint256 amount = ERC721.balanceOf(owner);
    for(uint256 i = 0; i< amount ; i++)
    {
        _ownerAmount.push(_ownedTokens[owner][i]);
    }
    return _ownerAmount;
}

The error message shows:

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

Best Answer

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

Is perfectly normal as uint256[] storage _ownerAmount; is not initialized, meaning that it defaults to slot 0 possibly overwriting whatever is already occupying that slot.

However, looking at your code you probably don't need a dynamic storage array. Only dynamic storage arrays can be resized (pushed to / popped from), this makes sense when the number of elements in unknown, but that is not your case due to :

uint256 amount = ERC721.balanceOf(owner);

A more gas efficient implementation could rely only on static memory arrays with fixed size, such as :

function tokenOfOwner(address owner) public virtual returns (uint256[] memory) 
{
    uint256 amount = ERC721.balanceOf(owner);
    uint256[] memory _ownerAmount = new uint[](amount);
    for(uint256 i = 0; i< amount ; i++)
    {
        _ownerAmount[i] = _ownedTokens[owner][i];
    }
    return _ownerAmount;
}
Related Topic