---
# System prepended metadata

title: AMM for swap
tags: [algorithm]

---

# 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

















