batchDeposit()
and batchWithdraw()
leave undistributed, unaccounted dust within the Batcher
contract
Description
The users of the Batcher
contract use the depositFunds()
function to deposit stakeable tokens into the batcher. The keeper of the Batcher
contract uses the batchDeposit()
function to merge several user deposits, send the users' stakeable tokens to the vault, receive LP tokens from the vault, and distribute them among the users.
The users of the Batcher
contract use the initiateWithdrawal()
function to deposit LP tokens into the batcher. The keeper of the Batcher
contract uses the batchWithdraw()
function to merge several user withdrawals, send the users' LP tokens to the vault, receive stakeable tokens from the vault, and distribute them among the users.
Here's how batchDeposit()
distributes LP tokens:
for (uint256 i = 0; i < users.length; i++) {
uint256 userAmount = depositValues[i];
// Checks if userAmount is not 0, only then proceed to allocate LP tokens
if (userAmount > 0) {
uint256 userShare = (userAmount * (lpTokensReceived)) /
(amountToDeposit);
// Allocating LP tokens to user, can be calimed by the user later by calling claimTokens
userLPTokens[users[i]] = userLPTokens[users[i]] + userShare;
++totalUsersProcessed;
}
}
The code that distributes stakeable tokens in the batchWithdraw()
function is analogous.
Consider the following scenario (using the batchDeposit()
function as an example):
Three users deposit 1 USDC each.
The batcher exchanges the 3 USDC for 2 LP tokens.
Each user receives 0.666666 LP tokens; 0.000002 LP tokens stay within the batcher as unaccounted dust.
The Batcher
contract provides no way to withdraw this dust.
There is an analogous issue in the batchWithdraw()
function.
Impact
Unaccounted, undistributed, and unreclaimable dust accumulates within the Batcher
contract.
Recommendations
Consider
introducing 1) two dust counter variables: one for stakeable tokens and another for LP tokens; and 2) a dust withdrawal function.
modifying the
batchWithdraw()
andbatchDeposit()
functions so that they immediately distribute the dust among some of the users.L!\footnote{This introduces additional gas costs.}
modifying the
sweep()
function so that it allows the governance to withdraw partial amounts and use that to withdraw the dust.
Remediation
The issue has been acknowledged by the Brahma team.