What Happened

The bug was realized in the following situation:

  1. Assuming the pool has margin enabled
  2. Assuming a margin position gets opened against this pool (custody asset or collateral asset)
  3. Assuming the pool has now positive custody and liabilities balances either on the external or native side
  4. Assuming we have ongoing swap activities on each direction against this pool (rowan -> atom, atom -> rowan, usdc -> atom, atom -> usdc, etc.)
    1. On these conditions, a swap transaction calls the function pool.UpdateBalances (here) that uses X and Y as inputs. This function is supposed to update both sides of the pool balances with the input and output of a swap. In this scenario the X and Y inputs to the function included the custody and liability values in the pool. This caused the pool’s balances to incorrectly increase by the amount of custody and liability every time a swap was executed.
    2. Even though we are dealing with a single position against atom, this process is repeated each time there is a swap activity against the atom pool
  5. The fix here changes the call to pool.UpdateBalances to use the correct X and Y pool balance values instead of including custody and liabilities amounts

Sequence of Events

Fund Remediation

Numerous individuals in the community reached out to the Sifchain team to return the extra funds they received. Thank you to these individuals who contributed to the well-being of the community. Your honesty is greatly appreciated.

Community members returned the following amounts to the Fund Recovery Wallet:

The wallet addresses for the Fund Recovery Wallet are: