Assessment reports>Yeet>Medium findings>Unoptimized ,getClaimableAmount, function
Category: Optimization

Unoptimized getClaimableAmount function

Medium Severity
Medium Impact
High Likelihood

Description

The getClaimableAmount function returns the total reward amount that can be claimed from the Reward contract at the moment (including the amount already claimed):

function getClaimableAmount(address user) public view returns (uint256) {
    // (...)

    for (uint256 epoch = lastClaimedForEpoch[user] + 1; epoch < currentEpoch; epoch++) {
        // (...)
    }

    return totalClaimable;
}

The initial value of lastClaimedForEpoch[user] is zero. If a user has never claimed their reward before, this function iterates from the very first epoch to the current epoch, which can be inefficient if a number of epochs elapsed.

Note that the claim function invokes the getClaimableAmount function:

function claim() external {
    uint amountEarned = getClaimableAmount(msg.sender);
    require(amountEarned != 0, "Nothing to claim");
    require(token.balanceOf(address(this)) >= amountEarned, "Not enough tokens in contract");

    lastClaimedForEpoch[msg.sender] = currentEpoch - 1; // This should be the fix.
    token.transfer(msg.sender, amountEarned);
    emit Rewarded(msg.sender, amountEarned, block.timestamp);
}

Impact

The getClaimableAmount and claim function will spend a lot of gas if a number of epochs has elapsed. For instance, after three years from the creation of the Reward contract, a new user will have to spend around nine million gas in order to invoke these functions.

Recommendations

Consider optimizing the gas usage of the getClaimableAmount function.

Remediation

This issue has been acknowledged by Sanguine Labs LTD, and a fix was implemented in commit 551ed0a7.

Zellic © 2024Back to top ↑