본문 바로가기

:D/block chain

UNISWAP 4 : 유니스왑 V2 코드 분석(2)

 

 

UNISWAP 4 : 유니스왑 V2 코드 분석 1편 보러가기

 


UniswapV2Pair.sol

 

LP 토큰(쉐어)를 만들어내는 mint 함수

pair contract가 기록하고 있는 자기 자산의 양과 실제로 그 첫번째로 token0(1) 컨트랙트에 기록되는 자기 자산의 양이 다를 수 있다고 했음 

만약 token0(1) 컨트랙트에 있는 내 자산의 양이 더 많다 라고 하면 mint를 시켜 줘야 함

반대로 더 적다 라고 하면 burn을 시켜줘야 함. 그것을 보고 mint를 할지 burn을 할지를 정하는 것.

 

그래서 mint를 하기 위해서는 token0 컨트랙트로 가서 balanceOf를 호출해서 내 잔고를 받아옴

마찬가지로 balance1도 똑같이 함 그리고 _reserve0(1)은 지금 내가 기록하고 있는 내 잔고를 나타냄 

받아온 잔고에서 내가 기록한 잔고를 빼면 내가 받은 amount(양)가 나옴. token1에 대해서도 마찬가지

 

그럼 _reserve0, _reserve1을 가지고 _mintFee를 해서 수수료 계산을 먼저함 왜냐면 인플레이션이 됐으니까

 

만약에  _totalSupply가 0이다. 즉, 처음 이 컨트랙트에 pair를 넣는 사람이라고 하면 

LP share의 최소 단위. 즉 1 LP token의 천 배에 해당하는 돈이 burn이 됨

생성되는 liquidity는 amount0 * amount1의 루트 값. 즉 기하평균 값인데 여기에서 MINIMUM_LIQUIDITY를 뺌

 그리고 그 MINIMUM_LIQUIDITY는 address0에게 생성이 됨

그런데 address0의 소유주는 세상에 존재하지 않으므로 이 돈은 그냥 묶인 돈이 돼버림 

그러면 이 사람은 저 만큼 뺀 양의 liquidity를 가지고 가게 됨 

 

만약에 _totalSupply가 0이 아니다. 새로 생성한 사람이 아니다 라고 하면 그냥 인플레이션을 시킴 

totalSupply * (amount0 / reserve0)(분수) 만큼을 생성

근데 이제 token0과 token1 중에서 더 적은 것으로 골라서 LP token을 만들어 내는 것 

 

 

 

모든 과정이 다 끝나면 to 주소 (지금 돈을 넣은 사람)에게 liquidity(LP token)을 만들어주고 

그다음 balance 들을 업데이트 해주고

KLast, 업데이트 된 K값. 즉, 두 토큰 수량의 곱에 해당하는 K값을 새로 업데이트 해줌 

그리고 emit으로 mint 했다고 log 남김 

 

 

 

 

 

burn도 마찬가지로 다른 컨트랙트에서 잔고 정보를 받아온 다음에(balanceOf) 이 사람이 지금 태우는 liquidity의 비율에 해당하는 각각 토큰의 amount 만큼을 태우는 사람이 받게 됨 그것을 계산하는 공식 

 

 

amount0는 지금 이 컨트랙트가 가지고 있는 token0의 양(balance0) * (liquidity / totalSupply)(분수) 임

amount1도 이 컨트랙트가 가지고 있는 token1의 양(balnace1) * ((이 사람이 태우는 LP liquidity의 양) / (전체 LP token의 양))(분수) 임 그만큼을 이 사람이 받아감 그 transfer(송금)이 (line 148, 149)에 있음

그 다음에 balance0 와 balance1이 업데이트 됨 K값도 업데이트 (더 작아짐)

 

 

 

 

두 토큰을 서로 교환하는 swap 함수

 

swap을 하려면 내가 지불하는 토큰과 받는 토큰이 있으면 된다고 생각하는데 그런데 이 swap 함수를 보면 

amount0Out, amount1Out 나가는 out 토큰이 두 개임 내가 넣는 돈 in은 없고 out만 두 개가 있음 

 

플래시 론(flash loan) 이라고 해서 유니스왑에 꼭 한 토큰만 집어넣지 않는 경우가 있을 수 있다고 하면 

