chainlink node stakingDeFi Staking App: Code Along

wef chainlink whitepaper previsao chainlink chainlink node staking DeFi Staking App: Code Along
chainlink node staking chainlink crypto prediction DeFi Staking App: Code Along
good morning good morning how is everybody doing were just going to give it a couple of minutes here for people to show up for people to say hi so good morning in the chat gm hows everybody doing today how are we all doing as we wait for people to come in we get set up gm oh see the gms in the chat excellent excellent excellence excellent im also just finishing getting set up here myself good morning good morning good morning good morning gm gm gm lets do this yes exactly lets do this all right lets switch back to lets switch over to me hello hello good morning good morning one good morning all what is up it is 7 34 were a couple of minutes in we have a long session today we are going to be going through it today were going to be doing some amazing default weve done a ton of learning about how to build some of these protocols how to build with solidity how to use these different frameworks and now were taking that and applying this to a d5 protocol we are building were going to build live today a very minimalistic defy staking application so i hope everyones excited i hope everyones ready hope everyone has had their coffee and or wheaties because were going to be going through today and let me show you what were going to be building as long as i can pull it up here it is let me switch screens here theres nothing on my screen let me uh let me fix that there we go now theres something on my screen so this is d5 minimal im going to post a link to this in the chat here this is d5 minimal its a get repo that shows examples of minimalistic defy applications so if we go into contracts we have a lending protocol we have an options protocol a reward token a staking how to interact with a swap how to do a really minimalistic uh automated market maker like uniswap uh its a great repo to come check out and learn how to kind of build some of these minimalistic d5 protocols everything in here is based off of something from mainnet some one of these more mainstream applications and today were going to be building one of the ogs one of the original um d5 protocols which is going to be a staking application which is going to be based off of this off of synthetics so if you havent heard of synthetics synthetics its a its an app a protocol that allows you to mint synthetic assets dont worry too much about that now really cool but they also uh pioneered this staking design which is what were going to go through so what is taking a lot of people might say okay what is staking well staking is when you lock your tokens into a protocol and you gain yield uh in return so you lock a token in your protocol you gain yield in return and the tokens locked do certain stuff right so the tokens that are locked do stuff so lets create a quick read meme the staking can be locking tokens to net rewards tokens to net rewards and let me zoom in and the tokens locked will do something right so were not going to do that do something thing but maybe your protocol needs collateral maybe your protocol needs a ton of underlying money to to do some stuff right so locking your tokens can have a bunch of different um you can have a bunch of different reasons to lock tokens the reason synthetics locks these tokens is so that it can have underlying collateral to mint their synthetic assets and if thats confusing dont worry too much about that now definitely go check out the synthetics documentation if you want to learn more but thats essentially what were going to be building today um and i hope youre ready so we are going to be using uh the hard hat repo excuse me the hard hat um framework for this however if youre using brownie if youre using foundry if youre using anything else all the contracts are going to be the same right itll just be your tooling thats going to be a little bit different so were going to go through the contracts first so if youre like hey i just want the contracts great just stay for the contracts bit you dont have to stay for the tooling bit um but we are going to be working with hard at but again the uh solidity code is going to be exactly the same so with that being said lets jump into it if theres any questions before we get going oh and then i guess i should mention um for those who dont know d5 is absolutely insane one of the main use cases for um for blockchain okay cool so we got somebody saying hey what is what is d5 d5 stands for decentralized finance i just sent a link called defy llama its a tracker which tracks different decentralized finance applications um and what its one of the big major benefits to smart contracts smart contracts enable us to engage in censorship-resistant non-centralized finance so we can borrow we can lend we could swap protocols without ever having to work with the centralized intermediary so we can interact with finance we can use these financial products without a centralized intermediary and its absolutely massive and like i said since this is live i want these to i want this to be interactive i want people to ask questions um etc so before we get going z5 staking similar or the same as the earn function in binance i guess well start with a definition of what defy staking is so um im not familiar with binances earn function but its probably something similar right youre going to lock some tokens youre going to deposit some tokens and in return youre going to get a reward and theyre going to use your tokens for something right theyre going to use your tokens to lend to give out loans theyre going to use your tokens for underlying collateral or a whole bunch of different reasons yep right there non-centralized finance right so theres no single bank who can screw you over theres no lender who can screw you over its all autonomous code d5 equals decentralized finance aka future of france yes hopefully thats clear um theres some good reefs learning resources like what is uh d5 and you get some good stuff in there but lets go ahead lets get started and lets build a staking application so once again im in my visual studio code ive got a new folder called staking and were going to go ahead and get started so im going to do a little boilerplate setup with hard hat here and im going to cheat a little bit um no im not going to cheat a little bit yeah say im going to cheat a little bit for the one of my uh up and coming free coat camp videos ive been doing a lot of work on a on a hardhead edition ive just kind of been grabbing this yarn dev thing this yarn to add right here its a massive massive piece of boilerplate but its a piece of blurred plate that ive really really enjoyed using so its uh were adding a ton of dependencies here were adding nomic labs hard hat ethers hardhead deploy ethers nomiclabs hardhead nomiclabs hardhat waffle chai waffle all this stuff to set up like a hardhat project in our our repo here so if youre like whoa that seems like a lot of stuff i posted in the chat um but its basically just some boilerplate hard hat stuff and then some plugins that i really like that come with it and were going to do a little formatting its going to be good while we wait for this to uh come in any other questions we wait for this a million packages thats a million packages to be uh downloaded here also im going to add in these two dot prettiers and dot prettier is just a file to help format our code if you want to learn more about it later we can talk about that as well why defy thats more important yeah d5 uh because if you if you came to our the purpose of smart contracts right we know that the reason that were doing all this is for trust minimize agreements right having sophisticated financial products is one of those reasons for having d5 right we want to have defy we want to have be able to engage with finance without getting screwed over we want to be able to say hey you know i want to buy this thing or i want to you know invest my money and not get screwed over thats why because youre not trusting essential identity great founder your hard hat what would be better it doesnt matter pick one and go does not matter can we do npm ad with all that stuff yes you could do npm install i think it would be save dev or you just do npm install all that stuff so just instead of yarn add dash dash dev you just do yarn add and then paste that in here no problem with deprecated packages uh dont i guess a productive learning exercise for the is pythonists can be to rewrite this in brownie python yes that would be super cool so if youre here your python rewriting the the boilerplate in uh python will be cool but like i said all the contracts are still gonna be solidity so we dont have to worry about uh too much there i just installed a whole bunch of boilerplate whatever hard hat setup that you like you can use for this and lets go ahead and create our new uh file folder actually lets do uh lets do yarn hard app and well set up well just say create an empty hardhead uh config.js and great we now have a new hardhat.config were going to update this solidity version to 8.7 and were also going to update a whole bunch of stuff in here but for now well just leave it just leave a blank so now now lets actually start building some stuff so lets create a new file or folder called contracts and in here were going to create our first solidity file called staking dot sol and this is going to be our staking application before we actually get the coding stuff in here lets talk about what were going to do ill be doing this with brownie excellent can i start working on the hack joining today yes you absolutely can it also allows you to design your financial yes it does oh same oh my gosh i love all the people doing this in brownie just pick one and master it and begin yes exactly doesnt matter which framework pick one and go so lets talk about this staking application what do we want this to do what do we want this to do well we probably wanted to uh and and then were gonna go the reason were thinking about this first is we dont want to start coding right we wanted to actually um like think about what were gonna do and then actually code it so first thing were probably gonna want is people to be able to stake this is gonna be users lock tokens into our smart contract thats the first thing were going to want people to be able to do and since theyre going to want to stake theyre probably going to want to be able to do what if theyre going to lock tokens into the protocol then we probably want them to be able to withdraw which is unlock tokens and pull out of the contract were also going to want to have some type of claim reward right where users users claim users get their reward tokens at the end of the day those are kind of the three core functions that we want this to do right we want to be able people to stake tokens withdraw the tokens theyve staked and then also claim whatever reward that they are that they are due can we use natural language processing for building d5 or any other applications in near future i dont know um that sounds really cool though yes unstake unlock unstake yes exactly uh were going to call it withdraw but unstake same thing right cool and the reward were gonna have to figure out whats a good reward mechanism like whats good math or lets do it like this whats some good reward math hey those are going to be the main things that we want this to do lets jump into it we can start with steak because that should be relatively straightforward and i do want to point out too actually while that while were looking at staking stuff if any of you all are familiar with solidity by example saluted by example uh has a different version of this its slightly different but its still absolutely fantastic i highly recommend checking it out um let me paste it in there again i highly recommend checking it out if thats something that you want to um you want to work with so lets do this so were going to get started by actually coding so well do some spdx license identifier mit pragma of solidity 0.8.7 contract staking uh we did it lets even just make sure it works im gonna run yarn hardhead compile or mpx hardhead compile okay cool filing successfully okay contract staking whats the first thing that we said were going to do we said were going to make a stake function so lets make that function function state what should this take as input parameters well lets do a un256 amount right amount of tokens and then we already are running into our first question do we allow any tokens or just a specific token to be staked right if we allow any tokens were probably going to have to do a un256 amount comma address of the token that theyre staking and etc for our example here we are not going to allow any token were just going to have one token so one erc20 so just uh so yes check mark here were going to do just one specific token right if we wanted to allow any token and this is where i challenge you to do some improvements we need to do some chain link stuff to convert prices between tokens so we can always know how much value we have okay so for now were just going to do a singular a singular token and well define it someplace else and you know what why dont we just define it now so were going to do a singular token and were probably going to need to keep track of that singular token somewhere so why dont we just go ahead and do that right in the constructor so that right away were always going to know exactly what token that were going to deal with so were going to say constructor well say addresses of the staking token like this and then well create a global variable that keeps track of the staking token that were going to pass as an input parameter now we could store this as like an address public you know s staking token s stands for storage because this is going to be a storage variable uh am i lagging am i lagging here if im lagging let me know uh i saw somebody saying that im lagging hopefully im not lagging um but yeah let me know but instead of doing this as an address we know that this is the address of an erc20 and were going to want to do nope not to me okay cool uh this is going to be an address of an erc20 so instead of making this an address were going to make this an ierc20 okay so how do we actually turn this address into an ierc20 well opens that one to the rescue opens up in github oh and for everybodys whos here please be sure to take the uh the feedback form after we are finished with this session i will be sending uh not to me whos like uh we will be sending a feedback form after this uh please please please be sure to take that let us know if you liked this session if you didnt like the session etc so opens up in contracts they have a a token interface that we can use so well use their ierc20 and well just wrap around this address that we pass it so we can have we can save a global ierc20 instead of an address so we can just immediately call the functions on here grab this of course were going to need to import it so well need to do import at open zeppelin contracts slash token slash erc20 slash ie or c20.sol were going to import this now that weve imported this ier220 interface and we have it as a new type so we can do our erc20 public s staking token again were doing the s underscore to tell us as developers hey this is a storage variable it is expensive to read and write and then well just say in our constructor say s staking token equals ierc20 of staking token cool so now were keeping track and let me zoom out a little bit hopefully this is still big enough now were keeping track we only have one type of token that were going to allow people to stake and this is and were going to input that token in the constructor okay great so what we can do now in our stick function is were going to want to what were going were going to want to keep track of how much this user has staked what else are we what what else are we going to want to do were going to want to keep track of keep track of how much token we have total and what else were going to want to do well were going to want to transfer the tokens to this contract so thats it so we want to keep track of how much each user has staked right because when they go to withdraw we need to know how much theyve withdrawn so were going to have to create another global variable uh thats going to keep track of these balances were going to make a mapping that maps addresses to a un256 and uh in my code example i have it as private but just for the demo here ill just make them all public um oh okay why ierc20 so were using an ierc20 because were we were telling uh solidity that our s-staking token is of type ie or c20 now were not doing of type erc20 because we dont need all the extra baggage right so when we uh when we call functions on staking token like for example you know approve if we call approve on erc on an i or c20 the irc20 doesnt have the function actually defined how to do approve so what happens is it says hey like irc20 doesnt have it approved well im just going to call approve on whatever address you gave me if we gave it of type erc20 instead of ie or c20 right the approved function in erc20 has stuff in here right it has stuff in here uh and so thats going to be confusing to us because the stuff that we have in our proof function here might be different than the stuff in the address so we make this staking token type ie or c20 so we can call just so that we can call the functions in an erc20 and then whatever code is at that address will handle it hopefully that makes sense uh if the if the interface stuff is a little confusing just dont worry about it for now um and just any time you want to kind of like create a new type like this uh you just use the interface and dont use the actual contract so hopefully thats helpful just tell us about these different tokens like erc777 um no uh thats not uh thats not what this sessions about about different tokens were were just uh were just taking like heres two twenties so um thank you for the comments keep them rolling in so we need to keep track of how much users have staked uh mapping address to you in 256 public s underscore balances this is going to be a mapping of someones address mapped to how much they staked right so someones address from this address to how much they staked so down here were going to say s underscore balances right because its a storage um variable of message.sender equals and then we can do plus equals but im just going to be a little verbose here equals s underscore balances of message.sender plus amount so were increasing how much were keeping track of how much they staked by how much theyre actually staking here like i said were also going to want to keep track of the total supply so lets make a total supply up here so you and 256 and well just make this public s underscore total supply and this is going to keep track of how many tokens have been sent to this contract now this is a little bit redundant um but its going to make it a little bit going to make calculating rewards later a little bit easier and ill show you why so were going to say total supply equals total supply plus amount as well and then wed probably like to emit an event but for now were just going to skip that uh and then of course we need to transfer the tokens of the contract so are our staking token here has a function and again if we go to erc20 transfer from right it also safe transfer phone but it has transfer from and thats how were going to transfer our tokens so were going to say s underscore staking token dot transfer from and it takes from to an amount as input input input parameters so its going to be from whoever calls stake so message.sender 2 is going to be address this so were sending it to our staking contract that were going to deploy and for amount and transfer from is external returns a boolean perfect so we can say bull success equals that and then we can do require success comma and then just say failed if it doesnt actually work now um this is kind of what youll see in a lot of code in a lot of code out there however were going to do the slightly more gas efficient way just because i feel like doing it doesnt really matter um but instead of doing requires like that we can make custom errors at the top so typically the way you want to do custom errors is you put the contract name two underscores and then what the error is transfer failed now instead of doing require youre gonna say if its not successful thats what that exclamation mark or bang as its known if bang success revert taking transfer failed and boom thats going to do the same thing this staking function isnt done but uh for where we current for where we currently are this is doing everything that we want to do right its updating balances its updating total supply its sending us the tokens and then its reverting if any if sending the tokens fails great any questions about that so far we are going to come back and update this a little bit but for now thats essentially what we need to do all right cool next we have a stake now we need a withdrawal okay cool so theyve been able to stake the token now if later on they want to withdraw how do they do that okay great so well say function okay whats the staking underscore underscore transfer failed code yes great question so in here uh you might have seen like require success right so um our code looked like this basically be saying hey require that success is true otherwise revert the transaction and omit this failed thing here now doing that is really gas expensive because failed is a string so were saving this string on our contract which costs a lot of gas so instead were kind of doing like the almost reverse of that were saying if its not successful if bank success if its not successful revert with this custom error code that we created we made it at the top here error staking transfer failed revert with this custom error and this is way more gas efficient than doing require failed im willing to bet sometime in the near future solidity will support custom errors like im willing to bet in the future things look like this because thats way more gas efficient but right now that doesnt work so this is what we have right now where would the approval happen without approval would it transfer from revert since transfer from is called by the stake and contract not the user amazing question yes spot on if you dont call approve this will fail now our staking contract cant call approve why not why cant our state contract call approve well because our state and contract doesnt own the tokens so our state and contract cant be the one to oh yes and uh thank you for um thank you for doing that for doing npm install packing installation i type this npm install uh try to try without uh save dev try without say dev um in any case though uh so actually on the front end or the user needs to approve this themselves so our contract cant do this so the user will call approve on the erc20 token contract themselves instead of um instead of our staying contract calling approve because if you if we allowed any contract to be able to call approve then any contract could hypothetically approve any token so thats the case then should we check if its approved or not uh yes we could check if its approved however uh staking token.transfer from will fail right this will return false and then this will will revert to the transaction okay so its still going to get reverted yeah we probably could check a little bit earlier up um but were still catching whether you know were still catching it down here um but yeah you could you could check to see if its approved or not if you wanted to cool really good questions really really good questions hopefully thatll make sense any other questions those are both fantastic questions im going to keep going if you keep having questions keep dropping them in the chat thats what these live sessions are for so now function withdraw we need to pull those tokens back out well lets do unit 256 amount how many do we want to pull out make this external and lets pull these out so were going to do pretty much the reverse of what we did up here so were going to say s balances of meshes of sender equals s balances of message.sender minus amount were going to do this exact same thing with total supply except for its going to be minus amount and then were going to transfer tokens once again were going to transfer instead of transfer from if we look in here were going to call transfer instead of transfer from were going to call transfer because our staking contract now has access to the tokens when we do transfer from were saying hey we want to grab those tokens from the user when we use transfer we say we have the tokens and were going to send them so were going to use transfer instead of transfer from so were going to say bool success equals under s underscore stakingtoken.transfer message.sender amount so were going to send back were going to send those tokens back right and this is going to be the equivalent of equivalence of this we had said taking token.transfer from address this to right these these are do essentially the same right but since addre since who its coming from is us we can just use transfer right so those are going to be the same all right some questions here do we check for overflow slash underflow we are not going to do that here why because in solidity version 0.8 uh and above solidity automatically checks that uh we could actually change this to not check for that by using the unchecked keyword um but solidity automatically checks for overflow underflow in newer versions of solidity the custom error saves gas but how is it interpreted in on the evm um i forget i would have to double check actually but it definitely saves gas because ive definitely tested it uh thats why we use irc 20 instead of erc20 because we didnt want contract to approve um not quite uh we we cant we cant call a proof right we cant call approve here because we dont own those tokens so we cant call it proof if we owned the tokens we call proof but we dont so we cant hi patrick in staking function you are adding in advanced balance to the sender but the transaction can fail after that yes yes it can oh amazing amazing point so revert thats what this revert keyword so revert and require if if success is false in either one of these cases it ends up sending whats called a revert command and what revert does is revert says hey all that stuff that we did previously yeah dont do that and it reverts all these changes so you make a really good point hey patrick uh we just updated the balances in total supply but this transfer firm could fail so whats up revert will revert these changes so revert says anything youve done this transaction nope reset it that was a really good question hopefully that makes sense hold on i uh i lost my water let me let me grab it one second excuse me and were back uh hopefully that makes sense thats a really really good question okay im confused about imports and import copies structure from irs220 and github it compiles and deploys uh that with our contract that consumes more gas right can you explain more about import mechanics uh youre spot on thats exactly what it does we could if we wanted to make this super minimalistic uh instead of importing this whole irc20 we could just import the functions that we want but youre right so point did you mention that custom errors are only available in 0.8.4 and above i did not uh good point thats true 0.8.4 and above are where custom errors come in so revert basically cancels the transactions yes exactly amazing question in the front end can we call the approve function within a function not necessarily asking uh the using to approve yes so in the front end you will you will have the user call the um the approve function so the user will call the approve function on the front end but they will call the approved function on the token contract not on your staking contract does our constructor need to be formatted the same as the ier c21 uh no i dont even think this has a constructor uh irc20 doesnt even have a constructor smart contract oh well why dont we add the balance updates after the revert check to save gas that way wed save oh oh i love this question why dont we add the balance updates afterwards so why youre basically saying why dont we do this right oh i love this question okay who wants uh who wants to answer this oh it looks like somebody actually already answered you want you dont want to do that because of reentrancy attacks thats exactly why you you absolutely do not want to do that uh because of reentrancy attacks so lets pull this up so were not gonna have time to go over that here uh wheres literally by example i believe he has a reentrancy attackery yes were not going to have time to go into here this right now but if you want to learn more about reentrancy attacks i just dropped a link to it in the chat but yes you absolutely 100 want to change state before you transfer your your tokens here so great questions reentrancy dance yes okay cool so were going to transfer the so now were back to the withdraw weve updated the balance weve updated supply now were transferring the token we have bull success and the same thing here were going to say if not successful revert uh with some error that we create actually well just do transfer failed again revert staking transfer failed were going to send the tokens back if that doesnt work just revert the whole transaction and well admit event in there somewhere but you know whatever all right so stake heck its not done but we have it withdraw check its not done but we have it to claim rewards now sex effects uh its not a really question why are we using external and not public function access modifier great question so external is actually a little cheaper than public right external is a little bit cheaper to use than public because when we say external were saying hey no function inside our staking contract is going to use this stake thing so were saying only contracts or addresses or accounts outside of this contract can call this function and by doing that we save guess and thats really it i mean we could we can make it public if we wanted to um but oftentimes youll see these as external because yeah because only external uh addresses and contracts call them so okay great we have those two now lets do function time reward and heres where things are going to get a little interesting okay because we need to figure out oh theyve staked some stuff how much reward do they get for staking so we need to figure out same reward thing well make this external as well so we need to figure out how much reward do they get and this is where each implementation of staking is going to be a little bit different right because everyones going to have their own reward mechanism were going to do one of the one of the most common ones one of the most the most fundamental ones to defy where the contract is going to emit x tokens per minute or or x tokens per second and disperse them to all uh token stakers so lets say its 100 tokens per second lets say this contract sends 100 reward tokens per second and there are two tokens or excuse me theres uh theres somebody who has 50 staked tokens and somebody with 20 staked tokens and someone with 30 staked tokens well that would mean that the rewards would be say staked rewards would be 50 reward token 30 or excuse me 20 20 reward tokens and 30 reward tokens so if were giving 100 tokens per second if this is whats currently in staked this is what would happen for rewards now lets say someone comes along and stakes a hundred more tokens now for sake we have 100 50 20 and 30. right what are the rewards going to be now well since were doing a hundred reward tokens per second rewards are still only gonna match up to a hundred so the total here total equals two uh 200 now we just do some math so we say okay well 200 100 divided by 200 is going to be 50. so this first ones going to get 50. this next person is going to get 25. um this next person is going to get 10 and then uh math 15. because were gonna give out a total of 100 tokens per second so the more people stake the less rewards every person gets wow i never knew the visibility function save gas yup there you go i want to be better for gas efficiency if we make the ward one a day um why would that make it more gas efficient youll youll see uh were not going to uh yeah youll see youll see youll see one-to-one staking to reward ratio uh not quite right um and and the reason actually so some people might be asking you know why not one two one hey why not if we stake a hundred we get a hundred um and the reason is you can often just quickly bankrupt your protocol but youre gonna need enough reward token to give to your people so kind of figure out your your rate right your reward rate and just having that be constant and oh god thats its that one we save it doesnt freak out on us there we go um uh figure out your rate in that way your protocol can continue to live forever so now this is where it gets a little bit harder because were doing a lot more math here so were doing this function claim reward and what were going to need to do is first off is first off we need to figure out yeah how much reward that that we have so when we when we stake withdraw and claim reward we need to keep track of how much reward people have so in all of these functions we need to create some type of modifier or some type of math where we can update internally how much reward everybody has whenever they stake whenever they stake whenever they modify etc and then we can use that reward amount to math down here okay heres how much they they deserve so lets create a modifier ill make this up here we carry a modifier called update reward for some address account for some address user right were going to add this modifier to all of our functions now to get um this is where the math gets a little bit tricky to update the reward of each one of these users were gonna need to do a couple things so first off were gonna need to figure out okay how much is the reward per token and what is that what is the current reward for token and then were going to need to um get the last timestamp uh and were basically going to say okay between time periods of you know noon and one or whenever these uh or whenever this was last called user earned tokens right because anytime somebody stakes anytime somebody stakes the amount given out is different the amount given out is different every time somebody stakes within a time frame right so lets lets look at another example here lets say for five days um one person had 100 tokens staked hasnt claimed it or anything or actually five seconds five seconds one person i had 100 token stakes that means their total reward can be 500 tokens now lets say at the sixth second right at six seconds two persons um have 100 tokens staked each so this would mean person one is going to get what for reward theyre gonna get 550 the person two is gonna get 50. because person one got his 500 tokens for being the only one staked his or her and then person two is just going to get 50. and now going forward person two is only 50 tokens per second because theres excuse me person one is going to only get 50 more tokens per second because theres two people in here so we need to keep track we need to basically have some data structure that says okay between seconds one and five person one got 500 tokens okay at second second six on person one gets 50 tokens now and we need to continually update and continually keep track of the time so that we can have this reward correct and the math here once again it might look a little bit tricky it might look a little bit weird um but this is kind of the standard staking um staking pattern for uh for a lot of these protocols hopefully that makes sense if this makes sense let me know each user call and claim reward it updates the reward balances or some chain the keeper um yes each so we want were going to put the onus of updating uh on the users right because when they call claim rewards um uh were going to have that data structure thats going to keep track of how much they previously earned is going to get reset to zero so we want to put the onus on the users can you please show us to calculate the apr of this pool maybe when you finish the withdrawal function probably not um because uh the apr so this isnt a pool right so and and the apr is going to be incredibly variable especially variable on the token price which we havent um added into this right so um and the apr is going to change like kind of as you see here right the more people are in this pool the less your apr is going to be more people are in this pool the less the apr is going to be so i could um so if we have time we can talk more about that but im already already an hour in oh my goodness yes uh you arent sending withdrawing tokens every second its just an internal calculation the gas um yes exactly so youre not yeah okay yeah pyro you got it yes yes yes okay what if we use flexible aby according to real-time market um i mean again this is this is going to have a flexible api this isnt like a borrow and lending pool so saying like hey can we calculate what the apy is it doesnt really make that much sense should we add time period after withdrawal that locks the function so they dont spam the withdrawal um i mean if they want to spam the withdrawal and i mean theyre the one paying the gas to do that um it seems like a waste of gas to me and it doesnt really seem like itll cause that much harm sorry if youve already discussed this but what are some of the ways that contracts make money from having tokens staked to them they can be used in liquidity pools yes so that is how some contracts do use it like youll deposit tokens for liquidity pool for this one were not uh were not doing that were not actually defining in this example what these stake tokens are used for um but yeah like were were giving out a reward right and where the rewards coming from we its not really clear uh but its just kind of the setup for you know if you wanted to give out a reward heres what it would look like and then this is how the users make money is because they get these rewards can you please explain the staking math a little more yes let me just give another example so lets say time equals zero person a has 100 and person b has 50. staked staked at time equals one so say pa still has 100 staked that means theyve earned theyve earned how much theyve earned if were doing 100 tokens per second and then well just say 100 tokens second mistake 50 staked uh actually these are kind of crappy numbers lets do well do 80 and 80 and 20. so 80 staked that means theyre going to have earned how many theyre going to earn 80 and theyll have withdrawn zero right person b is gonna have 20 staked theyll have earned 20 and withdrawn zero right at time at time one so theyve been theyve had this stuff staked for one second now lets say time equals two m equals two they still have 80 staked now theyre going to have 160 earned right and this person is going to have 40 earned lets say time equals 3 now right now theyre going to have um 240 if my math is right im 240 here uh earned and withdrawn zero now lets say new person enters assuming this is time three lets say a new person enters now time equals three we now have a person c coming in the new person enters and they stake say that they stake a hundred person c comes in they stick 100 now how much do we have earned and withdrawn for everybody well person uh person a is going to have his their 240 earn 240 plus what plus 80 divided by um the total which now is going to be 200. so the new total token staked now equals 200 because we have 80 plus 20 plus 100 is 200. so 80 divided by 20 or 200 i need 200. so its going to be 40 of the 200 times 200 so oh wait no hold on um 80 divided by 200 so its going to be uh if were doing 100 tokens per second so its the 0.4 times 100 so theyre going to get 40 tokens theyve withdrawn person two same thing earned is going to be 60 the previous 60 plus the new but its going to be 20 divided by 200 times the 100 tokens per second so that equals what 10. run zero and then 100 this person here theyre going to have earned 50 right because they have half of the staking pool withdrawn is going to be zero make sense what is apr the return per period they get uh what is apr oops api what is apr annual percentage rate first the yearly interest generated by the sum thats charged to borrowers or paid to investors good questions so every time theres a withdrawal we should calculate the time diff times token per second and divide by total number stakers and add that number to everyones staked address thats how im thinking about it pretty much yes pretty much and we we only need to like calculate and do that math when somebody withdraws or or when somebodys when somebody stakes um when somebody stakes or or withdraws or claims the reward yes hopefully this is helpful here um but yes the and the only time we actually need to update a function and spend gas is when somebody um somebody stakes or somebody withdraws because when somebody withdraws we need to say hey um so lets actually lets do one more well say time equals four time equals four and well say um say pa withdrew everything well now theyre gonna have lets say they withdrew everything and they claimed the reward now theyre gonna have zero staked theyre gonna have zero earned and theyre gonna have 280 withdrawn if they withdrew all their stake they withdrew all their earned and thats how we tell the contract hey this person doesnt have anything anymore and then these two would be like updated accordingly but im not going to do the math great questions really good questions here okay hopefully that makes more sense lets keep going so actually i think this this was a helpful exercise because i think itll itll make doing the math here a little bit better one of the first things that were going to need to do in our um in in our update or our claim or excuse me our um update reward bit is were gonna need to figure out okay what is the uh what is the reward per token stored right so in our example down here uh at the beginning when theres were giving out 100 tokens per second that means that means that what that down here it was one token per stored token or staked some token per stake token down here when the total was 200 is what 0.5 tokens per staked token and thats how we did some of this math down here okay so we need to get this reward token reward per token stored and were actually going to make this a storage variable so that other functions can use it were going to make it at the top so you went six um public oh and the other thing is if youre like hey man ill be honest the math is really confusing for me dont worry about it just trust the math works although im saying just trust and like the whole antithesis of this space is to trust stuff um but you can look at a lot of these these uh these big protocols like synthetics uh like other protocols that are doing staking and kind of see the different math strategies that they use right so this is the one that synthetics is using so we need to get this reward uh per token stored so and were going to turn this into a function called reward token were going to create so lets create this function reward per token and this is going to be a public view view returns un256 and at any time somebody can see okay what is the reward per token in here per each one of these tokens i get um for each one of these tokens i get whats whats the reward basically how do i what is the reward per token how much reward a token gets based um based on how long its been during uh its most recent snapshot if you will now what were going to say first off were going to say if s underscore total supply is 0 and were just going to return thats underscore reward for token stored so if theres nothing staked were just going to say okay great reward for token storage its just whatever we had whatever we said it was last otherwise were going to return reward for token oops reward for token stored plus and this is where it gets a little bit tricky again lets say the block.timestamp minus the last timestamp s underscore last timestamp which we havent defined yet which we will last update time so anytime we call stake or withdraw were going to need to update the time and actually were going to do that in our update reward function last update time equals block dot im stamp were going to make this global as well even 256 look and again this is where the math gets hard so if youre like what is what is he doing bear with me um just bear with me here block.timestamp um times some reward rate reward rate which again for our contract is going to be a hundred tokens uh 100 tokens per second so were going to say units 256 public will make it a constant reward rate equals 100. times the reward rate times 1 e to the 18th because we want it to be in uh in way divided by s underscore total supply you might be reading this and you might be going what in great heavens is going on here so again um we have a reward rate of 100 tokens per second so right here were grabbing okay well how many seconds has it been how many seconds has it been right okay its been 100 its been one second okay times that by 100 times by 18 decimal places divide that by the total supply if theres a hundred tokens excuse me if if uh if its been one second right if this is one if its been one second reward rate is 100 and the total supply is 100 then this persons gonna get a reward per token of one plus whatever the reward per token stored is so plus whatever theyve earned before okay excuse me plus whatever the return uh reward per stake is you do not have to remember all this math uh you can absolutely rewatch this later oh thank you you do not have to remember all this math you can absolutely watch this later um so if youre going what is what in what the what is this math um i would i would basically just say dont worry too much about it um but yeah feel free to come back to this and we can ask more questions about the math i i know that uh if we spend too long on the math here everyones gonna be like what what what are you talking about whats this math um but for now lets just keep going right so were updating updating the reward that each person gets were getting the reward per token like so were getting the last time stamp so we can have those timed snapshots and now we can finally like update how much reward each person has right because we want to keep track of how much everybody has earned between these timestamps of people you know staking and unstaking stuff so were going to say s underscore rewards of account equals earned and were going to create an earned function of account now that we have the reward per token we have the last update we can now see how much in total this person has earned so well say function earned uh which will take an address account its input parameter this will be a public view and return a un256 now were going to get the total this person has earned right and theyre going to use this to call withdraw so and get ready for some more math here so actually lets lets make this a little easier so well say uh well need unity six current balance equals s underscore balances right and maybe this will be the part to that should be easier to understand well get their current balance which is the current balance that they have staked right which were just getting from our storage variable were also going to need the reward per token um but were also going to need how much they have been paid already um so were going to create a new data structure called s user reward for token paid and this is going to be a mapping up here mapping of address to uint256 public this right here and this is just going to be a mapping of how much each address has been paid why do we need that well because we dont want to give them what theyve already been paid so were going to say unto 256 amount paid equals s your s user reward amount uh paid per token of accounts and then well update this later on in our claim reward function and then we need um the un-256 current current reward per token equals reward per token so get the current balance amount paid amount theyve already been paid the current reward per token and then s underscore rewards um 256 past rewards right and this is all the stuff that we need to calculate how much theyve how much theyve earned how much they have um how much theyve earned here and well say their current balance times the current reward for token minus how much theyve been paid were doing the reward per token minus how much theyve already been paid times the current balance stick with me stick with me i can see some of you all zoning out how to by 1 e to the 18th and this whole thing is added to best rewards 256 earned equals this return earned i feel like i i did it like this to make it easier to understand but i feel like i did not accomplish that i did not make this easier to understand um yeah 100 tokens per second is pretty hardcore well if you if you think about 100 tokens per second as in like you know if one token is one one two three four five six seven eight nine ten one two three four five six seven eight if this is one token then you know 100 per second is nothing right we have this earned function which i see a lot of you all being like what is going on and im like oh yeah uh this is definitely a little bit tricky to understand here um lets just keep going again this is a whole bunch of math stuff uh i tr if youre like if youre super struggling with this math say hey math is hard and uh and call it a day um dont call it a date look look into the try to try to understand whats going on here i i i know that this is kind of hard because theres a lot of math so hopefully this is making sense let me lets just finish the function here um and uh well finish the function here and then we can ask more questions about like what what just happened with all the math so i will say s underscore user reward per token paid of account and the equal to s underscore reward per token stored and that is the end of this modifier so the reason we made this modifier is because whenever we stake we want to update the um excuse me we want to update the reward of message.sender whenever we withdraw we want to update the reward of message.sender whenever we claim reward we want to update the reward of thats the tell sender right anytime we do anything we want to update the reward update the rewards of this person right because if they withdraw okay great we need to if they withdraw great we need to say hey we withdrew a whole bunch and now when now they have nothing left to be earned or they have nothing left staked when you claim rewards you gotta update earned um withdrew and claimed rewards on everything when they withdrew and claim rewards they have nothing staked now everything was withdrawn so they have nothing left turn anytime we pretty much do anything we need to update the rewards for that user cool hopefully that makes sense now that we have that update rewards function and we created a whole bunch of random variables and stuff did i create this one yep did we create this one thats rewards we didnt create us rewards straight ass rewards so this is going to be a mapping of an address to a unit 256 3 public s rewards mapping of how much each address has been paid this will be a mapping of how much rewards each address has so claim reward they first need to update the reward amount okay now that we have that what we can do is we can say okay great well two unit 56 reward equals s rewards now that were calculating this this rewards thing message.sender now all we got to do is we just transfer them the awards that they do right thats it so we update the rewards and we just transfer them the reward so s rewards is going to be kind of the um how much each reward address has to claim i should say that all right so s rewards is how much they have to claim which is great right we want then we can just transfer them how much they have left to claim so well update that reward amount and then transfer them the amount they have to claim so once again well just do bool success equals s underscore rewards token dot transfer message.sender reward and uh we only have a staking token so far but we probably want to have a different reward token so lets do the same thing in our constructor here so well do an address staking token well also do an address rewards token or reward token then well just copy paste this and so well say s underscore reward token equals i erc 20 reward token and then well just copy paste this into i reward token so we have two different tokens in this contract we have one for staking and one for reward they could 100 be the exact same token but were just gonna make it clear that we potentially could have two different ones and then down in claim reward full success were going to say if not success revert um taking transfer failed so are we done pretty much we could do a little bit of cleanup here uh we create a little modifier modifier called more than zero more than zero which takes a you into the six amount just to make sure that people are are staking and withdrawing more than zero well just say if amount equals equal zero then we could say revert needs more than zero and well prepend it with staking its taking underscore underscore needs more than zero a little underscore down here up at the top error staking needs more than zero and well use this more than zero modifier on our stake function more than zero amount i also probably do more than zero on withdrew uh one zero amount okay so now that both of those are needed more than zero we probably could double check for reentrancy by using like opens up on reentrancy guard but for the most part were pretty much good here so im going to compile real quick and then im going to answer your questions dont worry im coming darn hard hat compile im going to come answer the questions i forgot to add this so lets go ahead and add these well do yarn add dash dev that opens up on slash contracts we have 40 minutes left okay so were doing plenty fine on time well do compile again uh i meant s reward token do anything else wrong looks like i have shadow declaration okay so i have an earned variable and an earned method earned okay earn so well say call this like underscore earned that better okay cool okay so now this is compiling successfully um so pretty much were good here now what we want to do is create a deploy function make some tests um etc and if we have time i think the tests will really show us oh thats how it makes sense thats why it makes sense um and thatll thatll show kind of the math that that goes on behind the scenes so but before we do any of that in the last 40 minutes lets answer some questions here and i think the tests will really make the math make a lot of sense what happens if i claim rewards and then deposit them again well youll update the rewards right and then you can just go ahead and restake them which will update rewards again so were updating balances no matter what um so thats what will happen right because when you when you claim rewards youll youll now have zero left to claim and then you can just redeposit them which is great youve made it pretty clear appreciate your patience if math is mathematical and critics are critical then oh okay you will get a bigger portion of the pool what is line 48 saying oh its a its a underscore so this is saying um this is like after the after you write your modifier code you know youre saying hey uh now go ahead and do the rest of whatever function that im modifying so when you do so in like more than zero here um you can kind of read this as okay do the update reward code okay then do the more than zero code which is do this and then do the rest of the code where do we define s underscore rewards i didnt define it um when i was coding but now i defined it like this mapping of how much rewards each address has to claim will there be github for this yeah yes indeed oops um so this is at a minimal here uh so i just posted it in the chat how often do you run these code alongs for the hackathon were doing them kind of all the time so uh definitely check out and you can see uh the agenda down here so today its this later on today were doing an nft using ipfs tomorrow theres a whole bunch of stuff day after that is a whole bunch of stuff next week theres a whole bunch of stuff theres a whole bunch of stuff all over the place how do you call functions when it has modifiers with different parameters as the function being called when it has different parameters as the function being called i mean so you can just call a modifier um with whatever functions the modifier takes right so for example we have update reward which is a modifier which takes an address account as an input parameter were just passing address as the input parameter even though the stake function has a different input parameter so up to reward is looking for an address we just pass it an address like in the function declaration whats the scope of revert every operation before the revert instruction within the called function its uh its the entire transaction actually the entire transaction so every operation uh before the revert instruction uh within the whole transaction yes crazy right which is what we want the math done here related to staking are there any reference books or blogs which cover them in details yes um somebody by example does a pretty good job um i guess he doesnt really go over it he just kind of shows his his code um synthetics you look at this uh oh actually yeah smart contract programmer actually this is really good yeah okay this one is really good ill post a link to this in the chat its got a video uh which goes over it cant see s underscore rewards token oh yeah its uh we we fixed that was updated meant the last line of earned okay earned were returning earned what do we mean the more investors of the contract the less the apr yes uh the way that were defining it so thats because we are have a constant reward rate now what synthetics does and what a lot of protocols do is they dont have a constant reward rate their reward reward rate changes based off of how many people are using their protocols for example so if theyre making a killing on fees this reward reward rate is going to spike so but in this one in this one yes the more investors the less the reward rate so you can but you can customize this as much as you want uh out of interest are there any well-known public staking projects that update per second this at least shows what d5 and programmatic contracts can do wouldnt it be feasible for tradfy to do it shows with d5 bro uh well what do you mean this one this one updates per second so like synthetics updates per second not sure i follow when does the modifier on a method get executed yes so uh when you call this function excuse me uh when you call any function you run the modifiers first so were gonna run update reward first were gonna run run zero well thats not necessarily true they get run whenever the modifier tells tells it to so this this weird little underscore thing this stands for the rest of the code so if we run a bit more than this more than zero like this we first would run the function and then wed run the code in here but more than zero gets like uh hit first if you will like it goes to more than zero first um i just got a calendar notification saying i have a workshop right now well its a good thing im already doing the workshop uh so thats how that works this is to make lp stake um this is to make a staking contract um im not sure what you mean by lp stake i meant functions take amount with modifier more than zero another variable so you just pass another variable in here so you do like my you know um 256 my other var then you see this hopefully thats clear and then function stake with modify more than zero another variable when you call function hash you need to send two parameters amount and another variable right yes exactly can i ask some ethereum related but non-sticking question yeah sure okay hopefully this is clear now what do we want to do now actually so we have a couple options so i can write a quick test to hopefully show you kind of the math in action and kind of this in action or we can talk more about the math um if we want what do we want to do here how are people feeling how are we feeling and ill ill flip back to me because i know we just been talking for an hour and a half here um so i hope everyones still doing all right oh i need a haircut huh tess wed love to see some tests okay i have something uh notice and cant understand whats that i create a function which generate the private key randomly the private key got after many empty accounts have asset but the account i not totally following your question sorry can you do a test and deploy test test test and play all right here we go all right were jumping in test and deploy absolutely we can absolutely do that so for those of you who uh follow with the uh hardhead starter kit um you absolutely should let me hard hat starter kit you know that we love working with hard hat deploy and i just posted a link to the heart at starter kit oh and remember for people who are who are jumping off before you jump off oh before you jump off hold on let me grab something before you jump off please please please uh remember to fill in the feedback form im going to post it here whats in the chat im also going to put on screen uh please please please please please please and i think i have a qr code copy link oh that just goes to the um yeah please please fill out that uh that form let us know how we do it did in these um but yeah wait till the end let us know how we did it helps us figure out what workshops are good and which ones are bad and maybe if we get feedback here saying hey math too hard we wont do any more math ones um a couple more questions then well absolutely jump into the test and play the first thing in contract you do follow a follow a code and keep learning to do similar contracts the first thing in contract you do you do you follow a code cant and keep learning to do similar contracts um yes no need for hackathon its i need no need for a haircut attack on the mode can uh um can a modifier run after the code yes a modifier can run after the code so like in staking if we put this underscore up here this means the code of the function is going to run first and then this is going to run so this underscore stands for the rest of the code question really good question okay lets jump lets do this so first thing we got to do is lets lets write our deploy script so that we can deploy it for our tests so i use hard hat deploy if youre not familiar with hardhat deploy its awesome im not going to go over it too much right now but to write our tests since this is a staking contract were going to need to deploy were actually going to need to deploy tokens right deploy a reward token a.js deploy our reward tokens before we can deploy our staking contract right because if we look in our staking what does a constructor take it takes two addresses two erc20 token addresses so before we even do that then what were going to need to do is create a new file called reward token thats sold and im going to go a little bit quick here because short on time and im just going to copy paste this code in here but basically we have real simple real minimalistic reward token were importing from elpin zeppelin the reason were using erc20 not ie or c20 is because we want those functions uh yes you could test with brownie if you wanted but were going to test with hardhead here um and were just minting this many of the tokens and this is going to be both our staking token and our reward token so first lets go ahead lets deploy the reward token um and in our deploy functions uh if you go to the hardhead starter kits you can kind of see an example of what these look like you can also check out the hard hit deploy package that were using to help make our deployments easier so so get started were gonna do module.exports equals async named accounts and deployments um its gonna be a little um arrow function here and in our hardhat config were actually going to need to add a whole bunch of stuff in here were going to need to and im just going to copy paste im sorry i realized that were short on time so im adding uh so in order for any plugin to work with hard hat you need to add it to the hardhead config so were adding hard hat waffle for our tests were adding hardhat deploy so that our deploy script works we dont need this one we dont need this one we dont need this one and we we dont need this one either well we probably should use that one but were not going to use it so whatever and the other thing that were going to do in our config is were using this get named accounts function which comes with hardhat deploy and basically we just name accounts in our module.exports here so well just do named accounts you were hoping id do what um well say deployer its gonna be default zero so were basically saying hey were naming a deployer account to be like the ethers built in accounts at index 0. ethers uh which comes with hardhead gives us like a bunch of fake accounts and were just saying the deployer were going to name one deployer and thats always going to be um at index zero and and thats it and its just kind of nice for uh writing some tests here now were going to say const deploy uh which is how were going to deploy stuff equal deployments to const deployer equals a weight get named accounts i gotta go crazy fast if i want to write a test here um were gonna do const reward token equals await deploy reward token this reward token is the name of the contract ah so the name of the contract is reward token so boom were saying were going to deploy reward token were going to say from deployer and this is the arguments that were going to give it args is going to be blank blogs right no args no constructor arguments log will say true thats it and well do module.exports.tags equals all and word token just to make sure this is working and i know im going kind of fast darn hard hats deploy dash dash tags reward token unrecognized task deploy head config boy oh no we have it the poly thats why because the poly isnt a task and we ran into an issue from.two lowercase is not a function um okay wrong ollie yep its about deploy wrong yep from not to lower case its not a function what the heck uh all right well it worked this time cool im not sure what it did wrong but its working now great so were deploying this uh awesome so now that we have a um a reward token now were gonna create our uh were gonna deploy our staking token you know sometimes stuff just works right like um isnt life great and were gonna do real similar setup to this im gonna copy this this bit boom because were going to deploy staking in here and were going to have the same setup uh and then if you saw this again let me im just going to run this one more time right were saying deploying reward token we deployed here we deployed it yay awesome now lets deploy our staking contract uh were going to do real similar setup here the only difference is were going to say const reward token equals await ethers.getcontract yup and const we gotta import ethers from harnett ethers.getcontract reward token and this is one of the cool things about hardhead deploy to get the most recently deployed reward token we can just do ethers.get and it will get it for us which is phenomenal and then we can say const taking deployment equals await deploy were staking deploy our state contract were gonna say from deployer args are gonna be what what are the args for staking see the constructor address one and address two so well say reward token.address and then reward token.address and then were gonna need log is gonna be true and then thats it and this will be sticking now if i just run yarn hard hat deploy it should deploy our staking our reward tokens and then our stake in contract and i ran to an issue no contract deployed with name reward token uh deploy reward token oh my god did i just overwrite this with oh my god i did overwrote deploy reward token with lets take lets undo undo and do a do and do im doing do and do there we go yall see me do that thats kind of funny uh now i put in the right spot oh whoops i didnt save this wrong here two lowercase is not a function okay so now were back at that weird weird four im pretty sure i just spelled something wrong right if i do uh yes okay because i i need to have deployers in uh brackets like that okay cool deploying reward token deploying staking okay we we did it uh okay so now we have like two seconds we have 15 or we have 10 minutes to do some testing which were gonna uh were gonna do now that we have some deploy scripts uh any questions deepali well its working now yep was hoping to do another version of testing with brownie yeah sorry im not uh do you even need to import hardhead yes yes you do um but okay great now lets do some tests because were gonna go a million miles per hour here so tess were going to do is a staking test staking.test.js and the reason that tests are so fantastic is its were really going to be able to see like by running these tests exactly how much um well get how much reward people will get you know on different uh on different stuff okay so im just going to write one giant test there are more tests in that repo that i sent you um but lets do it so well say describe and this is going to be using like mocha test scribe staking test this will be an async function and well say do a little let well say staking reward token employer well say die and then stake them out say before each the async function i dont know why im using an arrow function yes air functions are silly async function were saying before each test that we run well say uh const uh deployer equals uh well do await ethers ethers.get actually ethers is imported from hardhat great and well call this accounts accounts and well say const deployer wait zero dont need to wait now to deploy to run through our entire deploy folder and this is why i love it so much we just run await deployments dot fixture and we just say all so that will deploy everything for us and then were importing deployments from hardhat then well say staking now equals weight ethers dot get contract staking and do this a couple more times we say reward token equals like a reward token and then i dont have die i dont need die to my mind um so well say reward token staking reward token we have those and then well say stake amount equals ethers dot utils dot parse ether 1000 boom okay so we have a little before each now we can just now well do like our one massive test in and ill do it in like five minutes um its what the heck what is that it allows users to stake and claim rewards this will be an async function now what we want to do to work with the staking contract is were going to do everything that its all going to its all coming down to this first thing what were going to want to do in staking is were going to want to stake were a stake were going to want to stake some tokens right and as a lot of people said hey patrick transfer from when does that actually get called well its going to get called on the ui or its going to get called on our test so were gonna do await reward token dot approve speaking dot address stake amount so if were on like a a website or a ui were the one actually calling this right and in our tests we still have to be the ones to call this so were saying okay great were going to approve the staking address to take x stake amount of our tokens now were going to await staking at stake take them out so were going to stake um 100 000 tokens so were staking a hundred thousand tokens and we could just run our tests here right so lets even just do um well say cost earned or starting earned equals weight staking.earned uh and this is deployer.address because its the deployer open uh yeah deploy dot where employer deployer cost deployer oh player there we go then well just console.logs out console.log and im doing a little string interpolation like that then we can do hh test or yarn hardhead test i have a shorthand installed where i can do just do hh and it tells and its the same as doing like yarn hard hat so we have okay great we have earned zero which makes sense because no time has passed right we staked 100 000 tokens no time has passed so we start off with zero so im gonna say starting which is exactly what we expect okay now i have some utils that i use and im just going to copy paste them because guess what that since were running on our own local blockchain we can actually move blocks and move time ourselves so i have already created these functions and and im not going to go through making them because were short on time but i have a function here called move blocks where we move blocks however many blocks like we mine however many blocks we want and we can move time however long we want to move it right which is really important for running tests and im going to import them so im going to say const blocks equals repo for this is right here blocks equals require bills slash the box or also move time move time we staked a whole bunch of stuff and cool nothing really happened well lets go ahead and well move time um and well see how much how much weve uh weve gotten after we move time so to move time well say const seconds in a day equals eight six four zero zero and the reason i know this is because i googled it before kiki and what were gonna do is now were gonna do await move time seconds in a day and then well do a wait move blocks one so were moving this many seconds and then were moving one block just to make it so that uh we have a block which has the time and now we can run earned again but this will be ending earned and the earning equals the weights taking down earned and then we can do the same console.log here again but with instead of starting earned well do ending earned ending earned run it like going crazy fast so moving one blocks ending we ended up earning this many tokens at after after one day right and you might be thinking holy cow thats a lot of tokens remember one token is one one two three four five six seven eight nine ten one two three four five six seven eight really this isnt a whole lot of tokens at all like we didnt even get one we didnt even get one token from one day so lets try a year so well say const seconds in a year and i already know how many seconds in a year its that many seconds so lets try doing that so well do seconds of the year well run this again and after a year weve got this many tokens which is a lot more still less than one but not so much but again our contract is only outputting at a very very tiny rate so thats how the math works right it keeps giving us more and more tokens as time progresses now what do you think if we waited a year and then somebody else staked right um we actually dont have time for that we have seven minutes left so you can check the tests um in the repo here and you can play with it you can expand on it you can do whatever you want um but yeah hopefully this was helpful i know i kind of really sped through this because we have no time left um im gonna switch back to me thoughts comments questions and yeah im sitting down now um thoughts comments questions on anything that we went over i know this was a lot i know this was kind of definitely the most advanced workshop weve done so far um yeah what did uh how did we do what did what do we think any any thoughts comments questions these are everybody who ask questions though these are really good questions um im constantly impressed by the level of questions here especially with a concept like this where we had two hours to like learn defy almost which is uh not a small feat at all so if you understand understood anything if you took anything away from this workshop im im incredibly proud i mean im incredibly proud because again this was a hard workshop and again in the chat um right here posted a link to that feedback form please please please uh give us feedback thats how we know hey like maybe uh maybe these maybe the hard hats um uh default workshops arent for real maybe maybe you guys all say hey you know what we dont like those you know let us know uh patrick youre uh you coded way too fast i couldnt follow along repo wasnt clear make the repo better code example not good etc whatever any or or maybe hey patrick youre youre amazing you killed it you know whatever feedback um it helps us it helps us figure out you know positive or negative positive feedback says great keep doing it negative feedback says all right stop doing it so good session good session um and we have five minutes left here so are there any questions on anything defy anything this project or really anything at all right because we have five minutes left so we can kind of talk about whatever we want to talk about now um questions comments concerns yeah i yeah freddie i i uh based off your questions i could tell you were coding along which is awesome you are 100 doing this the way uh way i had intended yeah the math part uh and then i got really fast at the end i um because we started running out of time um uh the the math part took me a few tries to figure out myself so and thats why and thats why im like saying like hey like its its its even with people who really understood like the staking like explaining it to me i was like what so its its its a little bit tricky to grasp once you grasp it its it makes more sense but it definitely takes a couple tries that video from solidity by example is really good um so let me by example or our smart contract programmer really really good where is the repo of all the files so i posted it in the chat a couple times um d5 minimal smart contract kit d5 minimal its in the chat somewhere if you scroll up as well is it worth to add typescript supports probably is is there a brownie mix you would recommend to use a starting point to remake this project with brownie so i havent done this with brownie but you could pretty easily copy just copy all the contracts and then create your own like scripts on it if you look at the chain link mix i mean if you look at the chain link mix it should be i dont want to say straight forward because thats thats not always true um i uh basically i dont think i know of of a staking contract uh brownie repo but there are plenty of repos with with defy um ive done some flash loan stuff ive done some ave stuff um thatll be pretty similar all right cool awesome thank you is the code for staking nft similar yes itll be very similar device thinking is complicated make sense see like that the thing is like it doesnt have to be um just the math is right at the end of the device taking is pretty simple and and i want um and i i dont want us as a community to get into the habit of saying like oh d5 is hard like so be it because it really should be something that anybody can can pick up right we want to enable this technology to allow like anybody to just use and go right we dont want to have a system where like only elite people can use d5 like that would suck and like thats kind of already what traditional finance is right now were only like the elite people can use it and like thats like not what were trying to build here um or at least thats not what im trying to build that will tear me apart if thats what happens was following along up to the test then went like the flash well go through the yeah sorry i start i i started like copy pasting a ton because well we had like no time left um which makes it you know impossible to code along because im like hey like im copy and pasting this now good luck um thanks for following along paul can anyone stake or do you need experience in computer programming yeah anybody anyone can stake and anyone should be able to stake i think thats where we want to aim we want to aim to be a point where anyone should be able to stake apart from solidity by example what other resources would you recommend to learn more about staking and see other examples of contracts um good question good question open zeppelin for sure absolutely open zeppelin uh damn vulnerable defy if you if you want to learn about d5 security um open zeppelins ethernet is very good those are more like security stuff but they also will help you like learn um a lot of default stuff but a lot of and the cool thing about all these protocols is that theyre all open source so if you want to go see synthetics code if you want to go see obvious code you can just go to their repo and play around the thing thats a little bit hard is theyre pretty large code bases so going to those those repos might be really overwhelming um but you can do that or you can go to those repos you can go to any any production project is deploying contracts to l2s like arbitram or optimism very different from mainnet notes like nearly exactly the same all right cool all right i will remember to fill up that feedback form its in the chat so scroll up just click the link um thank you all for being here it is 9 31 so we are now over uh hopefully you all learned something here let me know in the feedback form what you learned what you didnt learn and we will talk to you all soon good luck at the hackathon uh later on today we have an nft end to end theres theres no math in the end a few bits so thats good um and were going to be hosting an ip fest so its going to be a ton of fun so if you want to learn how to make nfts programmatically make them customized make them dynamic definitely go to the session later today well see you there and good luck with the hackathon bye all you Code along with Chainlink Labs Lead Developer Advocate Patrick Collins and build your very own DeFi staking app. Make sure you visit the DeFi minimal repo for more DeFi code examples: Chainlink is the industry standard for building, accessing, and selling oracle services needed to power hybrid smart contracts on any blockchain. Chainlink oracle networks provide smart contracts with a way to reliably connect to any external API and leverage secure off-chain computations for enabling feature-rich applications. Chainlink currently secures tens of billions of dollars across DeFi, insurance, gaming, and other major industries, and offers global enterprises and leading data providers a universal gateway to all blockchains. Learn more about Chainlink: Website: Docs: Twitter: Chainlink Chainlink,