Skip to content

Latest commit

 

History

History
59 lines (49 loc) · 2.79 KB

023.md

File metadata and controls

59 lines (49 loc) · 2.79 KB

Massive Crimson Cougar

Medium

Repaying a borrowed amount on the WETH reserve for the specified amount will never revert when it should on a lesser value

Title: Repaying a borrowed amount on the WETH reserve for the specified amount will never revert when it should on a lesser value

https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/helpers/WrappedTokenGatewayV3.sol#L80-L82 https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/helpers/WrappedTokenGatewayV3.sol#L83

Impact

When the amount is being passed through the repay ETH function, if it is less than the repay amount then it is set to the paybackAmount as depicted below.

    if (amount < paybackAmount) {
      paybackAmount = amount;
    }

The problem is that the validation in the requirement statement then checks to see if msg.value is >= paybackAmount. But, the msg.value is essentially the amount and if it is set to one and the same in the if statement above, then this require statement will always pass when the amount is less even though it should fail and revert as depicted below.

    require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');

So, some people might get away with entering 1 WEI as the amount but still successfully pay off their loan.

POC

  1. The investor developer uses your flash loan code.
  2. They decide to borrow the money to do something then pay you back.
  3. They borrow the money in the flash loan, which they have to payback at the end of the call.
  4. The amount passed to the amount parameter is less than the flash loan amount, let's say 1 WEI, maybe a bit higher.
  5. The call is successful but they lose money on the flash loan call.
  6. So, instead of the call reverting, it is instead paid back successfully and Aave lose money, but don't realise.

Mitigation

Refactor the code with a few tweaks like setting the amount to msg.value and changing the require and if statement. A suggestion is depicted below.

  function repayETH(address, uint256 amount, address onBehalfOf) external payable override {
    uint256 paybackAmount = IERC20(POOL.getReserveVariableDebtToken(address(WETH))).balanceOf(
      onBehalfOf
    );

+   amount = msg.value;

-    if (amount < paybackAmount) {
-      paybackAmount = amount;
-    }
+    require(amount >= paybackAmount, 'msg.value is less than repayment amount');
-    require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');
    WETH.deposit{value: paybackAmount}();
    POOL.repay(
      address(WETH),
      paybackAmount,
      uint256(DataTypes.InterestRateMode.VARIABLE),
      onBehalfOf
    );


    // refund remaining dust eth
    if (amount > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount);
  }