Summary
withdraw
function in LendingPool contract is defined as follows:
function withdraw(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
if (withdrawalsPaused) revert WithdrawalsArePaused();
ReserveLibrary.updateReserveState(reserve, rateData);
_ensureLiquidity(amount);
(uint256 amountWithdrawn, uint256 amountScaled, uint256 amountUnderlying) = ReserveLibrary.withdraw(
reserve,
rateData,
amount,
msg.sender
);
_rebalanceLiquidity();
emit Withdraw(msg.sender, amountWithdrawn);
}
We can see that a Withdraw
event with 2 keys is emitted.
The problem is that ReserveLibrary.withdraw
will execute the following code:
function withdraw(ReserveData storage reserve, ReserveRateData storage rateData, uint256 amount, address recipient)
internal
returns (uint256 amountWithdrawn, uint256 amountScaled, uint256 amountUnderlying)
{
if (amount < 1) revert InvalidAmount();
updateReserveInterests(reserve, rateData);
(uint256 burnedScaledAmount, uint256 newTotalSupply, uint256 amountUnderlying) = IRToken(
reserve.reserveRTokenAddress
).burn(
recipient,
recipient,
amount,
reserve.liquidityIndex
);
amountWithdrawn = burnedScaledAmount;
updateInterestRatesAndLiquidity(reserve, rateData, 0, amountUnderlying);
emit Withdraw(recipient, amountUnderlying, burnedScaledAmount);
return (amountUnderlying, burnedScaledAmount, amountUnderlying);
}
A second Withdraw
event is emitted, which is different as it contains 3 keys.
Vulnerability Details
The problem arises because each time a user executes a withdrawal, 2 different Withdraw
events are emitted, which can be misleading.
Impact
The impact of this issue is low as it leads to double Withdraw
event emission with 2 different Withdraw
events, which might cause front-end integration issues.
Tools Used
Manual review
Recommendations
Make sure to emit only one of these 2 events.