Submitted by ScopeLift
The internal _withdraw method does not follow the checks-effects-interactions pattern. A malicious token, or one that implemented transfer hooks, could re-enter the public calling function (such as withdraw()) before proper internal accounting was completed. Because the earned function looks up the _userWithdrawn mapping, which is not yet updated when the transfer occurs, it would be possible for a malicious contract to re-enter _withdraw repeatedly and drain the pool.
The internal accounting should be done before the transfer occurs:
0xScotch (sponsor) confirmed 
Alex the Entreprenerd (judge) commented:
