# Inflation attack by token transfer

First staker inflates wxETH exchange rate via direct xETH transfer so next staker mints zero shares, then unstakes to steal their deposit.

- Payout: Audit contest
- Severity: medium
- Program: xETH
- Found by: d3e4
- Disclosed: 2023-08-15
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2023-05-xeth#m-06
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-xeth%3AM-06
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:precision-loss vuln:share-inflation

**Target:** wxETH vault stake/unstake share accounting
**Root cause:** exchangeRate() uses xETH.balanceOf(address(this)) minus lockedFunds instead of internal accounting, so direct transfers inflate the rate; previewStake rounds down to zero shares.
**Steps:**
1. Alice stakes 1 xETH as first depositor, gets 1*BASE_UNIT/INITIAL_EXCHANGE_RATE wxETH (totalSupply=1).
2. Alice transfers `a` xETH directly to the wxETH contract, raising balance to 1+a.
3. Bob calls `stake(b)`; previewStake computes `b*BASE_UNIT/((1+a)*INITIAL_EXCHANGE_RATE)` which rounds to 0 when a>=b, so Bob gets 0 wxETH though his b xETH is transferred in.
4. Alice calls `unstake(1)`; previewUnstake returns `1*(1+a+b)*BASE_UNIT/BASE_UNIT = 1+a+b`, extracting her stake plus Bob's.
**How found:** Reading stake/previewStake/exchangeRate: noticed exchangeRate derives from raw balanceOf, so external transfers move the rate, and integer division in previewStake can round mintAmount to zero.
**Exploitation:** Front-run a victim's stake by directly transferring xETH to the vault to inflate exchangeRate, causing the victim's minted shares to round to zero while their deposit stays in the contract; then unstake the sole share to drain both deposits.
**Insight:** When a vault's share price reads token.balanceOf(this) rather than internal accounting, any direct transfer moves the rate; check whether previewStake/previewWithdraw can round to zero for the next depositor and whether the deposit still transfers in.

