ADD: AssymWithdraw

Current

Assets withdrawn 50:50

Desired

Assets can be withdrawn asymmetrically, equivalent to REMOVE+SWAP (in one direction).

This is also somewhat necessary for users who add liquidity from a single chain, and never want to hold RUNE or get a THORChain wallet. They can add asymmetrically, then withdraw asymmetrically, eg, ADD Bitcoin, then REMOVE just Bitcoin.

Implementation

Adding

When adding, a user can ADD symmetrically or asymmetrically:

SYMM

  1. ADD:BTC.BTC:<thorAddress> from Bitcoin
  2. ADD:BTC.BTC:<btcAddress> from THORChain

The user binds their two address together, now can both withdraw symmetrically or asymmetrically.

ASYMM

  1. ADD:BTC.BTC from Bitcoin

The user has only their Bitcoin address registered, so can only withdraw in one direction

WITHDRAWING

SYMM

If a user has registered both addresses when adding (above) they can withdraw symmetrically.

  1. WITHDRAW:BTC.BTC:10000 from either chain, withdraws 50:50

ASYMM

If a user has only registered a single address, then they can only withdraw in one direction.

  1. WITHDRAW:BTC.BTC:10000 from Bitcoin, all to be withdrawn as Bitcoin

ASYMM-OPTIONAL

If a user has registered both addresses, but wants to withdraw in a certain direction:

  1. WITHDRAW:BTC.BTC:10000:BTC.BTC from thorchain, all to be withdrawn as Bitcoin

Algorithm

share = (s * A * (2 * T^2 - 2 * T * s + s^2))/T^3
s = stakeUnits for member (after factoring in withdrawBasisPoints)
T = totalPoolUnits for pool
A = assetDepth to be withdrawn

Implemented in javascript:

function calcAsymmetricShare(s, T, A) {
    // share = (s * A * (2 * T^2 - 2 * T * s + s^2))/T^3
    // (part1 * (part2 - part3 + part4)) / part5
    const part1 = s.times(A);
    const part2 = T.times(T).times(2);
    const part3 = T.times(s).times(2);
    const part4 = s.times(s);
    const numerator = part1.times(part2.minus(part3).plus(part4));
    const part5 = T.times(T).times(T);
    return (numerator.div(part5)).integerValue(1);
}