# Loss of precision leads to under-collateralized

PoolTogether vault's exchange-rate calc uses yieldVault.maxWithdraw() which rounds down 1 wei, falsely flagging the vault as under-collateralized and blocking deposits.

- Payout: Contest reward
- Severity: medium
- Program: PoolTogether
- Credited: bin2chen
- Disclosed: 2023-09-27
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-pooltogether-findings/issues/143
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-pooltogether%3AM-22
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity vuln:accounting-error vuln:dos vuln:precision-loss

**Target:** ERC4626 yield vault exchange-rate / collateralization check
**Root cause:** _currentExchangeRate() derives withdrawable assets from _yieldVault.maxWithdraw(), which rounds shares down, so a 1 wei shortfall makes the computed rate fall below _assetUnit and trips under-collateralized mode.
**Steps:**
1. Deploy non-exclusive yieldVault; seed it with 333e18 and donate 0.1e18 profit.
2. Alice deposits 100e18 into the PoolTogether vault.
3. Observe yieldVault.maxWithdraw(vault) returns 99999999999999999999 (1 wei short).
4. vault.isVaultCollateralized() returns false, blocking further deposits.
**How found:** Reasoned that any non-exclusive ERC4626 yield vault rounds shares down on maxWithdraw, so the exchange-rate comparison against _assetUnit would be off by 1 wei; confirmed with a Foundry PoC.
**Insight:** When comparing a vault's maxWithdraw() against total supply to derive an exchange rate, account for ERC4626 round-down dust; a 1 wei deficit can flip a collateralization boolean and DoS deposits.
