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!
borrow() function has the modifier solvent to check to see if it's above water. If it's not, then the transaction will revert. This is compared against the exchangeRate. Of particular importance is that this variable is mistakenly NOT upgraded in this function call.liquidate, the updating for the exchangeRate is done in the beginning of the function. If two prices are different between withdrawal and deposit, this can be a major case for exploitation.borrow function was 250 * 10^27. On the liquidate function the exchange rate was 328 * 10^27. By borrowing at one rate then liquidating at another, they were able to make a huge profit off of this. I'm guessing that the hacker was sitting on a large price difference for a while in order to exploit this bug.