Polygon Network – Why is Gas Fee Increasing Over Time for the Same Function on Polygon Network?

polygonremixsmart-contract-wallets

I have developed a Stacking Smart contract on Polygon. It was working fine soon when deployed. But after 10-12 Days, my invest() function stops working because of (maybe) high gas value. At start the gas fee was about 712,297 and today after about 10 days, it's increased to 29,880,863. There is a huge difference which is causing invest() transaction to revert. But it does not happen always. Sometimes the transaction is successful but most of the times it reverts!

Here is my contract Address:
https://polygonscan.com/address/0xc62e1ccdefe1ecf7d7a6173b0c1a2d1fd1fc8551

Here is my invest() function code:

function invest(address referer, uint units) external {
        if (!started) {
            if (msg.sender == firstWallet) {
                started = true;
            } else revert("Not started yet");
        }

        processDeposit(referer, units);

        payReferral(units);

        payForBinate();
    }

Anyone please help. Is this usual problem or is there any issue with the function?
How can I solve this problem?

Best Answer

You DoS yourself. When a number of iteration costs exceed the gas limit, the transaction fails and the contract may be blocked at some point.

I looked at your code, to be honest, it is not optimized at all, there are a lot of iterations, arrays, conditions.

payforRefferal is really huge, contains a lot of conditions, checks.

function payReferral(uint units) private {
        // pay to referral
        uint value = price * units;
        uint commission = value * commissionFeeRate / 1000;
        uint totalRefOut;
        uint userid = userids[msg.sender];
        address upline = users[userid].referer;
        for (uint i = 0; i < referRate.length; i++) {
            uint uplineId = userids[upline];
            if (uplineId == 0) break;
            if (upline != address(0) && levels[uplineId].level > i) {
                if (users[uplineId].disableDeposit) {
                    uint bonus = value * referRate[i] / 1000;
                    totalRefOut = totalRefOut + bonus;
                    token.safeTransfer(upline, bonus);
                    //                    emit PayBonus(upline, bonus);
                    emit UserMsg(uplineId, "RefBonus", bonus);
                    users[uplineId].totalBonus += bonus;
                    if (i == 0) {
                        users[uplineId].directBonus += bonus;
                    }
                }
                upline = users[uplineId].referer;
            } else break;
        }

        for (uint i = 0; i < lvl6.length; i++) {
            uint bonus = value * lvl6Rate / 1000 / lvl6.length;
            totalRefOut += bonus;
            token.safeTransfer(lvl6[i], bonus / lvl6.length);
            //            emit PayBonus(lvl6[i], bonus);
            emit UserMsg(userids[lvl6[i]], "LvL6Bonus", bonus);
            users[userids[lvl6[i]]].totalBonus += bonus;
            users[userids[lvl6[i]]].lvl6Bonus += bonus;
        }

        totalBonus += totalRefOut;
        available -= commission;
        totalCommission += (commission - totalRefOut);

        token.safeTransfer(commissionWallet, commission - totalRefOut);

    }

and payForBinate(), is even worse, it contains a lot of calculation, iterations, loops, etc.

function payForBinate() private {
    for (uint index = nextPayIndex; index < deposits.length - 1; index++) {
        Deposit storage deposit = deposits[index];
        uint balance = token.balanceOf(address(this));
        User storage user = users[userids[deposit.account]];

        uint half = available / 2;
        uint needPay = deposit.amount * payMultiplier - deposit.allocated;
        if (needPay == 0) continue;
        if (half >= needPay) {
            if (balance < needPay) return;
            //                token.safeTransfer(deposit.account, needPay);
            //                deposit.allocated += needPay;
            available -= needPay;
            deposit.allocated += needPay;
            deposit.paid = true;
            user.disableDeposit = false;
            user.totalAllocated += needPay;
            totalAllocated += needPay;
            //                emit PayBinate(index, deposit.account, needPay, true);
            emit UserMsg(userids[deposit.account], "Dividend", needPay);
            nextPayIndex = index + 1;
        } else {
            if (balance < half) return;
            //                deposit.allocated += half;
            available -= half;
            //                token.safeTransfer(deposit.account, half);
            deposit.allocated = deposit.allocated + half;
            user.totalAllocated += half;
            totalAllocated += half;
            //                emit PayBinate(index, deposit.account, half, false);
            emit UserMsg(userids[deposit.account], "Dividend", half);
        }
        break;
    }
    uint share = getOneShareAmount();
    if (share == 0) return;
    for (uint index = nextPayIndex; index < deposits.length - 1; index++) {
        Deposit storage deposit = deposits[index];
        uint needPay = deposit.amount * payMultiplier - deposit.allocated;
        uint balance = token.balanceOf(address(this));
        if (needPay == 0) continue;
        uint topay = share * needPay / 1e18;
        User storage user = users[userids[deposit.account]];
        if (topay >= needPay) {
            if (balance < needPay) return;
            if (available < needPay) return;
            token.safeTransfer(deposit.account, needPay);
            //                deposit.allocated += needPay;
            available -= needPay;
            deposit.allocated = deposit.allocated + needPay;
            deposit.paid = true;
            user.disableDeposit = false;
            user.totalAllocated += needPay;
            totalAllocated += needPay;
            //                emit PayBinate(index, deposit.account, needPay, true);
            emit UserMsg(userids[deposit.account], "Dividend", needPay);
            nextPayIndex = index + 1;
        } else {
            if (balance < topay) return;
            if (available < topay) return;
            //                token.safeTransfer(deposit.account, topay);
            //                deposit.allocated += topay;
            deposit.allocated = deposit.allocated + topay;
            available -= topay;
            user.totalAllocated += topay;
            totalAllocated += topay;
            //                emit PayBinate(index, deposit.account, topay, false);
            emit UserMsg(userids[deposit.account], "Dividend", topay);
        }
    }
}

I'm afraid that your contract is almost no longer usable.

The more people will invest and the more it will be complicated to invest.

Related Topic