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
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.
- The investor developer uses your flash loan code.
- They decide to borrow the money to do something then pay you back.
- They borrow the money in the flash loan, which they have to payback at the end of the call.
- The amount passed to the amount parameter is less than the flash loan amount, let's say 1 WEI, maybe a bit higher.
- The call is successful but they lose money on the flash loan call.
- So, instead of the call reverting, it is instead paid back successfully and Aave lose money, but don't realise.
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);
}