유니스왑

이한길·2023년 2월 8일
0

디파이

목록 보기
6/6

1. 유니스왑


유니스왑(Uniswap)은 현재와 같은 모습의 탈중앙화 거래소의 시초이자 현재도 탈중앙화 거래소 대표주자 중 하나이다. 유니스왑이 등장하기 전, 기존의 DEX시스템은 문제점이 많아 이용자가 적었다. 기존의 DEX시스템은 거래를 할 때마다 블록체인을 이용했는데, 트랜잭션의 완결성을 기다리는데에는 상당한 시간이 소요된다. 또한 매 트랜잭션 발생마다 수수료가 발생함으로써, 거래를 할 때마다 들어가는 시간과 비용이 중앙화 거래소에 비해 매우 컸다. 게다가 신생 DEX는 이용자가 적어 호가창이 비어있는 경우가 다반사였다. 때문에 유동성을 공급해주는 마켓메이커(Market Maker)가 필요했다.

문제가 많던 기존의 DEX시스템의 대안으로 유니스왑이 혜성같이 등장했다. 유니스왑은 자동으로 Market Price를 만드는 AMM(Auto Market Maker)를 활용했고, 여기에 CPMM 알고리즘을 사용했다. 유니스왑은 AMM을 통해 호가창 없이 시장이 원하는 가격대를 자동으로 형성했다. 또한 유동성을 공급해주는 사용자들에게 거래 수수료를 보상으로 분배했다.

유니스왑은 두 가지 토큰 쌍의 유동성 풀을 만들어, 거기에 토큰을 쌓아두고 사람들이 두 토큰을 거래할 수 있도록 한다. 유동성 풀에 토큰을 쌓아두는 사람을 유동성 공급자라고 하며, 유동성 풀에서 토큰을 교환하는 사람을 거래자라고 한다.

유동성 공급자(Liquidity Provider; LP): 유동성 풀(토큰 페어)에 유동성(토큰)을 공급해 유니스왑 생태계에 기여하는 사람. 공급자가 풀에 유동성을 공급하면, 유동성 공급의 증표로 LP토큰을 받으며, 나중에 이 LP토큰을 돌려주면 공급한 토큰들을 돌려받을 수 있다.

거래자(Trader): 스왑 서비스를 이용하는 고객. 스왑할 때마다 0.3%의 거래수수료를 부담한다.

2. 컨트랙트

유니스왑은 크게 Pair와 Factory 두 가지의 컨트랙트로 동작한다.

Pair 컨트랙트

페어 컨트랙트는 토큰A와 토큰B 두 가지 토큰의 유동성이 공급되어있는 유동성 풀이다. 유동성 공급자는 페어 컨트랙트에 일정 비율과 수량의 토큰A와 토큰B 페어를 예치함으로써 LP토큰을 받을 수 있고, 이 두 토큰의 비율은 컨트랙트 내의 CPMM 알고리즘에 의해 계산된다.

Factory 컨트랙트

팩토리 컨트랙트는 페어 컨트랙트를 조회하고 생성할 수 있다. 유동성 공급자가 어떤 토큰 페어를 예치하려 할 때 그 토큰 페어의 컨트랙트가 이미 존재하는지를 조회해서, 이미 존재한다면 그 페어 컨트랙트에 예치하도록 하고, 존재하지 않는다면 해당 토큰 페어의 새로운 컨트랙트를 생성한다.

3. CPMM

xy=kx * y = k

CPMM(Constant Product Market Maker): CPMM, 즉 상수 곱 마켓메이커는 말 그대로 두 변수 xxyy의 곱을 상수 k로 일정하게 유지함으로써 xxyy의 교환비율을 결정하는 알고리즘이다. 토큰X와 토큰Y의 페어를 교환하는 유동성 풀을 고려할때, 변수 xx는 풀에 예치된 토큰X의 수량, 변수 yy는 풀에 예치된 토큰Y의 수량이며, 이 두 토큰의 수량의 곱 xyx * y가 상수 k로 일정해야 한다.

