Resources

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!

APWine Incorrect Check of Delegations Bugfix Review- 880

ImmunefiPosted 3 Years Ago
  • APWine protocol is used to tokenize future fields. This is done by storing an Interest Bearing Token (IBT). Or, any other asset yield bearing asset in a smart contract with a Future Yield Token (FYT) in exchange.
  • The smart contract receives the yield from the assets directly. However, the FYT holders are the only ones allowed to withdraw the yields. The division of these yields is done via Principal Tokens (PTs). The FYT to PT is a 1 to 1 ratio.
  • In the ERC20 implementation, there is a function called _beforeTokenTransfer that does some validation steps when transferring out yield to an externally allowed entity. After the transfer occurs, there is an if statement to update the state of the contract.
  • This if statement confirms that the from and to are neither 0x0 or the vault contract itself. Is it possible to perform the transfer without updating the state?
  • When burning (removing) a token, the standard says that these tokens should be transferred to the zero address. However, there is usually a hook that prevents the sending of tokens to this address, which is what the vulnerable code it trying to do.
  • This becomes a problem when _burn is called. When the code is called with _beforeTokenTransfer(account, address(0), amount), the address is sent to zero. In particular, delegated funds being removed do not update the main state. This means we can arbitrarily increase the delegated funds!
  • To exploit this, we need to perform the following steps:
    1. Deposit money into the FutureVault vault.
    2. Create a fresh account (to bypass a sanity check) and delegate some funds to a smart contract address.
    3. Call withdraw to redeem on Principal Tokens for the interest gained. This works because the redeem balance for a user compared to their delegated amount is not run.
    4. Repeat these steps multiple times.
    5. Generate yield from the inflated delegation amount.
    6. Redeem a bunch of money!
  • To fix this vulnerability the delegation funds amount is put into the _withdraw function. Overall, great bug that was from the over-reuse of code. ERC20 is hard to implement correctly with all of the custom logic needed for specific applications.