BlockBaseのエンジニアの@suhara_pontaです。
【PancakeSwap勉強会シリーズ】
前の記事ではAMMについて基本的な概念を説明しました。今回は実際にコントラクトのコードを見ていきます。
なぜUniswapではなくPancakeSwapなのかというと、PancakeSwapのほうがFarmやらPoolやら機能が多い部分があり、シリーズ化していく上でやりやすいと感じたためです。(あと実際に動かしてみるときに、gasが安いというのもあります)
LP作成とswapについては、完全にUniswap V2のコードをコピペしているだけなので、Uniswap V2の解説だと考えていただいても大丈夫です。
githubレポジトリとコントラクトの全体像
PancakeSwapのgithubにはいくつかのレポジトリがあります。今回は
- https://github.com/pancakeswap/pancake-swap-core
- https://github.com/pancakeswap/pancake-swap-periphery
が対象になります。
全体像
ユーザーがフロントエンドから触るコントラクトはperipheryレポジトリのRouterコントラクトです。Routerコントラクトを経由してcoreレポジトリのPancakeFactory.solやPancakePair.solのロジックを利用します。
ペアの作成
addLiquidity
という関数内で、pairがない場合はPancakeFactoryコントラクトのcreatePair
という関数をコールして、ペアのコントラクトをデプロイします。
流動性提供
ペア作成時と同じくRouterコントラクトのaddLiquidity
から、PancakeLibraryというperipheryレポジトリ内のコントラクトの関数を呼び出します。getReserves
でPancakePair内に存在するreserveのamountを取得し、それを元にquote
という関数でLPトークンの数量の見積もりをします。pairFor
という関数でPancakePairのアドレスを取得し、そこにそれぞれのトークンをtransferします。PancakePairのmint
が呼ばれ、userに対してLPトークンが発行されます。
流動性提供を止める(remove liquidity)
LPトークンを返還してトークンを償還する場合はRouterコントラクトのremoveLiquidity
という関数を実行します。pairFor
でアドレスを取得してユーザーからpairのコントラクトへLPトークンをtransferします。その後PancakePairコントラクトのburn
を実行して、関数内でLPトークンがburnされ、提供していたペアのトークンがそれぞれユーザーにtransferされます。
Swap
swapExactTokensForTokensという関数を実行します(ちなみに微妙に関数名が違うものは、ETHがERC20ではないのでETHとのペアを使うときに実行する関数です)。LibraryのgetAmounts
でswapで得られるトークンの量を計算します。libsレポジトリのtransferHelperを利用してユーザーからLPへtokenAをtransferします。Routerコントラクト内のprivate関数である_swap
からPancakePairコントラクトのswap
を呼んで、tokenBがユーザーにtransferされます。
まとめ
- coreとperipheryの2つのレポジトリからなる。
- 基本機能はcreatePair、addLiquidity、removeLiquidity、swap
以上がコントラクトの概観になります。次は実際にコントラクトのコードの詳細を見ていきます。