If you’re an expert solidity developer and have worked on various projects this would surely be a matter of concern for you most of the time.
Memory arrays are usually dynamically constructor arrays in a function with visibility identifiers like pure, view where we generally read the state and construct a dynamic array rather than modifying a state.
While modifying a state we usually read from storage and hence we can construct dynamic arrays. So that’s a whole of a different issue.
Problem:
We’ve created a smart contract that stores the IDs of NFTs owned by a wallet address and on the fly, we should generate a dynamic array that returns the IDs of NFTs that are bought within 30 days from now.
Solution:
Need to construct a dynamic array.
Code:
// SPDX-License-Identifier: ISC
pragma solidity ^0.8.13;
contract DynamicArray {
uint256 public supply;
struct NFT {
uint256 id;
uint256 purchasedAt;
}
struct User {
uint256[] nfts;
}
mapping(address => User) private user;
mapping(uint256 => NFT) public nft;
function purchase() external virtual {
supply += 1;
nft[supply] = NFT(supply, block.timestamp);
user[msg.sender].nfts.push(supply);
}
function fetchUserNfts(address userAddrress)
external
view
returns (uint256[] memory)
{
return user[userAddrress].nfts;
}
}
So in the above smart contract, it is clear that when we return a static memory array it works like a hot knife on butter.
But we don’t need to fetch just the NFTs of a user instead we need to fetch the NFTs that are purchased within the last 30 days. So here comes the need for a dynamic array.
function fetchUserNftsInLast30Days(address userAddrress)
external
view
returns (uint256[] memory) {
uint256[] memory nfts = user[userAddrress].nfts;
uint256 size;
uint256 counter;
for(uint256 i=0; i<nfts.length; i++) {
if(
nft[nfts[i]].purchasedAt + 30 days
> block.timestamp)
{
size ++;
}
}
uint256[] memory filtered = new uint256[](size);
for(uint256 i=0; i<nfts.length; i++) {
if(
nft[nfts[i]].purchasedAt + 30 days
> block.timestamp)
{
filtered[counter] = nfts[i];
counter ++;
}
}
return filtered;
}
Analysis
The above code will allow you to fetch the IDs of NFTs purchased by a user in the last 30 days but the gas consumption increases exponentially. Basically, we don’t spend gas for viewing but still, there is a risk of running out of block size.
Safe limit: 200 IDs
If always your array length would be less than 200 in length, then you could practically apply this solution in your smart contract.
Another approach to this would be removing the size calculation in the first part of this function and just declaring the total size of the array as the size of the new array except for the fact that we end up with a handful of zeros in the array that doesn’t satisfy the necessary condition.
Gas difference: 98,435 Vs 6,00,000
But the array returned would have a lot of zero entries, since the entries that are not updated will be returned as zeroes, and also these zero entries cannot be poped from the array since the memory arrays do not have the pop() method
If you want to add your views to this article, please email me at somraajsujith@gmail.com with Sub: ID: 102 in mirror.xyz