스왑시

거래자가 자신의 토큰X를 토큰Y로 교환받으려고 할때를 생각해보자. 교환을 하려는 토큰X-토큰Y 페어에 예치된 두 토큰의 수량은 현재 각각 x0,y0x_0, y_0개이고 둘의 곱은 k=x0y0k=x_0* y_0이다. 거래자가 자신의 토큰X Δx\Delta x개를 토큰Y로 교환받기 위해 풀에 토큰X Δx\Delta x개를 공급한다. 그러면 풀의 토큰X 수량은 (x0+Δx)(x_0+\Delta x)개로 증가하게 된다. 이때 토큰X와 토큰Y 수량의 곱이 (x0+Δx)y0(x_0+\Delta x)*y_0가 되면 상수 kk가 유지되지 않으므로, 상수 k를 유지시킬만큼 토큰Y 수량을 감소시켜야 한다. 따라서 k값을 유지시키기 위해 식 (x0+Δx)(y0Δy)=k=x0y0(x_0+\Delta x)*(y_0-\Delta y) = k =x_0* y_0 를 만족하는 토큰Y의 수량인 Δy\Delta y만큼을 풀에서 빼서 거래자에게 주어서 k값을 유지시킨다. 결국 거래자는 토큰X Δx\Delta x개를 주고 토큰Y Δy\Delta y개를 교환받은 것이다.

