BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: low
Valid

Rounding Dust Locks Assets

Description

  • Winners should fully drain the vault after final withdrawals.

  • Math.mulDiv rounds down; without a “last user sweeps remainder” path, dust accumulates and the final withdrawer can lack funds.

// src/briVault.sol:305-314
uint256 vaultAsset = finalizedVaultAsset;
@>uint256 assetToWithdraw = Math.mulDiv(shares, vaultAsset, totalWinnerShares);
IERC20(asset()).safeTransfer(msg.sender, assetToWithdraw);

Risk

Likelihood:

  • Any time total assets aren’t evenly divisible by winner shares (most cases) dust occurs.

  • Tokens with low decimals exacerbate rounding error.

Impact:

  • Last withdrawer may receive slightly less or revert due to insufficient balance.

  • Dust builds up across tournaments, leaving stranded funds.

Proof of Concept

// 3 winners, each 100 shares, vault 1000 wei
// Each withdrawal gets 333 wei, leaving 1 wei stuck forever.

Recommended Mitigation

+ mapping(address => bool) public hasWithdrawn;
function withdraw() external winnerSet {
+ require(!hasWithdrawn[msg.sender], "already withdrawn");
uint256 shares = balanceOf(msg.sender);
uint256 vaultAsset = finalizedVaultAsset;
uint256 assetToWithdraw = Math.mulDiv(shares, vaultAsset, totalWinnerShares);
+ if (totalSupply() == shares) {
+ assetToWithdraw = IERC20(asset()).balanceOf(address(this));
+ }
_burn(msg.sender, shares);
+ hasWithdrawn[msg.sender] = true;
IERC20(asset()).safeTransfer(msg.sender, assetToWithdraw);
}
Updates

Appeal created

bube Lead Judge 19 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Dust in the contract

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!