Smart contract pagination for list

  • A contract has an infinite internal storage
  • There are 2 limits to practicalitygas costs and the block gas limit.

Example

Create 5k5 players, read one time

https://testnet.bscscan.com/address/0x721ff9e58831b698efd26b9ac744cf8f0aaecbc2#readContract

Max Gas Limit is 28,500,000 at May 12, 2021 = 0.22BNB ~ $145

  • [WRITE] Can add 500 player in 1 tx
  • [READ] Can not get all 5600 players (1600 is ok)
call to TestPlayerRead.getPlayers
call to TestPlayerRead.getPlayers errored: Error: Internal JSON-RPC error. { "code": -32000, "message": "out of gas" }
  • [READ] To read all data, should use paging approach

TestPlayerRead.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.3;

contract TestPlayerRead {

    struct Player {
        uint id;
    }

    Player[] public playerList;
    mapping(uint => Player) public playerMap;

    constructor () {}

    function addPlayers(uint more) public {
        uint currentSize = getPlayerSize();
        for (uint i = currentSize; i < currentSize + more; i++) {
            uint id = i + 1;
            Player memory player = Player(id);
            playerList.push(player);
            playerMap[id] = player;
        }
    }
    
    function getPlayerSize() public view returns (uint length) {
        return playerList.length;
    }
    
    function getPlayers() public view returns (Player[] memory players) {
        return playerList;
    }
    
    function getPlayersPaging(uint offset, uint limit) public view returns (Player[] memory players, uint nextOffset, uint total) {
        uint totalPlayers = playerList.length;
        if(limit == 0) {
            limit = 1;
        }
        
        if (limit > totalPlayers- offset) {
            limit = totalPlayers - offset;
        }

        Player[] memory values = new Player[] (limit);
        for (uint i = 0; i < limit; i++) {
            values[i] = playerList[offset + i];
        }

        return (values, offset + limit, totalPlayers);
    }
}

Leave a Reply

Your email address will not be published.Required fields are marked *