code-423n4 / 2022-01-yield-findings

1 stars 0 forks source link

Perform math inside code branch #106

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Handle

sirhashalot

Vulnerability details

Impact

The _calcCvxIntegral() function in ConvexStakingWrapper.sol doesn't use the same gas optimization that its sibling function _calcRewardIntegral() uses.

Proof of Concept

This code is from the _calcCvxIntegral() function

if (_isClaim || userI < cvxRewardIntegral) {
    uint256 receiveable = cvx_claimable_reward[_accounts[u]] +
        ((_balances[u] * (cvxRewardIntegral - userI)) / 1e20);
    if (_isClaim) {
        if (receiveable > 0) {
            cvx_claimable_reward[_accounts[u]] = 0;
            IERC20(cvx).safeTransfer(_accounts[u], receiveable);
            bal = bal - (receiveable);
        }
    } else {
        cvx_claimable_reward[_accounts[u]] = receiveable;
    }
    cvx_reward_integral_for[_accounts[u]] = cvxRewardIntegral;
}

The related code from the _calcRewardIntegral() function has the receivable calculation inside the if (_isClaim) code branch to save gas if _isClaim is false.

if (_isClaim || userI < rewardIntegral) {
    if (_isClaim) {
        uint256 receiveable = reward.claimable_reward[_accounts[u]] +
            ((_balances[u] * (uint256(rewardIntegral) - userI)) / 1e20);
        if (receiveable > 0) {
            reward.claimable_reward[_accounts[u]] = 0;
            IERC20(reward.reward_token).safeTransfer(_accounts[u], receiveable);
            bal = bal - receiveable;
        }
    } else {
        reward.claimable_reward[_accounts[u]] =
            reward.claimable_reward[_accounts[u]] +
            ((_balances[u] * (uint256(rewardIntegral) - userI)) / 1e20);
    }
    reward.reward_integral_for[_accounts[u]] = rewardIntegral;
}

This optimization would save gas each time _checkpoint() is called because _checkpoint() sets _isClaim to false and doesn't enter the if(_isClaim) branch.

Recommended Mitigation Steps

Modify the _calcCvxIntegral() function to place the receiveable calculation inside the if (_isClaim) code branch.

GalloDaSballo commented 2 years ago

You save gas on all the operations you don't do, nice finding