Vault Inflation Attack
Malicious users can perform an inflation attack against the vault to steal the assets of the victim.\\nA malicious user can perform a donation to execute a classic first depositor/ERC4626 inflation Attack against the FlatCoin vault. The general process of this attack is well-known, and a detailed explanation of this attack can be found in many of the resources such as the following:\\nIn short, to kick-start the attack, the malicious user will often usually mint the smallest possible amount of shares (e.g., 1 wei) and then donate significant assets to the vault to inflate the number of assets per share. Subsequently, it will cause a rounding error when other users deposit.\\nHowever, in Flatcoin, there are various safeguards in place to mitigate this attack. Thus, one would need to perform additional steps to workaround/bypass the existing controls.\\nLet's divide the setup of the attack into two main parts:\\nMalicious user mint 1 mint of share\\nDonate or transfer assets to the vault to inflate the assets per share\\nPart 1 - Malicious user mint 1 mint of share\\nUsers could attempt to mint 1 wei of share. However, the validation check at Line 79 will revert as the share minted is less than `MIN_LIQUIDITY` = 10_000. However, this minimum liquidation requirement check can be bypassed.\\n```\\nFile: StableModule.sol\\n    function executeDeposit(\\n        address _account,\\n        uint64 _executableAtTime,\\n        FlatcoinStructs.AnnouncedStableDeposit calldata _announcedDeposit\\n    ) external whenNotPaused onlyAuthorizedModule returns (uint256 _liquidityMinted) {\\n        uint256 depositAmount = _announcedDeposit.depositAmount;\\n\\n        uint32 maxAge = _getMaxAge(_executableAtTime);\\n\\n        _liquidityMinted = (depositAmount * (10 ** decimals())) / stableCollateralPerShare(maxAge);\\n\\n        if (_liquidityMinted < _announcedDeposit.minAmountOut)\\n            revert FlatcoinErrors.HighSlippage(_liquidityMinted, _announcedDeposit.minAmountOut);\\n\\n        _mint(_account, _liquidityMinted);\\n\\n        vault.updateStableCollateralTotal(int256(depositAmount));\\n\\n        if (totalSupply() < MIN_LIQUIDITY) // @audit-info MIN_LIQUIDITY = 10_000\\n            revert FlatcoinErrors.AmountTooSmall({amount: totalSupply(), minAmount: MIN_LIQUIDITY});\\n```\\n\\nFirst, Bob mints 10000 wei shares via `executeDeposit` function. Next, Bob withdraws 9999 wei shares via the `executeWithdraw`. In the end, Bob successfully owned only 1 wei share, which is the prerequisite for this attack.\\nPart 2 - Donate or transfer assets to the vault to inflate the assets per share\\nThe vault tracks the number of collateral within the state variables. Thus, simply transferring rETH collateral to the vault directly will not work, and the assets per share will remain the same.\\nTo work around this, Bob creates a large number of accounts (with different wallet addresses). He could choose any or both of the following methods to indirectly transfer collateral to the LP pool/vault to inflate the assets per share:\\nOpen a large number of leveraged long positions with the intention of incurring large amounts of losses. The long positions' losses are the gains of the LPs, and the collateral per share will increase.\\nOpen a large number of leveraged long positions till the max skew of 120%. Thus, this will cause the funding rate to increase, and the long will have to pay the LPs, which will also increase the collateral per share.\\nTriggering rounding error\\nThe `stableCollateralPerShare` will be inflated at this point. Following is the formula used to determine the number of shares minted to the depositor.\\nIf the `depositAmount` by the victim is not sufficiently large enough, the amount of shares minted to the depositor will round down to zero.\\n```\\n_collateralPerShare = (stableBalance * (10 ** decimals())) / totalSupply;\\n_liquidityMinted = (depositAmount * (10 ** decimals())) / _collateralPerShare\\n```\\n\\nFinally, the attacker withdraws their share from the pool. Since they are the only ones with any shares, this withdrawal equals the balance of the vault. This means the attacker also withdraws the tokens deposited by the victim earlier.
A `MIN_LIQUIDITY` amount of shares needs to exist within the vault to guard against a common inflation attack.\\nHowever, the current approach of only checking if the `totalSupply() < MIN_LIQUIDITY` is not sufficient, and could be bypassed by making use of the withdraw function.\\nA more robust approach to ensuring that there is always a minimum number of shares to guard against inflation attack is to mint a certain amount of shares to zero address (dead address) during contract deployment (similar to what has been implemented in Uniswap V2).
Malicous users could steal the assets of the victim.
```\\nFile: StableModule.sol\\n    function executeDeposit(\\n        address _account,\\n        uint64 _executableAtTime,\\n        FlatcoinStructs.AnnouncedStableDeposit calldata _announcedDeposit\\n    ) external whenNotPaused onlyAuthorizedModule returns (uint256 _liquidityMinted) {\\n        uint256 depositAmount = _announcedDeposit.depositAmount;\\n\\n        uint32 maxAge = _getMaxAge(_executableAtTime);\\n\\n        _liquidityMinted = (depositAmount * (10 ** decimals())) / stableCollateralPerShare(maxAge);\\n\\n        if (_liquidityMinted < _announcedDeposit.minAmountOut)\\n            revert FlatcoinErrors.HighSlippage(_liquidityMinted, _announcedDeposit.minAmountOut);\\n\\n        _mint(_account, _liquidityMinted);\\n\\n        vault.updateStableCollateralTotal(int256(depositAmount));\\n\\n        if (totalSupply() < MIN_LIQUIDITY) // @audit-info MIN_LIQUIDITY = 10_000\\n            revert FlatcoinErrors.AmountTooSmall({amount: totalSupply(), minAmount: MIN_LIQUIDITY});\\n```\\n