Lucene search

K
code423n4Code4renaCODE423N4:2022-10-PALADIN-FINDINGS-ISSUES-147
HistoryOct 30, 2022 - 12:00 a.m.

Pledge creator can increase their pledges' reward per vote without paying in edge cases

2022-10-3000:00:00
Code4rena
github.com
5
vulnerability
pledge
integer division
erc20 tokens
mitigation

Lines of code

Vulnerability details

Impact

Pledge creator can increase their pledges’ reward per vote without paying in edge cases.

Proof of Concept

When pledge creators wants to increase their pledges’ reward per vote, they must transfer an additional reward amount and fee:

uint256 totalRewardAmount = (rewardPerVoteDiff * pledgeParams.votesDifference * remainingDuration) / UNIT;
uint256 feeAmount = (totalRewardAmount * protocalFeeRatio) / MAX_PCT ;;

However, since totalRewardAmount is calculated using integer division, totalRewardAmount (and feeAmount) could be 0 in edge cases
where rewardPerVoteDiff * pledgeParams.votesDifference * remainingDuration < UNIT.
The function then go ahead and transfer totalRewardAmount, feeAmount to WardenPledge contract and chestAddress and also increase the pledge’s reward per vote without checking if totalRewardAmount or feeAmount > 0:

       if(totalRewardAmount &gt; maxTotalRewardAmount) revert Errors.IncorrectMaxTotalRewardAmount();
        if(feeAmount &gt; maxFeeAmount) revert Errors.IncorrectMaxFeeAmount();

        // Pull all the rewards in this contract
        IERC20(pledgeParams.rewardToken).safeTransferFrom(creator, address(this), totalRewardAmount);
        // And transfer the fees from the Pledge creator to the Chest contract
        IERC20(pledgeParams.rewardToken).safeTransferFrom(creator, chestAddress, feeAmount);

        // Update the Pledge parameters in storage
        pledgeParams.rewardPerVote = newRewardPerVote;

Since many ERC20 tokens does not revert when user try to send 0 amount, this means user can extend their pledges without actually transferring
award amount and fee to the WardenPledge contract.

Also because rewardPerVoteDiff does not have a minimum threshold, if desiredRewardPerVoteDiff * pledgeParams.votesDifference * remainingDuration > UNIT, the pledge owner can bypass this by calling function increasePledgeRewardPerVote repeatedly (since there is no limit in how many times you can increase reward per vote for your pledge) with a very small rewardPerVoteDiff(1 for example), and make
rewardPerVoteDiff * pledgeParams.votesDifference * remainingDuration <UNIT, increasing reward per vote each time without paying.

Tools Used

Manual review.

Recommended Mitigation Steps

I recommend before transferring reward amount and fee, do check to make sure totalRewardAmount and feeAmount > 0.


The text was updated successfully, but these errors were encountered:

All reactions