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!
mint() and burn() functions are common for adding liquidity and removing it from the protocol. mint() will create LP tokens from the provided asset token provided. burn() will destroy the LP token and give back the original asset token. These tokens are used for portions of the pool rewards.burn() function, all of the users tokens are burned. Then, based upon the amount of tokens burned and their share in the pool, it will give them the underlying token back. The code for this is below:
uint256 burnt = _balanceOf[address(this)]; _burn(address(this), burnt); poolTokensObtained = pool.balanceOf(address(this)) * burnt / totalSupply_;
balance of the pool. This leads the pool to the pool sending more tokens to a user than they should. Crazily enough, these donated funds are not lost though! An attacker can call mint(), which will use the difference between the balance and the cached pool. So, the inflation of the amount of tokens being sent to the attacker doesn't cost them anything. balanceOf() was not vulnerable. eject() function to take all of the funds. They learned a few lessons from this warroom. First, having a pause() would have allowed them to explore their options without an attack being viable. Second, the contract is not upgradable but uses the code>eject() functionality to recover funds. By having the ability to upgrade contracts, restoring the protocol would have been much easier.