I built a staking contract that allows users to enroll in auto compounding through a function that is basically adding the user address to an array UserList

Now for auto compounding I have these functions

 function performUpkeep(bytes calldata performData) external override {
    lastTimeStamp = block.timestamp;
    counter = counter + 1;

    for (uint256 i = 0; i < userList.length; i++) {
      if (earned(userList[i]) > 0) {
    // We don't use the performData in this example
    // performData is generated by the Keeper's call to your `checkUpkeep` function

Here we run the list of user addresses who have enrolled in auto compounding inside a loop, and if the user becomes too large then it would cause 'Out of gas' error which is commented by the auditor and suggested to be changed to an alternative method, but we found no such alternative option to change the loop logic to another logic

The source code for the contract is located here: https://github.com/Autonio-Foundation/niox-staking-contract/blob/main/contracts/StakingRewardsFactory.sol

Furthermore we checked the implementation in auto cake pool from pancakeswap where they also have a similar implementation and it is not creating any issue for them as shown below:

function updateStakingPool() internal {
    uint256 length = poolInfo.length;
    uint256 points = 0;
    for (uint256 pid = 1; pid < length; ++pid) {
        points = points.add(poolInfo[pid].allocPoint);
    if (points != 0) {
        points = points.div(3);
        totalAllocPoint = totalAllocPoint.sub(poolInfo[0].allocPoint).add(points);
        poolInfo[0].allocPoint = points;

They are also running the pools in a loop and it is not creating any issue for them, any suggestion for alternative logic would be really be helpful, instead of running the address in loop or shall I just use the loop logic and it wouldn't cause any issue? How many addresses can accommodate in a single array until it gives "Out Of Gas" error?

  • One usual solution is to assign shares to each user in proportion to their assets, when rewards are distributed the value of each share will grow in proportion. Let's say 1000 users deposit 1 token = 1 share (1000 shares in total), a month later there are 10 tokens as rewards then 1010 tokens belong to 1000 shares, so each share has a 1.01 value 1% increment. A user withdrawing will retrieve 1.01 tokens, to enter a user has to deposit 1.01 token to get 1 share.
    – Ismael
    Sep 30 at 6:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.