TL;DR - Final formula is at the end. It would be great if someone can verify that I didn't make any mistakes.
If we exchange token x
for token y
, as per the constant product formula:
x * y = k
Let a
be the amount of x
we are exchanging to get b
amount of y
. Therefore:
(x + a) * (y - b) = k
The execution price of the trade, by definition, is just b / a
.
If our target execution price is e
, then b / a = e
=> b = ea
Therefore:
(x + a) * (y - ea) = k
But x * y
is also equal to k
, therefore:
x * y = (x + a) * (y - ea)
Now we can just rewrite the equation to get a
in terms of the other variables.
x * y = x * (y - ea) + a * (y - ea)
xy = xy - eax + ay - ea^2
- eax + ay - ea^2 = 0
-ea^2 + a(y - ex) = 0
We know a
is not zero, else the price would be undefined which is not possible. Because a
is not zero, we can safely divide across by a
:
-ea + y - ex = 0
Now a few more slight adjustments:
ea = y - ex
a = (y - ex) / e
a = (y / e) - x
So this is the final formula:
a = (y / e) - x
where a
is the maximum amount we can trade to get an execution price of e
or better, and x
and y
are the number of input and output tokens in the pool before the trade respectively.
TEST CASE - where 1 ETH is worth 2,000 USD
x = 100 ETH
y = 200,000 USD
e = 1,950
a = (y / e) - x
= (200,000 / 1,950) - 100
= 2.564 ETH
(It would be great if someone can verify if this answer is correct)
As per the constant product formula,
x * y = k
where x
and y
is the quantity of two different tokens in the pool.
When we trade a
amount of the first token for b
amount of the second token, the constant product formula must be maintained, therefore:
(x + a) * (y - b) = k
The instantaneous price p
of a pair is defined as the ratio of the two assets in the pool, i.e.
p = (y - b) / (x + a)
With some rearrangements, we get:
p(x + a) = (y - b)
We can then substitute this into the constant product formula:
(x + a) * p(x + a) = k
p(x + a)^2 = k
(x + a)^2 = k / p
x^2 + 2ax + a^2 = k / p
Of course k
is just equal to x * y
, therefore:
x^2 + 2ax + a^2 = (x * y) / p
Using symbolab we find out:
as long as a
is not zero.
TL;DR:
a = sqrt(pxy)/p - x
where p
is the target price to be maintained and x
and y
are the quantities of the two tokens in the pool before the trade takes place.
(I should still verify that I didn't make any mistakes here).
TEST CASE
X = 100 ETH, Y = 200,000 USD, P = 1950
a = sqrt(1950*100*200,000)/1950 - 100
=> a = ~1.274
This seems right, because it is roughly half of this similar question's answer.
Calculating this in solidity
It is awkward to calculate this in solidity.
Here is some sample code (please test this code before use in production, and also make sure it suits your needs):
function sqrt(uint x) returns (uint y) {
uint z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}
function foo() {
// pn => price numerator
// pd => price denominator
uint a = (sqrt((pn*x*y)/pd)*pd)/pn - x;
// or in human readable terms:
uint inputAmount = (sqrt((priceNumerator * inputReserve * outputReserve) / priceDenominator) * priceDenominator) / priceNumerator - inputReserve;
}
Best Answer
You will lose money. Here's why - Since most liquidity pools do not have external oracles to tell them the price ratio between two assets, they rely on participants providing the correct ratio. If you were to, as you say in your example, deposit 1 USDT and 1 ETH into a ETH/USDT pool, you would effectively be stating that you value 1 ETH to be worth 1 USDT. This is obviously not the case, and an external arbitrageur would quickly provide 1 USDT to the pool in exchange for your 1 ETH (Or something close to this, in reality the external arbitrageur would not be able to trade for your full 1 ETH, as the USDT/ETH ratio and therefore price increases asymptotically as the amount of ETH in the pool goes toward 0).
So to answer your question - You'd put in 1 ETH and 1 USDT and a few seconds later you'd be left with a tiny amount of ETH and a couple USDT.
Edit: I initially read your question as starting a pool with this ratio, however the same logic goes if you contribute this ratio to an already existing pool. You wouldn't be lowering the price per ETH to 1 USDT in that pool, but would still be lowering it by some amount inversely proportional to the size of the pool nonetheless and be making some arbitrageur very happy.