code-423n4 / 2024-07-reserve-validation

0 stars 0 forks source link

Large Transfer Failure in StRSRP1 Contract #85

Closed c4-bot-10 closed 1 month ago

c4-bot-10 commented 2 months ago

Lines of code

https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L237 https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L337 https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/StRSR.sol#L477

Vulnerability details

Impact

The contract fails to handle large transfers correctly for some ERC20 tokens (e.g., UNI, COMP) when the transfer amount exceeds uint96. This can lead to failed transactions in critical functions such as staking, withdrawing, and seizing RSR, potentially causing a denial of service for users with large balances.

Proof of Concept

  1. stake() Function:
// Assuming rsrAmount > uint96
uint256 largeAmount = 1e30;
StRSRP1.stake(largeAmount); // This will fail for some ERC20 tokens
  1. withdraw() Function:
// Assuming rsrAmount > uint96 after unstaking
uint256 largeAmount = 1e30;
StRSRP1.withdraw(userAddress, endId); // This will fail for some ERC20 tokens
  1. seizeRSR() Function:
// Assuming seizedRSR > uint96
uint256 largeAmount = 1e30;
StRSRP1.seizeRSR(largeAmount); // This will fail for some ERC20 tokens

Tools Used

Manual review

Recommended Mitigation Steps

Create a helper function to handle large transfers by splitting them into smaller parts that do not exceed uint96.

function safeTransferWithLimit(IERC20Upgradeable token, address to, uint256 amount) internal {
    uint256 maxUint96 = type(uint96).max;
    while (amount > 0) {
        uint256 transferAmount = amount > maxUint96 ? maxUint96 : amount;
        token.safeTransfer(to, transferAmount);
        amount -= transferAmount;
    }
}

Assessed type

Token-Transfer