# YaxisVaultAdapter.sol#withdraw() will most certainly fail

YaxisVaultAdapter.withdraw rounds shares down, so vault returns slightly less than _amount and the subsequent safeTransfer reverts, bricking withdrawals ~99.99% of the time.

- Payout: Audit contest
- Severity: high
- Program: yAxis
- Found by: WatchPug
- Disclosed: 2022-01-27
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-11-yaxis-findings/issues/46
- Library page: https://bugbountylibrary.com/r/c4%3A2021-11-yaxis%3AH-01
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity vuln:accounting-error vuln:precision-loss

**Target:** Solidity vault adapter contract (YaxisVaultAdapter.sol)
**Root cause:** _tokensToShares(_amount) truncates when converting tokens to shares, and Vault.withdraw recomputes amount as balance*shares/totalSupply, yielding less than the requested _amount; the adapter then transfers the full _amount from its own balance.
**Steps:**
1. Call `YaxisVaultAdapter.withdraw(recipient, amount)` as admin.
2. Adapter computes `shares = _tokensToShares(amount)` with floor division.
3. `vault.withdraw(shares)` returns `balance*shares/totalSupply` which is < amount unless pps == 1e18.
4. `IDetailedERC20(_token).safeTransfer(recipient, amount)` reverts on insufficient balance (~99.99% of simulations).
**How found:** Reasoned about rounding direction across the two-step token->share->token conversion and simulated the outcome, finding the recomputed amount is almost always below the requested amount.
**Insight:** When an adapter converts units twice (tokens->shares->tokens), floor rounding at each step guarantees the round-trip is lossy; check that the amount transferred is the measured balance delta, not the requested amount.
