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
以上がコントラクトの概観になります。次は実際にコントラクトのコードの詳細を見ていきます。
