People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!
_transfer function had code for figuring out the dividends for the stakers of the token. This is done with two lines of code:
_balances[uniswapV2Pair] = \
_balanceOf[uniswapV2Pair].add(contractTokenBalance);
_balances[address(this)] = \
_balanceOf[uniswapV2Pair].sub(contractTokenBalance);
if statement to trigger this functionality is trivial to trigger every time. So, an attacker can send very little FM to increase the amount owned by the uniswapV2Pair contract. This is NOT the intended functionality.skim function is for making the balances match the reserves. Without the bug above, this wouldn't matter. But, since we can desync these trivially, an attacker can call this function to get the difference between the contracts.skim function being callable by anyone is very strange. Overall, an interesting exploit.