Potential Re-Entrancy Attack in the Crowdinvesting Contract
The attack requires a set of pre-requisites:\\nThe currency token should have a re-entrancy opportunity inside the token transfer.\\nThe re-entrancy can be done on a token transfer from the `_msgSender()` to the `feeCollector`, so there are not a lot of attackers who can potentially execute it.\\nThe owner should be involved in the attack, so it's most likely an attack by the owner.\\n```\\nfunction buy(uint256 \\_amount, address \\_tokenReceiver) public whenNotPaused nonReentrant {\\n // rounding up to the next whole number. Investor is charged up to one currency bit more in case of a fractional currency bit.\\n uint256 currencyAmount = Math.ceilDiv(\\_amount \\* getPrice(), 10 \\*\\* token.decimals());\\n\\n (uint256 fee, address feeCollector) = \\_getFeeAndFeeReceiver(currencyAmount);\\n if (fee != 0) {\\n currency.safeTransferFrom(\\_msgSender(), feeCollector, fee);\\n }\\n\\n currency.safeTransferFrom(\\_msgSender(), currencyReceiver, currencyAmount - fee);\\n \\_checkAndDeliver(\\_amount, \\_tokenReceiver);\\n\\n emit TokensBought(\\_msgSender(), \\_amount, currencyAmount);\\n}\\n```\\n\\nSo on the token transfer to the `feeCollector` above, the `currency` parameter can be changed by the `owner`. And the following token transfer (currency.safeTransferFrom(_msgSender(), currencyReceiver, currencyAmount - fee);) will be made in a different `currency`.\\nA possible scenario of the attack could look as follows:\\nMalicious owner sells tokens for a valuable currency. People are placing allowance for the tokens.\\nThe owner changes the currency to a new one with a much lower price and re-entrancy during transfer.\\nWhen a victim wants to buy tokens, the owner reenters on fee transfer and returns the old currency.\\nThe victim transfers the updated currency that is more expensive.
Save the currency in memory at the beginning of the function and use it further.
```\\nfunction buy(uint256 \\_amount, address \\_tokenReceiver) public whenNotPaused nonReentrant {\\n // rounding up to the next whole number. Investor is charged up to one currency bit more in case of a fractional currency bit.\\n uint256 currencyAmount = Math.ceilDiv(\\_amount \\* getPrice(), 10 \\*\\* token.decimals());\\n\\n (uint256 fee, address feeCollector) = \\_getFeeAndFeeReceiver(currencyAmount);\\n if (fee != 0) {\\n currency.safeTransferFrom(\\_msgSender(), feeCollector, fee);\\n }\\n\\n currency.safeTransferFrom(\\_msgSender(), currencyReceiver, currencyAmount - fee);\\n \\_checkAndDeliver(\\_amount, \\_tokenReceiver);\\n\\n emit TokensBought(\\_msgSender(), \\_amount, currencyAmount);\\n}\\n```\\n