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
-
ADD:BTC.BTC:<thorAddress>
from Bitcoin -
ADD:BTC.BTC:<btcAddress>
from THORChain
The user binds their two address together, now can both withdraw symmetrically or asymmetrically.
ASYMM
-
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.
-
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.
-
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:
-
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);
}