위의 교환식을 Δy\Delta y에 대해 정리하면 Δy=y0x0y0x0+Δx=y0Δxx0+Δx\Delta y = y_0 - \displaystyle\frac{x_0y_0}{x_0+\Delta x} = \frac{y_0\Delta x}{x_0+\Delta x} 가 되며, 이는 현재 토큰X-토큰Y 풀에 예치된 토큰 수량이 각각 x0,y0x_0, y_0개 일때, 거래자가 토큰X Δx\Delta x개를 토큰Y Δy=y0Δxx0+Δx\Delta y=\displaystyle\frac{y_0\Delta x}{x_0+\Delta x}개로 교환받을 수 있다는 얘기가 된다. ΔyΔx=y0x0+Δx\displaystyle\frac{\Delta y}{\Delta x}=\frac{y_0}{x_0+\Delta x} 이는 토큰X의 토큰Y로 표시한 가격을 의미한다. 스왑 후에는 x:yx : y의 비율이 k값을 유지하며 (x0+Δx):(y0Δy)(x_0+\Delta x):(y_0-\Delta y)로 변하게 된다.

  • CPMM에서의 실제가격:

    {pˉX/Y=ΛyΔx if Δx>0pˉY/X=ΛxΔy if Δy>0\begin{cases} \bar{p}_{X/Y}=-\frac{Λ_y}{Δ_x} & \text{ if } Δ_x>0 \\ \bar{p}_{Y/X}=-\frac{Λ_x}{Δ_y} & \text{ if } Δ_y>0 \end{cases}

슬리피지

현재 거래소의 토큰A-토큰B 풀에 예치된 토큰A와 토큰B의 수량이 각각 x,yx,y개일때, 즉 거래소에서 표시되는 두 토큰의 교환비율이 x:yx:y일때 거래자가 스왑을 하면 실제로는 a:yax+a=(x+a):ya:\frac{ya}{x+a}=(x+a):y의 비율로 교환을 받게되며, 거래소에 표시되는 두 토큰의 교환비율은 (x+a):(yb)(x+a) : (y-b)로 갱신된다. 이때 거래자는 처음 원했던 교환비율 x:yx:y 와 다른 비율로 교환을 받게됨으로써, 교환하려던 비율과 실제 교환받은 비율의 차이인 슬리피지가 발생하게 된다. 즉, 거래자는 토큰A 1개당 토큰B yx\frac{y}{x}개를 교환받을 것을 기대했으나, 실제로는 토큰A 1개당 토큰B yx+a\frac{y}{x+a}개를 교환받게 되는 것이다. 이 슬리피지를 계산하면 yxyx+a=yax(x+a)\frac{y}{x}-\frac{y}{x+a}=\frac{ya}{x(x+a)} 이므로, 거래자는 스왑시 토큰A 1개당 토큰B yax(x+a)\frac{ya}{x(x+a)}개를 의도치 않게 손해보는 셈이 된다.

이 슬리피지를 줄이려면 교환하려는 물량 aa 자체를 줄이거나, 유동성 xxyy의 크기를 키워야 한다. 따라서 거래자들의 슬리피지를 줄이기 위해서는 DEX가 많은 유동성을 확보해야 한다. 또한 유동성 xxyy의 크기가 커지면, 거래소의 스왑 전후 교환비율의 차이도 줄어들기 때문에 거래에 따른 급격한 가격변동을 막을 수 있다.

페어 예치시

스왑시와 달리, 유동성 공급자가 토큰 페어를 예치하려 할 때에는 k값이 변수가 되어 재설정된다. 즉, 현재 토큰A-토큰B 페어의 수량 상태가 xy=kx * y = k 일때, 공급자가 토큰A aa개와 토큰B bb개의 페어를(단, a:b=x:ya:b=x:y) 예치를 하면 (x+a)(y+b)=k+c(x+a) * (y+b) = k+c 가 되어 k값이 증가하게 된다(c는 양수). 이때 현재 거래소 풀의 두 토큰의 수량 비율과 동일한 비율의 수량을 예치했기 때문에 예치한 후에도 이 비율은 변하지 않는다. 즉, 유동성을 공급할 때는 x:yx : y의 비율이 상수가 되고, k가 변수가 된다.

예시


그림을 예시로 하면, 현재 거래소 이더리움-오미세고 풀의 이더리움 수량 xx는 10이고, 오미세고 수량 yy는 500이며, 따라서 k값은 5000이다. 거래자는 x:y=10:500x:y=10 : 500 의 교환비율을 생각하고 이더리움 1개를 교환했다. 거래자는 오미세고 50개를 받을 것을 예상했으나, 실제로는 (10+1)(500500110+1)=5000(10+1)*(500-\frac{500*1}{10+1})=5000 이므로, 오미세고 500/11개, 약 45.45개를 받게 되었다. 슬리피지는 500110(10+1)\frac{500*1}{10(10+1)}이므로 약 4.55개가 된다.

4. 버전별 기능 변화

유니스왑v1

스왑

유니스왑v1은 이더리움을 기축통화로 사용한다. 즉, 모든 페어가 이더리움-ERC20이며, ERC20-ERC20 페어는 지원하지 않는다. ERC20과 ERC20을 교환하려는 거래자는 이더리움을 매개로 이중으로 교환을 함으로써 수수료를 이중으로 부담해야 했다. 유동성 공급자는 풀에 반드시 이더리움을 함께 공급해야함으로써 원치않는 이더리움 가격 하락의 리스크를 부담해야 했다. 이 리스크를 비영구적 손실(Impermanent Loss)이라고 한다.

LP토큰

유니스왑에서 스왑 수수료는 거래금액의 0.3%이다. 유니스왑v1에서는 스왑이 일어날 때마다 이 수수료를 모두 해당 유동성 공급자들에게 LP토큰의 비율에 비례하게 분배한다.

유니스왑v2

스왑

유니스왑v2에서는 더이상 이더리움을 기축통화로 사용하지 않고, 오직 ERC20-ERC20 페어로만 교환이 가능하게 했다. 이더리움은 ERC20기반의 랩트토큰인 wETH로 교환할 수 있다.

LP토큰

유니스왑v2에서는 거래수수료 0.3%에서 일부인 0.05%를 걷어 다른 용도로 사용을 하고, 남은 0.25%만 LP토큰 보유자들에게 분배한다.

가격 오라클

거버넌스 토큰

UNI토큰

스테이킹

profile
블록체인, 통계학, 수학, 인공지능 공부하고 있습니다

0개의 댓글