PancakeSwap 🛠️ Developing a Hook in PancakeSwap v4 - ETHGlobal Brussels 2024
ETHGlobal·Wed, Oct 9, 2024, 12:00 AM
Join Chef Mist, from PancakeSwap team, in this workshop and learn how to go develop a hook in PancakeSwap V4. This workshops anticipates ETHGlobal Brussels, a 3-day hackathon happening from July 12 to 14, 2024, bringing together the most skilled web3 developers, designers and product builders from all around the globe for a weekend-long adventure to advance the Ethereum ecosystem! ---------------- Follow us: x.com/ethglobal Website: https://ethglobal.com Email us at: hello@ethglobal.com
Transcript
on developing a hook in P V4 I'm Chef miss a smart contract death with the team if you miss the talk on P V4 earlier it's recommended go through the developer docs you can find them under if Global Heaton Resources with that let's get started bank4 V4 has a three layered architecture on the left is the accounting layer which has a contract called f. so where all the tokens across all the pools are stoed in a single contracts by V3 the because each pool has own separate pool contracts each pool contract store its own tokens V is responsible for processing net settlement with the callers it reduces the gas cost significantly through flash accounting with transition storage in the middle we have the amm type in V3 we only have the concentrated liquidity amm type and it wasn't possible to extend V3 with new amm type so in V4 we made a choice to make it extendable if there's a new amm type it's now possible to develop a new pool managers based on their type and added in V4 without protocol re-implementations leg V4 will be launched with two amm type one being the contential liquidity and the other being the liquidity book or known as The Bean pool we'll go through a difference of these two pool type in the next slide on the right is the hook layer this is where we'll focus on today hooks allow you the developer to further extend the pool functionalities through callbacks which is shortly overall through the use of single contracts and Flash accounting having all pools in one pool managers and one V contract for accounting layer V4 is highly gas optimized over V3 so let's talk about the difference between these two pools for consal liquidity if you are familiar with Unis V3 it is similar basically LPS at liquidity at a specific price range because the liquidity concentrated in a price range it provides more Capital efficiency to the LPS and better price execut solutions to the Traders compared to V2 where legality was spread across the entire price range from zero to Infinity on the right is the bin type which follows x + y = k within a bin when you add liity to the bin type liquidity is added in a separate bin in a stack manner for example for if usdc assume liquidity for if at 2900 is this bin 2950 is this bin 3,000 is this bin 350 is this spin when and assume um if is 3,000 now when user is trying to buy if they will swap usdc for if in this bin and if there's sufficient liquidity to execute the entire order with this this Bean the swap will have a single price execution with zero trading slippage so that's one benefit of The Bean type liquidity pool however if there's not enough liquidity in this bin the swap will cross over to the next bin that's where the price impact will happen as the if price would jump from 3,000 to 350 in our dogs you'll be to find more details on this two pool type and a scenario which one may be a better fit for both Traders and liquidity providers next what are hooks think of hooks as executing corx doing transactions there are 10 possible callbacks before and after five key actions which happen in amm the key actions include pool ination swap liquidity related and donate you define a callback required during pool initializations and they are immutable to ensure that the pool behavior is consistent for example if you define a pool with before swap cback only you can add after swap cacks down the road you have to recreate a new pool with both before and after swap permissions what can you do in a callbacks some of the ideas they come out with are swap fee discounts limit orders custom oracles we're looking forward to see what you might in the Heaton so this is an example of a sequence diagram of a users performing a swap to illustrate how a hook is being caught on the left you can see the users interacting with the swaps so the first thing is the swap routers will CAU a f to get a lock next the SW routers after getting a lock will call Pool managers. Swap this is where the pool managers will check if the hook has before swap registered if it has it will then call hook the before swap after that the pool managers will continue to perform the swap with his own C pool Library when that's done it will then check if after swap is set and call the hook if it is when a pool managers call the hook the hook can perform any logic since one or even revert to prevent a swap in the demo later we will see an example of what the hook can do in the corex after which the pool managers will update a balance Delta to the Vault and return a balance Delta to the routers balance Delta represents the amount in and amount out for the swap if you recall the fult being the accounting layer the S RS would then need to take and transfer token in and out of default next let's do a step-by-step guide on how to develop a hook for a seal po some background in package ecosystems there's a token called V Ki this token serve a crucial role in the governance users can use VC to vote and they get V kick by locking kick so in our example hooks if the users hold V kick we want to give them an advantage in the first hour which is 0% s fee and bord 5% token one when they do a exact in token zero for token one all right let's start with some the first before the implementations to implement 0% s fee we have to first store the default s fee one of the ways to do this is when a pool is being initialized we include the default swap fee in the hook data this hook data will then flow to the after initialized callback where the hook can decode to get a s Fe and store in the hook so once the S Fe is being stoed the pool managers can call hook the before swap so now we start the swap fee for the pool whenever a swap happens pool managers will first call hook to before swapped and in before swaps there are three return value expected one is the bik for selectors which is the before swap selectors for pool managers to know is fine next we have the before swap Delta this is where hooks can take a fee or give token from either token in or token out however in our case as we want to give 5% more token out but the users owning specifi number of token in at this stage we do not know number of token out so we can't make use of before swap delas to give 5% more token out however if we want to give a specified number such as 500 more token out then before swap Delta can potentially be used Third Return value LPC overr right this is where we use to override the swap fee to 0% if the users is V kick holders next to implement 5% more token one when user swap EXA in token zero token one we can make us of after swap callbacks when a pool managers call hook. after swap it includes balance Delta in the parm which indicates how much token one is the users getting from the swap we can then use of this param to calculate how much extra token want to give to the users in after swap there are two return values B for which is the after swap selectors for po managers to know is fine in one to unspecified currencies unspecified basically mean the other side of the token for example when you swap Atta in token zero for token one because it's specified number of token zero then token one is unspecified in our case since we only reward 5% more token one when just swap exact in token zero token one we can make use of unspecified currencies to return extra token one that users will get lastly before return the value the H need to transfer 5% token one to the Vault so that the accounting in Vault is neted as the users will take that 5% so that's the general idea with that being said let's get started so first you want to come to this hook template repository click use this template so you create a new repost this template after that you clone install Foundry as a prerequisite and then you run for install and Forge test to verify everything is running so on my local setup I have already done all the above so if everything is working when you run Forge test you should see this four Test passing if that's happen that means everything is fine so let's go through the code in this report three we'll focus more on the source and the T folders so if you notice there are two folders inside there pool Bean pool C so this really depends on the hooks you're developing for if you're developing a hook for the Bean type you go to the PO Bean folders if you're developing a hook for the cell types you come to the PO C folders since this Workshop is about concentrated liquidity hooks let's focus on the PO C folders let's start with the base hooks base hooks basically a contract which you inherit For Your Hooks it contains all helper methods you need as well as the Callback methods you need to override if you're using these callbacks for example you can see all the before after related a callbacks next counter hooks is basically example we created it's a simple hooks that counts number of a hook callback is being caught so over here because we want to calculate keep track of how many times the Callback been C we create a Ming and next this method get hook regation B map is a method that you must Implement to Define what kind of callbacks you need in this case because we only need before and after liquidity and before and after swap we set those as true the others we set as force and then finally for each callback that you need you need to implement ment the method so we have four callbacks we have four methods over here and the implementation straightforward we just simply add the mapping Plus+ so uh that's counter hooks let's move on to the test so writing test is pretty straightforward we have have a see how test you to help you in setting up the test first thing you see in the set of methods we have this method called deploy contracts with tokens so this comes from C test use what it does is that it helps you to create the Vault the pool manager contracts the Pere contracts as well as the approval required and then we also have helper method to help you to add liquidity if you need to and next we create a hook and next we create a pool key so this actually determines what the pool is what currencies the hook address address zero if there is no hook the pool managers which is the sale pool managers address the Fe in this case is a 0.3% fixed fee pool and lastly the parameters where we Define the callbacks needed as well as the T spacing and finally we initialize the pool the key the price and H data in this case uh we passing new by zero because we have nothing to pass over to the hooks so for the test assertion is pretty straightforward we can test liquidity callbacks before before we add liquidity we check the counter is zero ality we check the counter is now one for hook being caught swap callbacks likewise we first ality to the pool we assert before and after swap count is zero perform a swap assert before and after swap count is one so that's a very simple example of how to do a hook test so with that being said uh let's go back to the slide to recap uh the implementation ideas for our case for demo so the first thing we need is to store a default swap fee with make us after initialize and to give 0% swap Fe we use before Swap and then finally to give 5% more token one we'll use after swaps so there's three callbacks that we need to implement so let's go back to the code I will just copy and paste the existing file and rename it as V KCK membership hooks let me just copy paste the descriptions we don't need a mapping because we are not tracking the number of counts so I'll delete that as well we'll keep the constructors for this permission we need to update accordingly so we need after initialize we don't need before and after after liquidity so set as false we need a before and after swaps so there's also one more potion that we need which is the after swap return Delta this is because we are modifying the Deltas in after source so you notice you will see later on why how how we actually modify the delas so let's remove the before and after liquidity callbacks let's add in the after initialize and of course uh you should always put pool managers only to ensure that uh only po manases can call your callx so okay this is a good template let's start with the first implementation to store the intended s fee so if you recall we do this in after initialize so to do that we decode the hook data and then we store this value in the mapping so let's uh create a variable to actually store the mapping and also uh we need to stall the promo end date which is the first hour so I'll just write the par variable over here as well and then we set the promo end it over here spell in after initialize okay and then we return the selector to say everything is fine next in before swaps we need to return 0% swap Fe us v c so just give me a second to so the first thing we do is if the time stem is after the promo ended we return early otherwise we'll check if it just is VC holder and return the SW fee accordingly so if you notice why do we have this extra attribute LP Fe libraries is because if we recall our pool is a dynamic fee so we are trying to overwrite the swap fee so we need to pass in this flag as well to indicate that we are updating the swap fee and lastly in the after swap is where we give extra 5% tokens to the users so we can first also return early if the promo has ended and then we'll check the parameters in there to see if we need to get give the 5% more token so first we check if a swap zero for one and then whether amount specified is less than zero which actually implies token in and whether users has v kick so if all these condition are fulfilled we can then calculate how much extra token to give to users from delta.
amount one which is token one and then remember we say we need to pass the tokens to theault we call key. currency 1. settle and then return the selectors okay so let me just format the code a bit and if you recall we mentioned about vki so we also need to store the vki address in the constructors so let me just add in that and the interface and I'll add in all those Imports that we are using in this file as well LP Library currency currency settlements so this all comes from the packet before calls and lastly because we're using this Library as well so using currency settlement for currencies all right um let's try to do a forge build to ensure the compilation pass all right ex expected perum line 97 okay okay looks like compilation is passing so let's get started on writing the test so I can just copy and paste this test rename it to VK membership test call this VK membership hook test and we update the import the import VK membership Hooks and likewise in counter Hook is relc membership Hooks and we recall the constructors need a v kick so we'll add in the mock V kick address all right and next the P key so current 01 hope pool managers will remain the same but because in this pool we are manipulating the sort fee is a dynamic case so we will pass in this flag Dynamic fee flag to tell the pool managers that this pool is a dynamic fee pool and then the parameters we leave it as say this passing hope permissions and lastly if you recall in the initialize we need passing the default swap fee so we actually change it change this parameter to the one with default SW profy in there and then because we need to potentially do all the swaps and liquidity related so I would just simply before everything we add some liquidity to the pool so a swap can happen and then from at point of view we approve token zero token one to the swap routers as well as giving at least some token one for token zero for trade later and give the hook address some token one to give out extra B bonus we'll delete all the adjusting test so for this case we need to write actually at least three tests one is that uh from a nonv KCK holders perspective and then from a VC holder perspective but after promo period and for VC holders within the promo period And if all three tests actually need to do a swap so add in a stop helper methods so you see in this stop helper method what it does is that it set at least as a TX origin and then from Al perspective it perform a swap token zero token one and the amount in is one okay so for non VC holders we can just do a swap and assert the amount out so the amount out because we swapping one e should be at least 0.3% lesser because of a 0.3% s fee next for VC holder after promo period we can first uh set a block time stamp to be after the promo period and then we give Al some vake we do a soap the amount out should be similar to a non VC holders after promo period and then finally for VC holders we give Alis on V kick We Do a Swap and we can verify the amount out now is much more because of z% swy and 5% more toen out so with that let's uh do a f test for [Music] okay if everything's working fine this is what you get the tree Test passing so that comes to end of our Workshop these are the link used in the demo thank you very much
Automatic transcript — names and jargon may be misspelled.