TokenDrop: Re-entrancy in the claim function can cause to draining funds
If the `asset` token is making a call before the `transfer` to the `receiver` or to any other 3-d party contract (like it's happening in the `Pod` token using the `_beforeTokenTransfer` function), the attacker can call the `drop` function inside the `transfer` call here:\\n```\\nfunction claim(address user) external returns (uint256) {\\n    drop();\\n    \\_captureNewTokensForUser(user);\\n    uint256 balance = userStates[user].balance;\\n    userStates[user].balance = 0;\\n    totalUnclaimed = uint256(totalUnclaimed).sub(balance).toUint112();\\n\\n    // Transfer asset/reward token to user\\n    asset.transfer(user, balance);\\n\\n    // Emit Claimed\\n    emit Claimed(user, balance);\\n\\n    return balance;\\n}\\n```\\n\\nBecause the `totalUnclaimed` is already changed, but the current balance is not, the `drop` function will consider the funds from the unfinished transfer as the new tokens. These tokens will be virtually redistributed to everyone.\\nAfter that, the transfer will still happen, and further calls of the `drop()` function will fail because the following line will revert:\\n`uint256 newTokens = assetTotalSupply.sub(totalUnclaimed);`\\nThat also means that any transfers of the `Pod` token will fail because they all are calling the `drop` function. The `TokenDrop` will “unfreeze” only if someone transfers enough tokens to the `TokenDrop` contract.\\nThe severity of this issue is hard to evaluate because, at the moment, there's not a lot of tokens that allow this kind of re-entrancy.
Simply adding re-entrancy guard to the `drop` and the `claim` function won't help because the `drop` function is called from the `claim`. For that, the transfer can be moved to a separate function, and this function can have the re-entrancy guard as well as the `drop` function.\\nAlso, it's better to make sure that `_beforeTokenTransfer` will not revert to prevent the token from being frozen.
```\\nfunction claim(address user) external returns (uint256) {\\n    drop();\\n    \\_captureNewTokensForUser(user);\\n    uint256 balance = userStates[user].balance;\\n    userStates[user].balance = 0;\\n    totalUnclaimed = uint256(totalUnclaimed).sub(balance).toUint112();\\n\\n    // Transfer asset/reward token to user\\n    asset.transfer(user, balance);\\n\\n    // Emit Claimed\\n    emit Claimed(user, balance);\\n\\n    return balance;\\n}\\n```\\n