# AMM for swap
###### tags: `algorithm`
## Summary
###Swap
When swap, assum we have X token0 in pool, Y token1 in pool, when user want to swap amount token0 to token1, (pool will get user's token0 and give user token1) and keep:
X*Y = (X + Amount) * (Y - Amount_out)
### Supply/Retreive
#### Example 1:
if we supply/retreive with 1:1
Thus X:Y = 1:1
For example:
X=10000 Y=10000
amount 10
10000 * 10000 = (10000 +10) * (10000 - result)
10000 - 10000 * 10000/10010 = result
result = 10000 - 9990.00999000999 = 9.99000999
result almost equal 10 = amount
#### Example 2:
if we supply/retreive with 1:1
Thus X:Y = 1:1
X = 10000 Y = 1000
amount = 10
10000 * 1000 = (10000 +10) * (1000 - result)
result = 1000 - 999.000999 = 0.999
so result << amount
## Implement
X*Y = (X + Amount) * (Y - Amount_out)
So:
X*Y = X*Y + Amount*Y - X*Amount_out - Amount * Amount_out
Amount_out * (X + Amount) = Amount * Y
Amount_out = Y * Amount / (X + Amount)
We need profit, so final result:
Amount_out = Y * Amount * 997 / ((X + Amount) * 1000)
final final result:
Amount_out = Y * Amount * 1021 / ((X + Amount) * 1024)
**Issue for Circom...** (Resovled)
In circom swap op,
var amount = args[5];
and X is pool liq0.
We need do Y * Amount * 1021 / ((X + Amount) * 1024)
However, as circom do not have if, so all other op's input will also be run in swap op (although we do not care about the constraint result)
This means for other op, as their input arg[5] maybe 0, and pool liq0 maybe also 0 at that time.
This divide will report divided by zero error and circom will always fail.
Thus looks like we have to change it.
Solution :
In circom, just need check the (X + Amount) is bigger equal than 1 via use bigequalFE template.
If it is, do the calc.
Or out is 0 for this op.
circom divide:
out c <-- a\b
a === b*c + r
r < b