This is a detailed writeup of how UpDown works.
- Epochs last a fixed number of blocks
- Depositing gives you 100x Ups and 100x Downs
- There is a balancer pool to exchange ups and downs
- At the end of each epoch take the difference in price from the beginning of the last epoch and rebase the losing side down and the winning side up by the percentage of the price change.
- For example if the price changed 10% then reduce the downs by 10% and increase the ups by 10% (and vice versa)
In this example we will use a 1 week timeframe using DAI as the payout token, and ETH/USD as the price feed. Timeframes are actually denominated in blocks and so we will use 13 second block time and get (1 week * 7 days * 24 hours * 60 minutes * 60 seconds) /13 = 46,523 blocks. This period of time is known as the Epoch. UpDown uses a price oracle to determine prices.
A single pool in UpDown consists of 3 contracts. The OptionPool which is the main contract that regulates rebasing and handles deposits and settlements. The OptionPool creates 2 ERC20 tokens at initialization: Up tokens and Down tokens.
In this example, UpDown starts at block 1000 and lasts 46,523 blocks ( as described above ).
At block 1000 the pool starts and the `epochStartPrice` is determined by calling the oracle.
At any time from block 1000 to block 47522 anyone may deposit Dai into the OptionPool.
The depositor gets 100 Up tokens and 100 Down tokens per unit of dai. At the end of any Epoch 200 tokens of up *or* down (or combination of the two) may be redeemed for 1 unit of dai.
At block 47,523 the price is recorded again from the oracle and two times the percent change in price from `epochStartPrice` is used to rebase the Up tokens and the Down tokens in the pool.
For instance, if ETH/USD went up 10% (say from $1000 to $1100) then the depositor would have 120 Up tokens and 80 Down Tokens. If ETH/USD went *down* 10% (from $1000 to $900) then the depositor would have 120 Down tokens and 80 Up tokens in their wallet.
The depositor can use balancer to exchange up tokens for down tokens in order to take a position on the increase or decrease of price. For instance, Alice could exchange all of her downs for ups giving her 200 ups. If the price of ETH increased 10% she would have 240 ups (which is worth 1.2 Dai). She has increased her value 20% even though ETH has only increased 10%.
The new price at block 47,523 is the `epochStartPrice` of the next Epoch which will last for another 46,523 blocks.
At any time during an Epoch a depositor may call `settle` which will lock their account from transferring any ups or downs or making any additional deposits. They may liquidate (and thus unlock) their account at the next epoch.
At any future Epoch (any Epoch after the one in which `settle` was called) the depositor may call `liquidate` and that will convert their tokens back into the payoutToken (in this case, Dai).
The protocol will incentivize liquidity on Balancer for the up/down pairs.
UpDown uses a key feature of balancer: weight adjustment. The rebases adjust the balance of the liquidity pool and so the weights need to be adjusted as well during rebase or else the pool is subject to relatively large arbitrage opportunities. UpDown mitigates this by atomically updating the weights in the Balancer pool.
Every OptionPool is based on an epoch and the price change is calculated from the first block in the epoch to the last. You may only withdraw your funds at the end of an Epoch.
This is the token which is put into the pool and is received at settlement. In the above example that would be Dai.
The OptionPool tracks the price of this asset (ETH in the case of the above).
ERC20 compatible tokens which are rebased at the end of an Epoch based on the price change of the underlying asset (ETH in our case). At the end of an Epoch, the percent change (times two) of the Underlying Asset is calculated. If the price went up, then up tokens are rebased to a higher amount in each wallet and down tokens are rebased to a lesser amount in each wallet. Vice-versa for a down price change.
A settlement is created at any time during an Epoch. It allows a depositor to cash out of the pool. They have to wait until the end of the epoch during which they call `settle`. For example, if a depositor calls settle in the above example on block 1001, they have to wait until block 47,523 in order to liquidate. If the depositor calls settle on block 47,522, they still have to wait until 47,523.
Liquidate is called after calling settle in order to get PayoutToken (Dai in the example) back. 200 Ups or Downs (or combo of both) buy you one unit of PayoutToken.