암호화폐 대출 서비스 Aave나 Compound 같은 그런 곳에서 토큰을 먼저 빌린 다음에 그 다음에 그 토큰을 swap하고 

그것 가지고 다른 곳에 집어 넣어 가지고 차액을 얻은 다음에 다시 Aave나 Compound에 반납하는 그런 식의 작업을 한 트랜잭션 내에서 atomic 하게 수행하는 경우가 있다고 하는데 그런 경우를 대비해서 저렇게 만들어놨다고 함 

그러면 in (amount)는 어디 있냐 in은 그냥 직접 쏨 

이 swap 함수를 실행시키기 전에 먼저 저 토큰 컨트랙트 pair 컨트랙트의 token0 이나 token1 주소에다가 먼저 교환하고자 하는 토큰을 집어 넣어야 함 그리고 나서 swap 함수를 호출함 

그렇게 되면 in은 기존에 가지고 있던 돈에서 새로 늘어난 돈을 계산할 수 있게됨 

계산한 다음에 나가는 것만 amount0(1)로 넣어주는 것 

그렇게 하는 이유를 백서상으로 보면 in에 해당하는 argument가 없으니까 돈을 누가 얼마나 보냈는지를 알 수 없다. 알기힘들다. 그래서 프라이버시를 지킬 수 있다. 라고 되어있음 

 

 

token0와 token1을 일단 보냄 저 amount0(1)Out 양 만큼 보냄 그 다음에 뭔가 데이터가 있다면 uniswapV2Call 이라는 함수를 이용해서 호출을 함 유니스왑으로 들어간 다음에 유니스왑을 실행하고 나서 다른 무언가를 실행하게 만들 수가 있음 그럴 때 저 data에다가 이제 뭔가 데이터를 가지고 와서 이 함수로 부를 수 있음 

(ex. Aave나 Compound에 대출을 상환하는 코드) 

그리고 이 사람이 돈을 넣었는지를 확인하기 위해서 밸런스를 받아옴 

 

 

밸런스를 받아온 다음 in을 계산함 새로운 balance를 봤을 때 원래 가지고 있던 reserve에서 지금 나간돈(내가 다른데 보낸 돈)을 뺀 것보다 balance가 크면 balance를 조정해 주는 것

근데 만약 작다면 amount가 잘못된 것. 내가 보낼 수 있는 양보다 더 크게 된 경우임 그런 경우는 그냥 0을 대입

amount1에 대해서도 마찬가지. 그 다음에 require 문이 나옴

amount0In과 amount1In이 0보다 커야지 통과임 만약에 하나라도 0이면 INSUFFICIENT_INPUT_AMOUNT (입금액이 부족함) 라고 알려줌 (돈이 덜 들어왔다~~~) 그걸 위해서 위에서 0으로 만들어주는 것

 

 

여기까지 하면 돈이 제대로 들어왔고 제대로 나갔고 call data 실행했고 그 다음에 컨트랙트가 할 일은 저 밸런스를 조정해 주면 됨 그 다음에 0.3% 수수료를 낼 수 있는지를 확인함 

확인하고 업데이트 된 balance 업데이트 해주고 swap을 했다는 걸 로그로 남기고 끝

 

 

 

입금된 토큰이 pair 컨트랙트에 담을 수 있는 토큰의 양을 넘었을 경우 그 남는 여유분을 회수할 수 있게 만들어주는 함수. 그것을 회수 안하면 K값이 지금 max로 고정되어 있으니까 로직이 망가짐 

 

sync는 skim과는 반대로 돈이 너무 적은데 토큰 간 imbalance가 생겼을 때 

그것을 다시 맞춰주기 위해서 콜을 하는 함수 

 

 

 

 

 

' :D > block chain' 카테고리의 다른 글

Moralis  (0) 2022.03.22
UNISWAP 5 : 유니스왑 V3  (0) 2022.03.18
UNISWAP 4 : 유니스왑 V2 코드 분석(1)  (0) 2022.03.17
UNISWAP 3 : 유니스왑 V2 백서  (0) 2022.03.15
UNISWAP 2 : 유니스왑의 컨트랙트 자세히 알아보기  (0) 2022.03.14