Transcript for:

welcome to the ultimate smart contract developer security researcher blockchain engineer full platform and course this course this set of videos is all you need to go from where you are to successful smart contract developer or security researcher we have been doing this for over 4 years now teaching the next generation of smart contract developers how to be successful on YouTube alone our videos have over 6 million views where we have both the number one and number two most watched smart contract educational content on the planet and that doesn't even count the number of viewers and users who watch and learn on our education platform cyphon updraft and we've taken all the learnings in those years of doing this education wrapped them all up to make what you're currently watching the best one yet this one has a ton of advancements in it making it the most cutting Edge web3 developer course period having made one of these courses for the last four plus years I've been reached out to by countless developers who are now full-time developers in the web 3 space making a living doing well and contributing to web 3 and there are thousands that I have not met who have left comments or left me notes and I know we're going to do it again with this video If you're looking to become a web 3 solidity smart contract or blockchain developer or any of those terms this is the course for you for you and this course is for anybody and everybody no matter your blockchain or developer experience level and additionally we're going to be using artificial intelligence to accelerate our learning progress and I'm going to teach you not only how to become a blockchain developer but how to work with AI tools to make you a 10x developer if you have a little bit of developer experience before this this course will be even easier to get through but again don't worry if you've never coded before and for those of you who are already familiar with blockchain and smart contract development feel free to jump around the different modules and different sections and grab the learnings that you want I promise there's a lot of cutting edge information in here and maybe you need a brush up and when I say this course I mean this path in its entirety if you're watching this on YouTube this is just one giant long humongous video watch this all the way to the end to have the highest chance of success for those of you who are watching this on cyphon updraft and you all should be you have a buffet of choices of where to go but don't worry I'm going to make picking the choices incredibly easy for you so no matter if you're brand new to coding brand new to block or you're an experienced smart contract engineer you're in the right place welcome to the edge of the rabbit hole let's get froggy for those of you who don't know me my name is Patrick Collins I'm a smart contract engineer security researcher and just lover of all things web 3 I'm one of the co-founders of the smart contract auditing firm cyphon average smart contract YouTuber and I live and breathe smart contract development I absolutely love web 3 blockchain and smart contracts and I love the power and the tools that they enable us to use but not only that I I love taking blockchain developers like yourself watching this video right now on the journey to becoming a successful smart contract developer I think the key to web 3 to blockchain to cryptocurrencies being successful is having a phenomenal Foundation of developers so I'm incredibly excited that you're here with me and for those you who don't want to become blockchain developers the first two lessons of this course lesson zero and lesson one are foundational pieces of conceptual information for you just to understand how to get into this web 3 thing so if you don't want to become a developer just stop once we get to the coding in any case I'm incredibly excited for your journey this is a data dump passion project of all the knowledge that I've collected over the past few years of working in this industry and being a smart contract developer myself and at this point I have the track record to show that I am 100% confident that if you follow along if you code along with us if you follow me on this journey you'll come out the other side armed with the knowledge to be a positive force of the cryptocurrency blockchain industry smart contract and solidity developers are massively in demand with an average salary being around $145,000 a year and with AI coming in place it's becoming even easier to get up to speed quickly but only those that understand the technology truly will be able to take advantage of all these advancements AIS get stuff wrong a lot so we especially need the knowledge to fact check whenever AIS get things wrong being here you have the opportunity to be a Pioneer ushering in the age of web three of cryptocurrency Blazing the trail of where this phenomenal industry has yet to go like I said this isn't the first time we've done this we've already helped so many developers get into space and we're going to give you the Cutting Edge most modern tools for Industries like dii nfts Dows tokens upgradeable smart contracts blockchains and everything else that you can think of once you finish this course it will be abundantly clear what you want your next steps to be and you'll have a ton of Economic Opportunity at your fingertips and and opportunities to make a huge difference in this amazing industry however I can't just give it to you you have to come with me on this journey you have to take the step despite what you might think you know cryptocurrencies and smart contracts enable a more accountable World a more transparent World a more collaborative world a world where promises can't be broken and that's a world that I want to live in we'll teach you about the purpose of smart contracts in section one of this course and then later we'll teach you how to build them so before we even get started I want to give give you a huge thank you for even being here on this video and listening and being interested in engaging in this phenomenal technology so thank you for being here and welcome to the rabbit hole cuz we're about to drop down with that being said let's get froggy so let's begin our journey by talking about some best practices that way you can get the absolute most out of this course and be as effective as possible now you're either watching this on on cyphon updraft or on YouTube and I encourage everybody to watch this on cyphon updraft because we've got a ton of features to make the learning experience that much easier for you so if you are watching this in Cypher uptp though there's a couple links I need you to be aware of the first one in the top right is going to be the GitHub resources page this will bring you over to what's called a GitHub repo or a GitHub repository or basically a site that has all the code and all the information and basically all the materials that you're going to need to learn everything in our curriculum you could basically think of this as your Bible for the duration of your blockchain developer Journey additionally in this GitHub there's a discussions tab right here that you can click on and in here is where you can ask questions discuss with other people taking the course interact with members helping out and it's where you can discuss anything that you're having trouble with then on the other side you'll see this tab called written lessons if you cannot stand the voice coming out of my mouth you can just flip over to that and just read the course curriculum as well if you prefer the written content over the video content and it's good to go over to the written lesson anyways to maybe copy paste some stuff if you scroll down here right now it's blank but if anytime there's an update to a video something's changed in the video and we haven't swapped out the video yet you'll see a little updates section with information saying hey the video says this but you should do this instead now like I said this is a very fast-moving industry and sometimes things change and sometimes things need to be updated so when you're watching one of these videos be sure to look for that updates tab at the bottom and then additionally whenever you're working with the code that we're working with I will give you a link to the finalized Edition that you can use as a reference as well to make sure that the code that you're working with actually is going to match what we are going to build additionally if you think you found something that is different or doesn't quite work be sure to make a discussion for it in that GitHub repo like I said it's going to be your Bible additionally there's a link to join the GitHub discussions this is your platform to ask questions engage with the community and learn with both other people taking the course and also our Tas who are going to be helping you out along the way additionally there is link to the Discord for more realtime communication I urge you to ask questions in the GitHub discussions as well because those are going to be indexed going to make them much easier to Google search later and have them show up as opposed to Discord Discord is still phenomenal for you to join them for those of you watching on YouTube hello you should scroll down to the description and in the description are going to be links to these resources as well and additionally a link to cyphon updraft if you've been watching you've already seen some of the advantages that cipon updraft has including written lessons single videos and there's also ways to track your progress instead of having to scrub on a giant YouTube video so for all of you who are watching this on YouTube definitely be sure to go over to cyh updraft sign up there and watch the curriculum there because your learning experience will be much better but leave this video playing in the background on YouTube so we get the bump from the YouTube algorithm thank you that being said as we go through this course we're also going to teach you some best practices on working with artificial intelligence how to best prompt these AI so that they can give you the best results just keep in mind they sometimes get things wrong and it's a good idea if you are going to use an AI to fact check it with a human or another resource so be sure to say hi in the discussions and maybe meet some like-minded peers and additionally once we do get to the coding portion of this course it's a good idea to code along with me as I'm explaining things so having the video up as well as your coding screen is a good idea so you can follow along with me as I'm explaining it if you're watching this on cyphon up you can just click the little video pop out button and have the video pop out as such en code next to it all of this is to say if you run into an issue jump to that GitHub repo and make a discussion we will also be giving you some tips very soon about how to best make a discussion yes asking questions to other human beings is a skill and we're going to try to teach you to be the most effective because asking well formatted questions is not only the secret to being a fantastic AI prompt engineer but also becoming an incredibly successful developer we're going to learn how to ask well-formatted questions and whenever we post on discussions or forums or whatever we're going to work on formatting them as best as possible take breaks I cannot tell you how many people have tried to rush through these courses and be like Oh I'm going to finish in a single weekend your brain doesn't work like that your brain needs time to absorb the information so take breaks maybe every 25 minutes to a half hour take a 5- minute break or maybe you like working in longer chunks maybe take a whole hour and then take a 15 20 minute break don't try to rush through the whole video in a day you're not going to retain the information go outside go for a walk grab some ice cream get some coffee go to the gym your brain needs time to have the information settled maybe every 2 hours just step away maybe be done for the day work at whatever Pace makes sense for you everyone's going to have a different learning Pace there is no right speed for this course I've had people take my courses in 2 weeks in 3 months in 6 months it doesn't matter pick a pace that you can do and stick to it not only work at your pace make sure that I'm talking at a pace that makes sense for you there's a little gear icon in the YouTube video here where you can change the speed of how I'm talking and how fast the video is going so if I'm talking way too fast for you then you can slow me down but if I'm talking too slow then you can speed me up and if you're watching this on cyphon updraft you have the same dials as well in the bottom right hand corner additionally if English isn't your native language we have seven different subtitles in the cyphon updraft video player as well so make the adjustments you need to make me go the speed you want me to go and of course this course is modular so you can Bounce Around topic to topic and go to where you want to go if you don't want to do any full stack stuff then skip that section if you want to go right to the advanced stuff do that like I said go the pace and take the learnings that you want to do and after every lesson it might be a good idea to go back and reflect on each lesson to really make sure the knowledge gets ingrained repetition is the mother of skill skill and we're going to be repeating a lot of smart contract development now the last bit here is in the cyphon updraft platform we're going to have quizzes that you can take to help see if you learn the knowledge that you were supposed to learn if you're watching this on YouTube you don't have that so go sign up for cyphon updraft and then play the YouTube video in the background so the YouTube algorithm bumps us up but additionally at the end of every section if you go to the GitHub repo associated with that section and you scroll down there's going to be a bonus nfts section with a link this will bring you to a coding Challenge on chain that you can actually solve to Mint yourself in nft a badge of honor proving that you gained the knowledge that you were supposed to these are optional challenges that you can do to try to make sure that you actually learned what was meant to be learned here and if you do solve them you get a very cool nft along with it don't know what an nft is don't worry we'll teach you later blockchain development and open source development world is incredibly collaborative so be sure to use tools like of course the GitHub discussions tab ethereum stack exchange the decentralized Q&A Forum piranha issues on different GitHub artificial intelligence and more and like I said we'll give you more tips on how to most effectively use these sites in the future and the reason I'm putting so much emphasis on this and that I will continue to put so much emphasis on this is being a successful smart contract developer is more than just knowing how solidity Works knowing where to go for information and how to collaborate with people is often more important than your smart contract knowledge because often times you're going to run into issues you don't know how to solve so we're going to teach you to unblock yourself on this this and really anything in life plus syncing with other people in the space makes it way more fun now before we can actually get to coding we need to understand how the blockchain even works what the purpose of these smart contracts even are and this is essential to becoming a successful smart contract developer because a technology is really just a solution and a solution is only as good as the problem is so we need to make sure we understand the problem really well so we know how to attack it with this smart contract technology and the better you understand the smart cont technology the better you'll be able to architect your smart contracts in the future and make really intelligent really powerful systems that further this amazing industry but if you already know the basics of blockchain feel free to jump into lesson two and skip over lesson one so those are some of the best practices to be really successful with this course but with that knowledge you're now standing at the edge of the rabbit hole and if you're like me once you jump in you'll just want to keep going deeper and deeper I'm so excited for you to embark on this journey with us and I'm looking forward to seeing you on the other side just like the thousands of other developers who have taken these courses and have emerged the other side triumphant so it all starts with blockchain Basics let's get froggy now throughout this course you will see a number of different guest lecturers who are going to be giving you this information we work with some of the best people in the industry to give you this information for lead instructors I've already introduced myself but just to reiterate my name is Patrick Collins and I will be the lead instructor for the majority of your journey on cyphon updraft but it's not just me who helps out creating the curriculum here I'd like to also introduce our co-lead instructor Kira Nightingale I will let her go ahead and introduce herself just a brief inlude from Patrick to say hi and introduce myself my name is Kiera Nightingale and I am a developer relations engineer at cyphon and I love all things smart contract engineering and I'm going to be helping Patrick out with creating content for you guys to become the best smart contract engineers in the world so if you see my face now and again not to be concerned cuz now you guys know who I am and with that said back to Patrick so don't be too surprised if you see her face popping up from time to time and with that let's continue now for you developers who are going to be going on to the solidity Basics and Foundry fundamentals or Viper or any of the other courses we are additionally going to be teaching you how to deploy to an L2 called ZK sync at the time of recording there there are a couple of differences that make deploying to ZK sync slightly different from deploying to ethereum but we imagine that in the future we won't need these couple differences as zky matures we imagine that the differences will become fewer and fewer Kira will teach you more about l2s and how they work in a future lesson and in our best practices section we talked about different challenge contracts that you can go out and you can solve to win an nft and it's on ZK sync where these challenge contracts are going to be deployed Kira will go over why ZK sync is such a phenomenal layer 2 rollup and additionally we want to give a massive thank you to matter labs and the ZK sync team for being the lead sponsor of cyphon updraft it's thanks to their sponsorship and their dedication to making web3 developer and security research education accessible that we are able to bring this course completely free to all of you so you can help support them support us by looking to deploy to their chain now we of course think disclosures are very important so anytime we work with the sponsor we will have a list of them in the sponsor section of the GitHub repo associated with this course and additionally we will also give you Alternatives as well so that you can use the technology that is correct for you we also want to give a thank you to arbitrum and optimism who historically have also donated to cyphon updraft now as of recording there are a few scenarios where if you're looking to deploy a real live professional smart contract to ZK sync it might be a little extra challenging so we have a file in the GitHub repo associated with this course that we recommend that you take a look at before you deploy a production smart contract to ZK sync in the future of course since you're watching this right now this probably doesn't apply to you but in any case a huge thank you to ZK sync and the matter Labs teams for helping sponsor cyphon updraft K will tell you more about why they are a really cool layer 2 and we're looking forward to seeing what cool smart contracts you deploy to ZK sync now since you're here you've probably heard of Bitcoin before Bitcoin was one of the first protocols to use this revolutionary technology called blockchain the Bitcoin white paper was created by the pseudo Anonymous Satoshi Nakamoto and it outlined how Bitcoin could make peer-to-peer transactions in a decentralized network this network was powered by cryptography and decentral and allowed people to engage in censorship resistant Finance in a decentralized manner due to its features when which we'll talk about in a little bit people took to this as a superior digital store of value a better store of value over something like gold for example and that's why you'll also hear people commonly refer to it as a digital gold similar to Gold there's a scarce amount or a set amount of Bitcoin available on the planet only so much that you can buy and sell you can read more about the original Vision in the white paper we have a link to the white paper in the GitHub repo associated with this course now this was an insane breakthrough and in a little bit we're going to learn exactly how this is all possible and how this actually works under the hood some people though saw this technology and wanted to take it a little bit farther and do even more with this blockchain technology and a few years later a man named vitalic butterin released a white paper for a new protocol named ethereum which used this same blockchain infrastructure with an additional feature and in 2015 him and a number of other co-founders released the project ethereum where people could not only make decentralized transactions but decentralized agreements decentralized organizations and all these other ways to interact with each other without a centralized intermediary or centralized governing Force basically their idea was to take this thing that made Bitcoin so great and add decentralized agreements to it or smart contracts and in fact technically these smart contracts weren't even really a new idea back in 1994 a man named Nick Zabo had actually originally come up with the idea smart contracts are a set of instructions executed in a decentralized autonomous way without the need for a third party or centralized body to run them and they come to life on these blockchains or these smart contract platforms like ethereum and it's these smart contracts that are going to be the core thing that we're going to be working on in this course and that we're going to be developing you can think of smart contracts in the same way you think of traditional contracts or traditional agreements they're just a set of instructions between parties except instead of written on pen and paper or typed up in Microsoft Word they are written in code and embodied on these decentralized blockchain platforms and that's also where they're executed instead of being executed by the two parties or three parties or however many parties that are involved this removes this centralized issue that we'll talk about more in a bit this is one of the main differentiators between the ethereum protocol and the Bitcoin protocol it's these smart contracts now technically Bitcoin does have Smart contracts but they're intentionally touring incomplete which means they don't have all the functionality that a programming language would give them this was an intentional move by Bitcoin developers Bitcoin developers viewed Bitcoin as a store of value versus ethereum developers viewed ethereum as both a store of value and a utility to facilitate these decentralized agreements now these smart contracts on blockchains alone are absolutely incredible however they do come with a huge issue if we want these digital agreements to replace the agreements in our everyday lives they probably are going to need data from The Real World blockchains by themselves actually can't interact with and can't read or listen to data from The Real World this is what's known as the Oracle problem these blockchains are deterministic systems and they're deterministic on purpose and we'll learn about more about how that works in the sessions to come so everything that happens with them happens in their little world but if they're going to be these agreements they need external data and they need external computation and this is where oracles come into play oracles are any device that delivers data to these decentralized blockchain or runs external computation however if we want our applications to stay truly decentralized we can't work with a single Oracle or a single data provider or a single Source that's running these external computations so we need a decentralized Oracle Network similar to our decentralized blockchain Network your onchain logic will be decentralized but you also need your offchain data and computation be decentralized combining this onchain decentralized logic with with this offchain decentralized data and decentralized computation gives rise to something called hybrid smart contracts and most of the biggest protocols that we interact with today are some type of hybrid smart contract or interact with hybrid smart contracts to some extent this is where the protocol chain link comes into play it is a modular decentralized Oracle Network that can both bring external data and external computation into our smart contracts to make sure they're decentralized end to endend while giving them the feature richness that we need for our agreements chain link allows for us to get data do upkeeps get random numbers or really customize our smart contracts in any meaningful way now throughout the course we're going to use the terminology smart contract however whenever we say smart contract we're often using it a little interchangeably with hybrid smart contracts but just know that when we say hybrid smart contract we're talking specifically about smart contracts that have some type of offchain component now since ethereum's release number of different blockchains or smart contract platforms have come to light such as Avalanche polygon Phantom Harmony and more for the majority of this course we're going to be assuming that we're going to be deploying to the ethereum network however everything that we learn here is going to be applicable to the vast majority of the blockchains out there like polygon Avalanche Phantom Harmony Etc and understanding everything from ethereum fundamentals will give you the skills that you need to switch chains very easily with literally one line of code so don't don't worry about learning a specific tool or with a specific chain because most of them work together seamlessly now there are a couple of smart contract platforms that don't use solidity but still learning the fundamentals here will make you much better at those as well and ethereum by far has the most value locked and is the most used blockchain and smart contract platform out there you'll also hear those two terms used a little bit interchangeably as well sometimes I'll say smart contract platform sometimes I'll say blockchain they kind of mean the same thing obviously blockchains could mean value and smart contract platform but you get the idea similarly chain link is the most popular and Powerful decentralized Oracle network is the one that we're going to be focusing on for this course as well chain link is also blockchain agnostic so it'll work on ethereum Avalanche polygon salana or really any other blockchain out there now additionally over the last year a new term has come to light called an L2 or a layer two this solves an issue that most blockchains see where they don't scale very well or they don't grow big very well we'll be talking about l2s a little bit more in the future but the basic concept of is that blockchains can really only get so big so what they do if if this is ethereum you can actually have blockchains hook into them to essentially make them bigger if that doesn't really make too much sense don't worry about it for right now layer 2os solve this scalability issues and at the moment there are two different types of true layer twos optimistic Roll-Ups and zero knowledge Roll-Ups optimistic rups like Arbitron and optimism or zero knowledge rups like ZK sync or polygon ZK evm yes there's a polycon chain but there's also a polycon z k evm L2 the two of them are very different don't worry about them for now but like I said once we learn how blockchains work from a basic Level under the hood then we'll explain more about how these l2s actually work now throughout this course you'll hear the term dap or decentralized protocol or smart contract protocol or decentralized application and they all kind of mean the same thing a decentralized application is usually the combination of many smart contracts and when we get into solidity you'll see what a singular smart contract really looks like and like I said learning all these core fundamentals will make you a better solidity and a better smart contract developer you'll also hear the term web 3 a lot in this video and in the industry web 3 is the idea that blockchains and smart contracts are the next iteration of the web web one being this permissionless open-source world with static cont content web 2 being the permissioned web with Dynamic content but all the agreements and logic runs off of centralized servers where they control your information and then web 3 comes back to the permissionless web but once again with Dynamic content and instead of centralized servers running your logic decentralized networks run the logic creating these censorship resistant agreements that these smart contracts enable it is also generally accompanied by the idea that the users own the protocols that they work with and it's an ownership account you'll see what I mean later in this course and we talked a lot about the history and about the high level of these protocols and of these smart contracts and what they can do but what do these smart contracts really mean what is it when I say trust minimized agreements or unbreakable promises what is the real value ad of these smart contracts before we look under the hood and take a peek at how this all works from a technical standpoint let's learn what all the value of this is what is the purpose of us building all these Technologies of you taking the course what problem does this technology solve in my mind a technology is really only as good as the problem that it solves if it doesn't solve a problem then why bother smart contracts blockchain web 3 cryptocurrencies those are all just different words that encapsulate the idea of what we're doing in such a unique Paradigm I think the easiest way to sum up what these smart contracts do is that they create trust minimized agreements and if you might be scratching your head to that a much easier way to think about it is just they give rise to Unbreakable promises Yes you heard that right unbreakable agreements and Promises additionally they give rise to speed efficiency and transparency and a number of other things I made a video pretty recently about exactly this so let's dive in and take a listen to the purpose the undeniable value of smart contracts cryptocurrencies fundamentally Rel landscape markets and agreements as we know them unfortunately you've probably only been bombarded with people screaming about nfts and money now some of the memes are fun but let's forget the and get down to the essence of this space if you're already in web 3 this is the video to send to your friends to explain why you're so excited about this space and explain why we're here and then if you're not into crypto you've come to the right place and yes there are fun memes and markets and there's some money stuff and there are all these things but outside of all that the purpose of blockchains relates to the ageold elementary school Unbreakable promise the pinky swear let's get froggy nearly everything you do in life is the result of an agreement or a contract your chair was a result of an agreement to buy and sell lumber to assemble and sell the chair to a retailer on Amazon then you made an agreement to buy the chair for $40 the lights in your house are powered by electricity which is an agreement from you and the electric company you agree to pay them in return they'll keep the lights on the electricity that they generate is agreements between them and Engineers who built turbines to generate the electricity with insurance you agree to pay some amount of money to them every month and in return they will do nothing or I mean they'll cover your medical bills almost everything you do and everything you interact with is the result of some form of agreement or contract in some aspect now agreements and contracts can feel kind of abstract and boring to really grasp on to so to simplify we can also refer to them as promises when you get an oil change they're promising that they will Faithfully change your oil in exchange for money when you put money in the bank they promise proom to keep it safe in exchange for them to use your money to give out loans when you buy a lottery ticket the lottery promises to give you a fair chance at winning a ton of money in exchange for you buying the ticket whenever you make one of these agreements in a way you're asking them to pinky swear to not screw you over and to treat you fairly but this doesn't always happen let's look at a real world example of someone breaking the pinky swear back in the ' 80s and '90s McDonald's ran a promotion for people to win money by collecting McDonald's Monopoly game cards the idea was simple you buy McDonald's in return you get a chance to win $1 million you can imagine McDonald's literally going hey everybody I promise if you buy our MC food and McNuggets we'll give you a fair chance of winning this money but they ended up breaking This Promise instead of having a fair chance of winning your chance was in fact zero in the mid 90s between 13 and $24 million went into the pockets of not people playing the game honestly but a group of corrupt insiders who had rigged the game meaning that when you played the McDonald's Monopoly game you are buying into a set of lies and promises that were 100% always going to be broken and the thing is it doesn't really matter if this was McDonald's fault or not they were the ones making the promises that they ultimately could not keep another way you can think about it is that that's $24 million that they essentially stole from you and I now if this system was deployed on a blockchain with something called a smart contract it would have been impossible to defraud this $24 million due to Smart contracts being immutable decentralized and transparent but I'll get back to that in a minute in all the agreements and contracts we make imagine making a pinky swear with a 10-year-old and imagining how that agreement would hold up hey buddy could you could you please keep my money safe you can play with it if you like but just just please have it when I come back immediately you might get that worrying feeling in your chest something might go wrong that this 10-year-old might lose your money you might be thinking how could I trust them will they break their promise and this feeling of I can't breathe because of untrustworthy situations happens to us all the time can I trust this used car salesperson to give me a good car can I trust this tag that says machine watchable or will it make my shirt shrink will my insurance provider break their promise of covering my medical bills when I get hit by a bus when Patrick promises he'll go on a hike with me will he actually yes I I I actually will the issue with our current agreements and contract is we have to trust the people who are making them to do the right thing however often they're actually incentivized to not do the right thing insurance doesn't want to pay out money sometimes salespeople just want to get the off their shelves and with my girlfriend I promis to go on a hike but I hate hikes where else has this happened now you might be thinking okay Patrick this seems cool but like where has this actually affected me well the McDonald's Lottery that we just spoke about above during the Great Depression with the run of the banks banks Promise to keep our money safe and that when we went back to go get it they would actually have the money there and well and behold there were times that they didn't have the money there just last year Robin Hood painted this amazing picture come use our application we will give you access to the markets we promise we will give you a retail investor a fair chance of interacting with the world of Finance Psy but not this asset this asset this asset or this asset the 2008 financial crisis remember that shady deals behind closing do combined with lies about financial product brought the world to its economic knees how are you fing us hyperinflation in Zimbabwe hyperinflation in Brazil faos history is a Relentless lesson of trustworthy entities being notorious promise Breakers we finally have a way to fix it with smart contracts now before I jump into smart contracts a lot of people might be thinking hey cool and all however we have systems in place to protect against a lot of these things which is true and which is great and that is a helpful step forward but these systems often break ones in 2008 definitely didn't work the ones with the Robin Hood crisis definitely didn't work and even if these systems apply and you go to court to try to work them out maybe you're in court for years before you actually see a resolution and by that time what you need the money for is long gone so what is this technology what is this tool that can fix this fundamental problem in our agreements today this tool is smart contracts and this tool is what the blockchain was built for now I'm going to give you a quick overview of what a smart contract is however I'm leaving some links in the description for more in-depth explanations but the basics of them is a smart contract is an agreement contract or a set of instructions deployed on a decentralized blockchain and once the contract or set of instructions is deployed it cannot be altered it automatically executes and everyone can see the terms of the agreement the real basics of it is that the code is executed by a decentralized collective like a group of people but a group of people running a certain software this means that no one person or entity can actually alter any of these agreements or change the terms of the arrangement in these traditional agreements whoever owns the contract whoever owns the execution of the contract can flip a switch and say n we're not going to do that anymore in smart contracts in web 3 in blockchain you no longer can do that typically these smart contracts are in a decentralized blockchain and used in combination with a decentralized Oracle Network to get the real world assets and information and if the these words sound like I'm Conjuring up a magic spell well again check the links in the description if you want to learn more about the technical implications if you're not a technical person and you're not interested in getting to the NR you can kind of think of it like https I bet the vast majority of you don't even know what https stands for and yet you use it every single day whenever you lock onto the internet so how does this fix the McDonald's Monopoly issue in its traditional form the lottery was executed behind closed doors somebody operated and owned the code and the contracts and the agreements that ran the Lottery and they had the power to alter it and nobody other than the people internal on the lottery could audit this altering happening now if the code for this Lottery was deployed onto a blockchain every time a hacker attempted to alter it everyone would be notified not only that but you couldn't even alter it because the terms of a smart contract cannot be altered once deployed combine that smart contract with a chain link vrrf Oracle to get a verifiably random number and Presto you now have a perfectly decentralized unalterable agreement that is impossible to hack commit fraud or manipulate we have just saved the public between 13 million and $24 million just by fixing the issue of trust how does this fix Robin Hood well the problem with Robin Hood is already fixed right again the problem is that there's a centralized body that can flip a switch at any time and say yeah you can't access these markets anymore we're breaking our promise of actually giving you access to the markets this is already fixed with something called decentralized exchanges and these exist today one of these exchanges is one called Unis swap you can swap erc20 tokens which are kind of the equivalent of stocks but some aren't some AR it's a little confusing I won't get into that here either but it doesn't have that centralized body that can flip a switch and ruin access to the markets and had these investors been on a decentralized exchange it would have saved them hundreds of millions of dollars and it would have prevented fraudulent Market manipulation how does it fix run of the banks with transparency built in and autom at solvency checks you can build a bank like smart contract that has insolvency checks built in that make it impossible to get there insolvent means broke as any agreement or any history lesson where there was a trust assumption that was broken smart contracts can be applied to and should be applied to especially in a time where big money runs owns and controls everything we desperately need to move to a world where some self-interested centralized entity can't flip a switch and ruin people's access to the services that they need we can move away from a world that is brand-based to a world that is math-based right now if you interact with a service that you don't like or that they break their promise the only thing you can do is walk down the street to the next service that's going to make the same set of promises and you have to hope and pray that they're actually going to keep it we can move from that to a world where we can just look at the math and say oh okay 1+ 1 equal 2 this is what this agreement is going to do for me every single time guaranteed because it's a decentralized autonomous agent has no incentive to be evil and everything is transparent and out in the open I'm a big company and if it was better for me for 1+ 1 to equal three maybe I would go behind some closed doors and fudge some numbers and come back out and be like hey 1 + 1 equals 3 but with smart contracts that's impossible doing the right thing is infrastructural now given the choice between two agreements one where you have to trust a single centralized entity that they're going to do the right thing for you versus a decentralized untampered collective which one are you going to choose I'm picking the one that can't screw me over every single time for every agreement I can apply it to now this technology is relatively new but we have already seen it Rel landscape intire markets and continue to do so the traditional Financial world is already getting its lunch eaten by defi or decentralized Finance there's already over $200 billion dollar of people's money in these protocols to help have a more fair more accountable more transparent Financial system this D5 movement is one of the main reasons I got into the space because we desperately need to move away from where we are right now and end people's chances for wealth being sucked up by some group that's bending the rules in their favor and smart contracts are our ticket to that better World more and more Industries are also coming over to Smart contracts and blockchain because of all the Innovations and because of all the advantages that it has as we grow and as we get better we get closer to this vision of having this this concept fulfilled trust minimized agreements these smart contracts are minimizing the trust that we need to give other people in order for these agreements to be executed if trust minimized agreements is too confusing for you just say unbreakable promises now I got to be honest with you guys blockchains and smart contracts and cryptocurrencies can actually do more than just trust minimize agreements what they have Security benefits uptime benefits execution speed benefits and a whole lot more but it's a lot easier to just learn about one and learn the other ones later right it's kind of like sprinkles on on top so this is why we are here this is why we're building this future and this is why we are so excited about it last year 2022 there were a lot of issues with a couple different companies like for example spf's FTX platform the thing to me that's most frustrating about that situation is that FTX platform wasn't anything that I just talked about it wasn't decentralized it wasn't trustless it wasn't transparent it was purely a traditional web to company pretending to be web 3 and just using the cryptocurrency part of web 3 but not actually using the smart contracts and we're doing a much better job as a community getting rid of the Bad actors and this is something that's incredibly important for you when working with protocols and when building protocols I want you to be incredibly successful here but I want you to be incredibly successful because you're making a ton of value a lot of these platforms that we saw collapsing last year were not creating value they were stealing value they were siphoning value they were faking having value and as you learn and as you build smart contracts yourself it'll start to become innately aware of what protocols and what companies are centralized and are not the ethos of web 3 and the ones that are we are building verifiable trust minimized agreements unbreakable promises and if you can't verify those promises then it's not trust minimized it's not web 3 it's not what this industry is for that's what I want you to do as you finish this course is be a force for good unfortunately because a lot of people haven't taken my course not everybody understands the difference between a legitimate project and a token that's just meant to pump somebody's bags as this space continues to grow and as people like yourself take courses like this we will get to continue to push real legitimate projects forward and wash out the projects that aren't actually contributing even in just this introduction part we've learned a ton so let's do a quick summary of what we've learned so far Bitcoin was the first protocol to take this blockchain technology into the Limelight and take these cryptocurrencies into the mainstream Bitcoin is a sort of digital gold or a store of value able to make transactions between users in a decentralized manner ethereum and other smart contract platforms take this blockchain technology one step further enabling people to make smart contracts and decentralized Trust minimized agreements these smart contracts and decentralized applications can access and interact with the real world using something called decentralized Oracle networks chain link is a decentralized network that allows us to build these hybrid smart contracts which combines our onchain logic with our offchain decentralized data and decentralized computation giving rise to our logic being completely decentralized and our data and external computation being completely decentralized giving us all the features that traditional agreements and traditional contracts have now these digital currencies like ethereum and Bitcoin have value even without the smart contract contract part having a censorship resistant decentralized store of value is measurably powerful in its own right we have some links in the GitHub repository that'll teach you how this decentralized store of value flips traditional Finance on its head and it's another one of the great reasons for building smart contracts but again the easiest way to boil it down is trust minimized agreements or unbreakable promises but let's also go into some of these other features that smart contracts have over our traditional environment the first feature of course is that they are decentralized and they have no centralized intermediary the different individuals that run one of these blockchains are known as node operators and it's the combination of all these thousands of node operators running the same software running these algorithms running these smart contracts that make the network decentralized we'll dive deeper into how that works later the next feature is transparency and flexibility in these decentralized networks since all these individual node operators run this software everybody can see everything that's happening on chain meaning there's no Shady deals there's no weird things happening anything that's going to be unfair people would be able to see and just not use everybody has perfect information and has to play by the same rules now additionally this doesn't mean that there's no privacy the blockchain is pseudo Anonymous meaning that you aren't necessarily tied to an identity in real life they also have the feature of speed and efficiency for those of you who have ever tried to do a bank transfer or send money across Seas you know it sometimes can take 2 to 3 weeks when in fact all these banks are really doing is basic math they're subtracting money from your balance and adding it to some other balance why does it take so long in the blockchain all of these transactions happen instantly another instance for those in the financial world today know that clearing houses and settlement days can take a long time in the blockchain there's no need for any of that because they happen instantly this obviously is much quicker but it also makes for much more efficient inter actions with each other security and immutability again immutable means that it can't be changed once a smart contract is deployed that's it whatever is in the code is going to be in the code Forever they cannot be altered or tampered with in any way this means that the security is much easier whereas in a centralized World somebody can hack into the server jump out the database and change some numbers you can't do that in the blockchain world and since it's decentralized in order to hack the blockchain you'd have to take over half of the nodes as opposed to in the centralized world where you only have to take over one in the regular world if your computer and your backup computer go down all of your data is gone in the blockchain world if your computer and your backup computer go down all your data is safe because it's being run on all these other decentralized nodes and even if a few hundred nodes or if a few thousand nodes go down it doesn't matter because as long as one node has a copy of the blockchain you're good to go hacking a blockchain is nearly impossible possible and Leaps and Bounds more difficult than hacking a centralized server not only that but this is safer in the asset sense as well all you need to access your credentials and your information and your assets is your private key which is basically your password for all of this and as we've discussed in the video these smart contracts remove this counterparty risk remove this centralized intermediary remove these trust gateways that we have to do in web 2 when we engage with users and individuals they don't always have our best interests at heart smart contracts remove this counterparty risk because once one of these contracts is created they can't go in and they can't alter it and they can't let greed or ego or anything else get the better of them and alter the terms of the deal and as we said this gives rise to these trust minimized agreements or these programmatic unbreakable promises we move away from brand-based agreements to math-based agreements where we can look at the cryptography we can look right at the code and see exactly what something is going to do and how going to execute versus having to rely on a human being doing the right thing with smart contracts and decentralized hybrid smart contracts doing the right thing is infrastructural all these pieces boil down to us having the freedom to interact the way we want to interact without having to be afraid that interacting like that is going to screw us over this trust minimized piece these unbreakable promises make interactions so much better in the purely web 2 world we're constantly bombarded with messages of of projects and protocols pushing us to move or act in the direction that makes them more profitable versus in the smart contract space we can see everything transparently and we can even engage and interact and be partially owners of the protocols and the interactions that we decide that we want to be a part of but let's also go into some of these other features that smart contracts have over our traditional environment the first feature of course is that they are decentralized and they have no centralized intermediate are the different individuals that run one of these blockchains are known as node operators and it's the combination of all these thousands of node operators running the same software running these algorithms running these smart contracts that make the network decentralized we'll dive deeper into how that works later the next feature is transparency and flexibility in these decentralized networks since all these individual node operators run this software everybody can see everything that's happening on chain meaning there's no Shady deals there's no weird things happening anything that's going to be unfair people would be able to see and just not use everybody has perfect information and has to play by the same rules now additionally this doesn't mean that there's no privacy the blockchain is pseudo Anonymous meaning that you aren't necessarily tied to an identity in real life they also have the feature of speed and efficiency for those of you who have ever tried to do a bank transfer or send money across Seas you know it sometimes can take two to three weeks when in fact all these banks are really doing is basic math they're subtracting money from your balance and adding it to some other balance why does it take so long in the blockchain all of these transactions happen instantly another instance for those in the financial world today know that clearing houses and settlement days can take a long time in the blockchain there's no need for any of that because they happen instantly this obviously is much quicker but it also makes for much more efficient interactions with each other security and immutability again mutable means that it can't be changed once a smart contract is deployed that's it whatever is in the code is going to be in the code Forever they cannot be altered or tampered with in any way this means that the security is much easier whereas in a centralized World somebody can hack into the server jump into the database and change some numbers you can't do that in the blockchain world and since it's decentralized in order to hack the blockchain you'd have to take over half of the nodes as opposed to in the centralized world where you only have to take over one in the regular world if your computer and your backup computer go down all of your data is gone in the blockchain world if your computer and your backup computer go down all your data is safe because it's being run on all these other decentralized nodes and even if a few hundred nodes or if a few thousand nodes go down it doesn't matter because as long as one node has a copy of the blockchain you're good to go hacking a blockchain is nearly impossible and Leaps and Bounds more difficult than hacking a centralized server not only that but this is safer in the asset sense as well all you need to access your credentials and your information and your assets is your private key which is basically your password for all of this and as we've discussed in the video these smart contracts remove this counterparty risk remove this centralized intermediary remove these trust gateways that we have to do in web 2 when we engage with users and individuals they don't always have our best interests at heart smart contracts remove this counter party risk because once one of these contracts is created they can't go in and they can't alter it and they can't let greed or ego or anything else get the better of them and alter the terms of the deal and as we said this gives rise to these trust minimized agreements or these programmatic unbreakable promises we move away from brand-based agreements to math-based agreements where we can look at the cryptography we can look right at the code and see exactly what something is going to do and how it's going to execute versus having to rely on a human being doing the right thing with smart contracts and decentralized hybrid smart contracts doing the right thing is infrastructural all these pieces boil down to us having the freedom to interact the way we want to interact without having to be afraid that interacting like that is going to screw us over this trust minimized peace these unbreakable promises make interactions so much better in the purely web 2 world we're constantly bombarded with messages of projects and protocols pushing us to move or act in the direction that makes them more profitable versus in the smart contract space we can see everything transparently and we can even engage in interact and be partially owners of the protocols and the interactions that we decide that we want to be a part of so smart contracts have been around for a few years now and what have they generated for what industries have come about due to these smart contract platforms being around well you've probably heard of some of these and some of these we've already mentioned but let's give you a quick refresher defi defi stands for decentralized finance and it gives users the ability to engage with finance and markets without having to go through a centralized intermediary for example like we said with Robin Hood youd no longer have to trust that Robin Hood would continue to give you access to the markets you instead would be able to see in the smart contract yes I have access to the markets or in the 2008 financial crisis you never have to trust that these groups and institutions are giving you the correct things on the back end you can see everything transparently right on the blockchain you can engage with things like money markets and sophisticated Financial products easy effectively and securely if you're really excited about defi we have a ton of defi examples showing you how to build and interact with these protocols in coming lessons Dows or decentralized autonomous organizations are another group that we've already mentioned Dows are groups that are governed completely decentralized by a set of instructions or smart contracts on chain there are some massive benefits here where engagements much easier the rules are black and white and you can see everything directly on chain voting and governance technology is completely decentralized and the blockchain space is one of the big ones pushing how we can evolve politics and how we can evolve governance to make it more efficient fair and reasonable and you better know it we have some examples of how to build Dows and how to work with Dows in coming lessons so be sure to watch those nfts stand for non-fungible tokens and can really be kind of described as digital art or just a unique asset they can do so much more but we'll keep it high level for now projects like board apes and crypt punks have revolutionized the way that people get paid for their work show off their creativity status and so much more and yes of course we have lessons showing you how to create and interact with nfts as well so many other groups and so many other Industries are being created as a result of this insane technology and maybe after finishing the journey with us here you go out and you're be the one to Pioneer the next industry or the next billion doll idea you've learned so much already but now that we've learned a lot of this highlevel information let's finally jump in and let's make your first transaction and let's get you set up to interact with this new world in this next section we're going to get you a wallet and we're going to show you exactly what a transaction looks like and feels like let's dive in this is the ethereum website ethereum.org we are going to make a transaction on a test ethereum blockchain I'll explain what that means in a little bit this is going to be our first ever transaction that's made on the blockchain and this process of making a transaction is going to work the exact same across all evm compatible blockchains and layer 2os like arbitrum ethereum ZK sync and Etc I'll explain what evm means in the future for now just follow along and have fun running your first transaction now in order for us to send a transaction on any of these EV chains the first thing that we need to do is set up a wallet so I'm going to go to metamask because it's one of the most popular wallets and one of the easiest wallets to use I'm using the brave browser but it works for Chrome or Firefox or really any other popular browsers out there and it's just going to be an extension in the top right hand of our browser it's going to make it very easy to see anything to do with our wallets and our transactions very easily and it's going to store all of our evm based currencies and evm based trans transactions so I'm going to go ahead and hit add to Brave ADD extension although Brave does also come jam-packed with its own wallet so now we come to the get started page and I'm going to go ahead and select create a new wallet sure we'll agree to help out metamask now we're going to create our password make sure it's really secure for the purpose of this demo mine's going to be kind of mediocre now I'm going to preface this this wallet that you're making right now as you follow along with me this is going to be your development wallet so if you want to make the password a little bit weak just so that you can test things out very quickly go for it just know we're never ever going to put real money into this wallet it's good if you treat this as if it is a real wallet that way you'll get used to and you'll get familiar with good wallet safety you will then get a video like this which will teach you about the secret recovery phrase which we saw a little bit earlier when we were creating our wallet let's watch this video metamask is a new way to connect to sites and applications on traditional websites a central database or bank is responsible for controlling and recovering your accounts but on metamask all of the Power belongs to the holder of a master key whoever holds the key controls the accounts your secret recovery phrase is your master key it's a series of 12 words that are generated when you first set up metamask which allow you to recover your wallet and funds if you ever lose access it's important that you secure your wallet by keeping your secret recovery phrase very safe and very secret if anyone gets access to it they will have the master key to your wallet and can freely access and take all of your funds to secure your metamask wallet you'll want to safely save your secret recovery phrase you can write it down hide it somewhere put it in a safe deposit box or use a secure password manager some users even engrave their phrase onto a metal plate nobody not even the team at metamask can help you recover your wallet if you lose your secret recovery phrase if you haven't written down your secret recovery phrase and stored it somewhere safe do it now we'll wait and remember never share your secret recovery phrase with anyone not even us if anyone ever asks you for it they're trying to scam you that's it now you know what a secret recovery phrase is and how to keep your wallet safe and secure awesome so that was a great introduction to keeping your wallet safe we'll talk a little bit more about safety with our wallets in the future let's go ahead and select secure my wallet now this is where we need to write down our secret recovery phrase and save it in a very secure place it gives us some tips here like a password manager a safety deposit box or split it up and keep it in multiple secret places for the purposes of this video I'm going to be showing you the secret recovery phrase because I'm not going to put any real money into this but you should never ever do this additionally you'll sometimes hear pneumonic as a synonym for secret recovery phrase the main takeaway from all this is you should never share any of this this is for you only if you show this secret phrase to anybody else they will have access to not just one account but every account that you make in metamask so be absolutely certain to not share this with anybody so again I know I'm belaboring the point a little bit but everything that we're going to do in this tutorial we're going to do with fake money and fake assets and never put actual money into this account that we're making here once you get familiar with using metamask and working with the tools and stank secure then you can go ahead and create a separate metamask that will have real funds in it if you want to put real money in different metamask a lot of browsers have a profile option and maybe you can make a new profile install metamask on that different profile call that profile real money profile or something and that's where you will store your money but for this video for this tutorial the metamask that you are using is going to be specifically for testing things out and you will never store real money to it I'm going to harp on that a lot more in this so even if you're coming here and you have a wallet I highly recommend still making a brand new one for this tutorial just in case you don't accidentally code something or do something autonomous and give away your funds if this is your first wallet then great but again when you're working with real money if you lose access to the secret phrase you will lose access to all your money so be sure to write this down promise me that you won't use real money for this course great I'm going to hit copy to clipboard for now and we're going to go ahead and hit next now we need to confirm by adding our c phrase back in we can go ahead and hit confirm and we now have created our wallet let's go ahead and clict got it awesome now we can see the interface of our metamask full screen and depending on your browser what you can normally do is hit this little puzzle piece on your browser and select this pin button so now we can pin our metamask into the top of our browser and we can click it like so and we can see it give a little drop down like this and we can see the same information in this little drop down as the is on the full screen now even if you lose access to that page now that this is bookmarked in your browser you can select your metamask select these three dots and hit expand view to reach this tab now additionally what we can do in here is we going actually go up to our accounts and we can actually create multiple accounts by hitting create account and if you wanted to you could give it a name here I'm just going to leave it as default for account two and now we have two separate accounts we have an account zero with an address and an account two with an address as well both of these accounts actually share that same secret phrase so anybody with access to the secret phrase can actually have access to both accounts however they have different private keys and that's what makes them different we'll talk a little bit more about that in the future if somebody gets access to a private key they'll get access to a single account if they get access to the secret phrase they'll get access to all the accounts that you make even you know if you made a third one they'd get access to this one as well now if you look up in the top right of the screen here you'll see this section that says ethereum mainnet this is our networks Tab and if you click it you can see all the different networks that our metamask has access to ethereum mainnet is the main network of ethereum and this is where real money is spent and used for this course we're not going to be working with ethereum mainnet we're instead going to be working with something called a test net for both engineers and non-engineers we often need a place to test or simulate our transactions and for the developers here throughout this course we are going to teach you another technique for testing out your transactions on a local network and a local network is actually going to be the preferred way we do our testing and our simulations however it's still really important to see end to end what a real transaction looks like and that's what a test net will do for us it simulates exactly what a mainnet or a live Money Network would look like however there's no real money at stake and we don't actually have to spend any money to see some of the test Nets that come default with metamask we can hit the show/hide button which will bring us to the settings page of metamask we can turn on show test networks and if we scroll back up now if we hit our networks tab actually let's go ahead close out of settings now if we hit this drop down we can see gelli test Network sapoia test Network and Linea gelli test Network these networks are test networks that resemble ethereum or polygon or Linea or arbitrum or optimism or ZK sync or any other evm compatible chain that we want to work with and again we'll Define evm in the future and we can actually switch the network that we're working on simply by clicking another Network so let's switch to sapoia we can see our Network changed up here and now we can see we have zero seoa eth so on eth mainnet this new account has zero ethereum and on the sepolia test Network we also have zero spolia eth which makes sense because this is a brand new wall wallet and we haven't put any money into this brand new account yet so of course we have zero at the time of recording sapoia is one of the most popular test networks out there so we're going to be working mainly with sapoia throughout this course however test Nets often change because again they're run out of the goodness of people's hearts and sometimes people stop running them you should absolutely have either the web3 de. education site up or the GitHub repository associated with this course and an important note sometimes you'll see this as the chain Excel org Foundry F course we recently renamed it to The cyphon Foundry F course so this is the correct link but if you see chain excl org that's fine as well and you should scroll down to the recommended test Nets section to make sure you're on the most up-to-date test net at the time of recording like I said we're working with sapoia throughout this course we are going to show you how to work with different testnets and different networks as well because it's incredibly important to do so the blockchain world is moving into a multi-chain world and especially with the PO ity of l2s which help ethereum scale learning the differences between different chains and different l2s is incredibly important now same as ethereum what we can do is we can actually go to sepolia etherscan so we'll go to sepolia etherscan.io and we can grab our address from metamask by clicking and copying the address here pasting it into the sapoia Explorer and same as ethereum we can see our account balance we have zero eth there are no transactions no token transfers nothing because obviously it's a brand new wallet now I'm showing you this because pretty soon we're going to send our first ever blockchain transaction if you've never sent a blockchain transaction before we're going to do it on this test net to give you some confidence as what a transaction actually looks like when you do move over to a main net and I'm showing you this site now because you're going to see when we send a transaction a lot of this information is going to get updated now just remember like I said earlier a test net is run out of the goodness of people's hearts so please use the transactions sparingly once you send your first transaction here try not to send too many more as one is good enough for you to see what's going on anyways and in order for us to simulate one of these transactions we're going to go to a faucet or a test net test Nets have this thing called faucets which allow us to get some free sapoia eth so that we can test out sending transactions and receiving transactions if you go to the GitHub associated with this course or web 3d. education we can scroll down to this test net faucets section and select one of the links to go to one of these test net faucets right now the recommended faucet that we're working with is faucets. chain. link But be sure to use the GitHub repo or web 3d. education to be most up toate what this is going to do is we're going to ask this faucet site to send us testnet ethereum and this is why this test net ethereum isn't worth any real money since we can get it for free anytime that we want these obviously don't exist on mainnet you can't get free mainnet ethereum via a faucet now what we can do is we can actually connect our wallet to this site and we can get some free test net sapoia eth this will make it so that in our balance here we'll actually have some sepolia eth to play with so to do this what we're going to do is we're going to go ahead and hit connect wallet except the chain link terms of service I've already read them our metamask is going to pop up to connect it to this website now get from familiar with this interface because this is how websites will interact with our wallet and interact with the blockchain connecting our account to the site we'll first select the specific account that we want to connect we're just going to choose account one we'll hit next and then we'll go ahead and hit connect and now we can see our wallet address in the top right and we can see that we're connected on the ethereum sapoia testet if we go up to our wallet and we actually switch to ethereum mainnet you can see that the website has actually changed this little dropdown to ethereum name net and if we go in here we can actually switch to ethereum sapoia and our metamask will pop up with this switch Network button which will help us switch the network for us so now we're back on seoa test Network connecting to these websites is how we give these websites a way to interact and connect with our wallets we can go ahead and select this hit these three dots and hit disconnect this account but don't worry anytime we want to send a trans transaction the website has to ask us if we want to send a transaction so just by connecting to the site it won't actually send a bunch of transactions for us and if we scroll down we can see our wallet address is placed right here and we can see we can request test link and we can also request test e for now we don't need any test link so we're going to leave that off but in the future we will come back to the site to get some test link for now we're just going to get 0.1 test ethereum and if all goes well we should hopefully see it in our saoa eth here in order for us to get this test ethereum we do have to log in Via Twitter if you don't have a Twitter you can use any of the other Faucets in the test Nets faucets area of the GitHub such as the Alchemy sapoia faucet or the seoa proof of work faucet but if you are on Twitter now is a great time to give me a follow maybe give me a shout out and maybe say hey sending my first transaction thanks Patrick Alpha cop or not whatever you want to do just some light Shilling of my own Twitter account anyways we can log on Via Twitter we can authorize this app verify that we're human give our AI overlords The Prompt here oh make sure we don't select the link and let's go ahead and send the request now what's going to happen is it's going to give us this transaction hash on sapoia and after a delay we'll see it go from initiating to waiting for confirmation to token transferred and we'll see a transaction hash and if we click the transaction hash we'll see a transaction that was sent to our address so this will be the first transaction that we get to see and there's a ton of information here but the most important piece is if we open up our metamask now we can see we now have 0.1 spolia eth in our account and if we copy the address again we paste it into here we can see now we have a 0.1 eth balance you might have to wait several minutes for the transaction to finish going through and if you accidentally refresh your browser again we can go ahead and just select our metamask copy our address and paste it into ether scan or just view it right in our metamask here and if you missed that piece about the transaction data if we go back to Ether scan with our address remember we're on sepolia ether scan and we scroll down we can see this most recent transaction hash that just occurred and we can click the link here and we can see that detail about the transaction again here now importantly remember though this is on sapoia if we switch back to mainten ethereum you'll see we have zero eth on mainnet ethereum if we switch to gly test Network you'll see we have zero gly eth on that network if we switch to Linea gelli eth or any other network other than sapoia you'll see that sapoia is the only one that has the 0.1 sapoia eth if you want to practice working with a different test net feel free to scroll up back to the faucet select a different test net and try to get testnet in one of these different test test Nets just be sure to take a look at what test Nets your metamask comes with since some of the networks this faucet is compatible with don't come built into our metamask but again like I said in the future I'll teach you how to add these different networks to our metamask in the future but huge congratulations you received your first transaction because again this faucet is US asking them to send us money it's not us sending money it's them sending money to us and if this is the first trans that you've ever sent you should be proud of yourself already give yourself a big pat on the back and here's a picture of me holding a cat with that cat's face all over my pajamas as a congratulations now once more let's grab our address paste it into ether scan here and scroll down and we're going to learn a little bit more about what actually went down what actually happened in this transaction you can see on ether scan it gives us some basic details it says from and to from is going to be another address a different address an address controlled by the faucet and two is obviously going to be our address and if we select this transaction hash we can see even more details in here understanding all these different fields is essential to becoming a smart contract developer and even just a web 3 or ethereum or blockchain user so let's learn a bit of the basics of what's actually going down in this transaction the first field on this page is the transaction hash you can even see a little question mark here which tells you a little bit more about it it's a unique identifier for this specific transaction on this network so this specific transaction hash we can even copy and paste this into the address bar and we'll get the exact same transaction back this is the only transaction in the entire blockchain that will have this transaction hash it's the unique identifier it identifies the transaction of sending 0.1 eth from the faucet address to our address we can see the status of this was successful we can see the block number and the number of block confirmations which we will explain in the future we can see the time stamp which of course is when this transaction occurred we can see the from and to who initialized the transaction and who it was sent to if we select this from and open this in a new tab we can see some details about who actually sent us this test eth and if we go back to the transaction detail and keep going we can see the value here which again if we roll over it's the value of ether or test ether and then in parentheses the Fiat value or the dollar value which of course since this is a test net it's always going to be zero the value of this transaction was 0.1 eth now what's underneath this value thing this transaction fee and this gas price thing what are these if we zoom in a lot more to these pieces here and we roll over transaction fee we can see it says it's the amount paid to the block producer for processing the transaction and and then gas price is going to be the cost per unit of gas specified for the transaction in ether or guay the higher the gas price the higher the chance of getting included in a block I'm going to explain that in a little bit but if we scroll down even more let's Zoom back out and we click click to show more we can see even more details about this transaction for now we're just going to click to show less and just focus on the details that are here so let's talk about just the concept of transaction fees and gas for a second because they are important concepts for you to understand remember how I said that these blockchains are actually run by a group of different nodes well the question is what's their economic incentive to keep running these blockchains are they running them out of the goodness of their heart well on a real Network these nodes actually get paid a little bit of ether for processing transactions whenever you send a transaction there is a node sometimes referred to as a miner or a validator depending on the network you're on who gets paid a little bit of the Native currency of the block blockchain to process that transaction for ethereum they obviously get paid in ethereum or for test ethereum they get paid in test ethereum which again the test ethereum is worth nothing which is why I said they're running them out of the goodness of their heart if you're sending a transaction on the polygon Network they're going to get paid in madic the native token of polygon if you send a transaction on an L2 like arbitrum or optimism you're going to get paid in eth which is the native token of those l2s this payment is obviously to incentivize people to continue to to run noes and they get paid more the more gas you use so what is gas gas is a unit of computational measurement the more complex your transaction is the more gas you have to pay for example if we hit more details just really quickly and I zoom in a little bit more we can see this section here gas limit and usage by transaction this means that when we sent this transaction we limited it to a maximum of 60,000 gas but in total we only used 21,000 gas this 21,000 gas represents how complex this transaction was it was 21,000 gas units worth of complexity now for simple things like sending ether the units of gas are usually pretty small for example 21,000 units of gas is actually a really small amount of gas being sent but maybe for more complex transactions like minting an nft depositing some funds into a defi protocol or deploying a smart contract those are typically going to be more expensive transactions because they're more complicated they have to do more stuff in the future we'll introduce you to this concept of evm codes or op codes and if you break down a transaction to the lowest level this assembly op code stuff you can actually see exactly how much each op code costs in terms of gas don't worry about this at all right now just know that these transactions are broken down into many many many many very very small instructions and each instruction has a specific amount of gas the more instructions usually means more gas like I said we'll explain this much later in the course don't worry about this too much here but just know that we use 21,000 gas now if you take this gas used and multiply it by the gas price in eth instead of guay so we'll take 21,000 and multiply by this gas price in eth not in guay and hit enter we'll see the total transaction fee of the transaction and you can see that this number does indeed match the transaction fee for you to understand how much eth you're going to pay for your transaction you multiply the gas price times the gas used transaction fee equals gas price times gas used so this means that whoever sent us this 0.1 eth also paid 0.525 blah blah blah eth to a blockchain node to a validator on the sapoia ethereum test net now each blockchain has their own unique way of calculating how much transaction fee someone's actually going to pay for most evm chains this is the simple algorithm it's going to be gas used times gas price after we understand how the blockchain works more in depth I'll explain to you what the rest of these values stand for for now just know that anytime you make a transaction on chain you have to pay the validators or the blockchain nodes a little bit of gas or a little bit of the Native token of of the blockchain which in our case is eth so you have to pay a little bit of eth to the blockchain nodes providing or sending the transaction sometimes I'll refer to this just as transaction gas let's look at an example of this ourselves if we pull up our metamask we go ahead and hit expand view as we know we have two different accounts in here we have account one and account two account one has 0.1 spolia eth count two has zero spolia eth if I send 0.05 from account one to account two how much do you think I'll have left in account one let's go ahead and do this and this is going to be the first transaction that you send on the blockchain which is incredibly exciting as well let's go ahead and hit this send button in our metamask we'll hit send we'll hit transfer between my accounts we'll select account two and we'll say 0.05 sapoia eth so we started with 0.1 suppo eth and we're going to send 0.05 to account two we'll scroll down we'll hit next we can see some information here about what's actually going on we can see some gas information which metamask automatically prompted for us and it even gives us the total amount that we're going to be paying in eth it's adding this 0.05 eth to the estimated amount of gas that we actually have to spend so that at the bottom it says the amount plus the gas fee is the two of those combined the value that we're sending plus the gas fee and additionally in metamask if you select this here you can get get some more information about editing our gas fees the amount of gas that you choose to spend can be different depending on how many people are making transactions with blockchain the more people are sending transactions at the same time the more expensive gas costs are going to be so if a lot of other people are also sending transactions right now the gas price is going to be higher if a lot of people are sending transactions that means there's not going to be enough space for everyone's transaction to get through so in order to throttle that they increase the gas price that's a bit of an oversimplification of what's happening but if you take that understanding that'll pretty much work if you want to specify exactly how much gas you want to spend you can click the advaned tab if you select zero gas there's a high likelihood that your transaction will never go through so we're just going to go with the default which is usually a good idea so let's go ahead and confirm we now see a send transaction in our Q in the activity tab of our metamask which shows us that we have a transaction currently sending and if we click on it and click view on block Explorer it'll actually open us up on ether scan and we'll see well mine was a little bit quick but normally we'll see a little indexing Tab and we won't see this having gone through we'll see it as like indexing or sending or something like that but after a little bit it'll actually finish sending you might have to wait a minute or so for this to actually finish going through but it looks like mine was really quick and same as our last transaction this has a lot of the same information and of if we scroll down we'll see that of course we sent a different amount of eth 0.05 and we have a different transaction fee now if we pull up our metamask what do you think that we're going to see we're going to go ahead and click expand view again and we see account one says 0.05 and account two also says 0.05 hm that's kind of odd I thought we spent some gas well if we click on the big accounts button we can see exactly how much eth is in each account you can see we have 0.499 in account one and 0 05 in account 2 and we can see in our activity history our account one recently sent 0.05 eth and account two recently received 0.05 sapoia eth now here's the best part of all this even if you don't want to become a developer you just learned the basics of sending a transaction and interacting with sites using your metamask congratulations now here's something that's incredibly exciting with just this little bit of information you now know how to interact with blockchains and interact with the ethereum protocol so if you don't want to learn how to code anything you can go and you can start interacting with ethereum and interacting with protocols with just this much information however I know most of you guys are here to learn how to code so let's look under the hood of ethereum and what is actually going on with these transactions and with these gas and with these blockchains and what's really going on let's learn all the fundamentals of a blockchain now if you want to just go ahead and jump into the coding go ahead and grab a Tim stamp from the description however learning exactly how the blockchain works is going to make you an incredibly powerful developer so let's take a look at that first so we're going to be going through this blockchain demo on this site right here now the creator of the site has a fantastic video and a fantastic walkth through blockchain 101 it is right on their site so if you're looking for another explanation definitely check out his video it is absolutely fantastic but the first thing that we really need to do in order to understand blockchain in order to on really anything and everything that's going on here we first really need to understand this shot 256 hash or hashing just kind of in general let's first understand what a hash is a hash is a unique fixed length string meant to identify any piece of data they are created by putting some piece of data into a hash function in this example uh the hashing algorithm used is Shaw 256 now ethereum actually uses uh this uh this right here for its hashing algorithm which isn't quite um sha 256 but is in kind of this Shaw family but it's it's really just another way to Hash things and uh the specific hash algorithm doesn't matter uh so much so uh this example uses sha 256 but you can imagine it's the same as the ethereum hash they're just going to you know result in a different hash so what's going to happen in this application here is whatever data or whatever information we put into this data section here as you can see below this hash changes so what's happening is this data is running through this sha 256 hash algorithm and it's outputting this unique hash so this hash is a unique fixed length string that's going to identify like a blank data piece here right so if I put in you know my name like you know Patrick Collins this is the hash that's going to represent Patrick Collins right and you can see even when I put you know tons and tons of data in here the length of the string doesn't change right so it's always going to be the same amount we can put almost any amount of data in here there is an upper limit on the max size of the data but for all intents and purposes we can pretty much put any length in here and you'll see too that you know every time I type in Patrick Collins this hash is always going to be this 7 e5b right I'm going to delete it I'm going to do Patrick Collins again you 7 e5b it's always this this unique hash is always going to be unique right it's always going to be this fixed length string here so so now we can take this idea right of putting this data in here and we can move on to uh this concept of a block so with this block concept we're going to take the exact same thing with this hash this this data section right but instead of having everything just being in this this singular data area right here we're going to split this data up into block nuns and data so all so what we're going to do is we're actually going to Hash all three of these to get to get this hatch right we're going to put all three of these we're going to say all three of these are combined uh together we're going to put every all three of them into this hashing algorithm uh to figure it out so if I type a bunch of stuff here we can see that block one with nuns you know this nuns and this data we're going to get this hash and as you can see actually the screen turns red this block turned red now what happens when I hit this mind button when I hit this mind button it's actually going to take some time it's going to think for a little bit and we can see that the nuns here actually changed right the nuns is different from what it was before and this hash now starts with four zeros okay and then it the back turned green when we're talking about mining we're talking about miners solving some type of very difficult problem that takes a lot of time to do now in this example here the problem that uh the miners had to solve was they had to find a nuns or or a value in this nuns section that when hashed with at block number one with this data it would start with four zeros so the problem here the minors had to solve was to start with four zeros and the only way for them to really do that is kind of this Brute Force you know trying stuff so they tried one okay one didn't work okay two nope two didn't work three no four five six okay five well that started with one zero but that's not four and they have to keep trying all these numbers until they uh get to this one where you know let's hit mine again where it has four zeros at the top at the start now this specific problem changes blockchain to blockchain right ethereum has a different problem for miners to solve um Bitcoin has different problems for minor solve but this concept is going to be the same and since ethereum is proof of stake now nodes actually take turns solving these problems again we're not going to go too deep into that right now though so they have to take um one block is going to be this this uh this concept is going to be all this data it's going to be the block number and it's going to be this nuns right and so this nuns is the solution um is is going to be the the number that they use to get like the solution to the problem right so if I go to one here you know and I do this again I'm going to hit mine and the nuns has changed right it went from one to 33,100 and so that's what's happening when uh blockchain miners are mining they're going through this process this very computationally intensive process of trying to find unnown that fulfills whatever the problem is so that's really it actually so that's a block and and that's really what's happening when miners are mining they're just looking there's trial and error Brute Force trying to find this nun so so now that we know what a block is let's go to the next step and figure out okay well what's a Block Chain so here we have an example of what a block chain is going to look like right we have a combination you know we have back here in the block section we have one what one block looks like now here we have multiple different block blocks right each one of these represents a different block but we have an additional column here or we have additional uh variable here so like before you know we have block NS and data right we have block nuns data but we also have this thing called previous right and so this is actually going to be pointing to the previous hash of the last block so for example if we go to the the last block in this blockchain it says previous is 00 A8 and if we look at the hash of block number four it's 00008 E8 and then we look at its previous it's 4 Z's B9 we have 4 Z B9 and so on all the way back to our first block which has previous of just all zeros right and so the block with the previous of all zeros is going to be known as The Genesis block so you've probably heard that before the Genesis Block it's the first block in the blockchain where the previous hash points to a hash that uh doesn't actually exist now as you can imagine kind of the same as how this block worked how the block NS and data all go through the hashing algorithm in the blockchain the block nuns data and previous hash all go through this hashing algorithm to figure out you know what the hash is okay so if we go to over here you know for example if I type in you know Patrick obviously this is now no longer valid right because this nuns uh combined with the block the data and the previous hash aren't going to solve you know our problem of having four zeros at the at the start right so I'm going to go and fix that and and that's that's kind of an easy way to to see it being broken but but let's take a look if I break this block right here what happens if I if I break the data in here if I do like Patrick in here you can see that both of these are now readed both of these are now invalid right because the block hash with the nuns hash with the new data which is my name Patrick hashed with pre hashed with the previous block is now a brand new hash right and this block is still pointing to this previous hash right here right is pointing to to this previous block and now it is wrong and it is messed up and now um and now its Nuns with this previous hash is also wrong right and this is where when we talk about uh blockchains being immutable this is exactly how it's immutable right because if I go back and I change anything you know if I just typed a right here the entire blockchain is now invalidated because none of these are going to have uh nses that solve this equation anymore so this is why blockchains are immutable is because anytime you change one thing you ruin the rest of the blockchain okay so however though you know if if a was here originally we can go ahead and mine these we can mine all these but as you can see you know this is going to start getting very uh computationally expensive because I have to go redo uh basically the entire blockchain uh and the farther and farther down the line you get the harder and hard it becomes to you know rehash and and redo all these different blockchains here now this makes a lot of sense right so we have this blockchain it's really hard to change something in the past but if we do we can just go ahead and remine it now if I'm the one who controls the blockchain right if I'm the one who controls this you know and I want to change something in the past well okay great all I got to do is change this data here and then you know mine each one of these you know obviously it's going to be very computationally expensive but it's something that I can do right if I'm the one who owns the blockchain now here's where the decentralized nature or the distributed nature really uh makes it incredibly powerful so we're going to go to the distributed tab here which I also refer to as the decentralized tab here and it's going to show us what a blockchain looks like uh in a decentralized manner so we have this exact same uh initial setup here we have distributed blockchain we have you know the our first blockchain which is kind of exactly as the one from here but we also have more than one so we have Pier a pier B and Pier C and when people are talking about peerto peer peer-to-peer transactions they're really talking uh this is kind of that concept that they're talking about right so we have a number of different peers who are running this blockchain technology they're all weighted equally right each one of these peers or each one of these nodes each one of these entities running a blockchain has the exact same power as anybody else right so the way that we can tell very easily which blockchain is correct or which ones are correct are by looking at this end hash here right are by looking at where we are uh in the blockchain because again remember because again remember this this hash that this this in this last block here is going to Encompass all of the blocks from before right because this last hash is going to have the previous hash here which includes the previous hash here which this hash includes the previous hash here and which so this last hash is encompasses everything in here right and we can look we can look at the hash of Pier C which is four zeros and then e4b we can look at the latest hash of pi b which is 4 Z e4b and then Pier a which is 4 Z e4b so all of these peers all of these nodes all of these decentralized you know these independent um all these independent users running this blockchain software they're all matched up it's very easy for their nodes to look at each other and say hey great we are all matched up now what let's say that a decides that you know something happened on the blockchain that they didn't like and they wanted to go back and change something right so let's say they change here you know obviously uh the rest of their block is invalidated and they have to spend a lot of computational power to catch up to speed so let's go ahead and humor it let's say that they they did they ended up catching up uh they ended up catching up you know they ended up mining everything and now they have a valid blockchain right it solves the equation awesome however in block number three there's something new right this is here and it shouldn't have been here this is something that perer a put in by themselves all that happens now is we look at all the blockchains that are running the software and we're looking at all the hashes at hash at block number five so Pier a has this new hash now 009 BC but Pier B has a different hash 00 e4b right so who's right is it is it Pier a with their new stuff or is it Pier B well that's where the decentralized comes in because then we can look at Pier C and Pier C also has e4b so Pier B and Pier C both say hey p a you're wrong get out right and P A will stop being able to participate in the mining rewards because they have essentially forked uh the blockchain and started their own little blockchain right with their own history because they're the only ones with this this piece of data in block three whereas Pier B and Pier C have nothing in there so that really shows why uh in these block worlds in this decentralized world there really is no centralized entity you know perer a you know might have been maliciously motivated to change you know this this block number three however democracy rules right the majority rules in the blockchain pier B and Pier C both say Hey you know that that's cute and all per a but you're wrong right that that's not right now it might be a little abstract that you just look at data and you know us typing kind of random stuff in here and think okay yeah that's that's data right that makes sense you know just kind of random strings in here doesn't really do anything for us so if we actually go over to the Token section here this is where everything really starts to make a lot of sense so we have the exact same setup here uh with Pier a pier B Pier C except the difference is instead of having kind of this this data section we have this uh TX this transaction section right and this represents all the transactions that are happening in this block right so we're we're sending $25 from Darcy to Bingle or to Bingley uh four uh $427 here 1922 right and it's the exact same thing so this all these transaction are going to get hashed in the exact same way uh that the data is going to get hashed and and this is why it's so powerful because again you know if I want to be malicious right if uh if I wanted to say hey I I really wanted to give Jane a lot more money from Elizabeth so I'm p and I go back and I change it to 100 well now you know not only do I does my whole blockchain uh get invalidated because that was so far so long ago but I'm not going to match any of these other chains right and so my blockchain is going to be excluded from overall blockchain so and let's let's go ahead and fix this and it's the same thing if down here if I I become malicious and I want to send you know I want uh Miss Audrey to have less money maybe I want to send a dollar and I go ahead and mind it the same thing here this hash now this 2a1 is not going to match pb's pb's hash of BBA and it's not going to match PC's hash of BBA as well so the two of them are going to say hey this your blockchain is invalid it's not matching the majority you know you're out right so that's really how uh these blockchains work at a low level and it all goes back to this this understanding this hash idea and using it in this very sophisticated manner uh to kind of cryptographically prove um you know where where stuff lies now the way the blockchain works is you instead of random stuff put in this data section it's actually going to be solidity code in here finding ways to interact with different blocks and different protocols that are on chain or as we've said before different smart contracts now the next question that you might be asking is okay well how do I know how can I be sure that I'm the one uh you know let's say this is let's say I'm Darcy right how can I be sure that I was that Darcy was the one to actually send this money here how do we know that Darcy sent $25 to uh Bingley well this is where we get into uh private keys and public keys and that's what we're going to go into now let's just do a quick recap of what we've learned in this section so far right we've learned that ethereum actually runs on this Kack 256 but you know we used sha 256 for this demo it doesn't really matter we're just talking about hashing algorithms so again a hash is a unique fixed length string meant to identify any piece of data a hash algorithm or a hash function is a function or algorithm that computes any type of data into a unique hash mining is going to be the process of finding the solution to the blockchain problem in our example the problem was finding a hash that starts with four zeros nodes get paid for mining different blocks and the problem is going to be different blockchain to blockchain a block in a blockchain is basically a combination of a block nuns transaction and a previous hash to create this unique hash for this block and again depending on the blockchain implementation this might have a couple other fields or might have different fields but this is essentially what's going on blockchains are decentralized and distributed because many independent users are going to run this blockchain software and they will check and they will compare against each other to see which blockchains are acting honestly and which ones are acting maliciously in the blockchain world majority rules the nuns here is the answer used or the number used to get this hash now nuns is kind of an overloaded term it's actually used for a number of different reasons in this case we're using it to solve this problem of getting you know four or five zeros at the stop of the hash however in ethereum it'll also be often used as the number of transactions from a given address so now we're going to talk a little bit about signing these transactions and and private keys and and some other cryptography pieces right because in this blockchain demo here we can see we have all these these fantastic transactions right all these things went through but how do we know that it was Darcy who is the one to send $25 uh to Bingley right how do we know that actually happened happened and this is where all those pieces that we just learned about uh in our our test net in our metamask account are really going to start to to come to life here a little bit here so here we have an example of public and private Keys okay at the top we have this private key right that was that was randomly generated uh a private key is is you know as it kind of states is a key that you really want to keep secret because you're going to be using this uh as kind of your your secret password for all your transactions right I can really pick you know any any any private key anything that I want and with it uh this algorithm uh they're going to use an algorithm you know for ethereum and Bitcoin they both use this elliptic curve digital signature uh algorithm it's it's a variant of just a digital signature algorithm and it's going to create this this public key right I'm really not going to go at all into kind of this digital signature algorithm but just know it does use some of these uh some of the hash uh knowledge that we just learned combined with some other pieces to kind of get this this public key here so I'm not going to go too deep into it but we have this private key that we create and we get this public key now this public key we want everybody to have access to right this is yeah whole world can see this this private key we really want it to be uh private we don't want people to see this we're going to use this private key as like a password to quote unquote digitally sign transactions and then people can verify them with this public key so let's let's see what this actually looks like let's pick a a random key a more secure key right because the longer it is the more secure it's going to be and if we go to signatures now right um let's say we have this uh this message that we want right we's say high world right we want this to be the message what's going to happen is this private key that we've created we can use to sign this data right remember how in the blockchain demo you know we were kind of we were hashing stuff right we were we're using this shade 256 hash to to get this hash well we're doing something similar but instead of hashing we're we're using this digital signature algorithm to create this message signature now what's really powerful about how this uh this algorithm works is that you can create this message signature with your private key but somebody else can't derive your private key from the message signature and that's what makes this really really powerful however if we go to verify using this public key right uh and so this is the this is that 0403 this is that same public key using this uh using this public key anybody can verify oh let's go ahead and sign it again anybody can verify that this signature is yours right so you have a public a private key just for you so you can sign things and a public key so that anybody can verify something right so anybody can verify this and let's say somebody tries to fake a transaction from you they say Hey you know this is this is this is their transaction um all they have to do is verify ver ify that this signature against your uh public key and very easily this whole thing turns red because uh it isn't verified right the the algorithm says Hey uhuh that's wrong so we can go ahead and take that into transactions in this exact same way so if I want to send money you know if I want to send $400 from you know my address to another address using my private key I can sign that transaction and anybody else in the the world can then verify this transaction right and this is why when people say hide your keys you know protect your keys this is what we're talking about in our accounts here right if we go to uh settings and again the only reason that I'm showing you guys my pneumonic and my private key is because this is a uh this is a dumpster account I'm going to throw this away at the end of this video or I'm just not going to put any real money in it um but when we look at our our our metamask here we have this pneumonic phrase which allows us to easily get these different private keys right so uh pneumonic phrase combined uh with you know uh whatever account number will get us a private key so pneumonic phrase combined with one we're going to get this private key and this is when we look at Account Details export private key password confirm this is going to be the private key that we're going to use to sign our trans transactions right this if anybody else gets access to this private key they then can sign transactions for us and they can send transactions for us and that's why we want to keep these private so uh it works the exact same way right so this is why it's so important to hide your private keys and hide your pneumonics now your ethereum address is actually a piece uh is actually a piece of your public hey now to get our address in ethereum all we have to do is is take this public key that we've created with our private key hash it using that same ethereum hashing algorithm and then take the last 20 bytes and that's how we'll actually derive to our um to our address here now knowing the exact methodology of how to get the address doesn't really matter because it could change blockchain to blockchain and could even change NE two um but just know that that is essentially how kind of these addresses are derived right there's some derivative of the public key right because the public key is public and you know uh using the public key in kind of any public way is is totally fine um but not the private key so that is how we sign our transactions note though this isn't how we send the transactions so so this is just going to sign it create a transaction for us to send uh we'll learn later on how to send these transactions so that was a lot of information there too let's do a quick recap your public key is derived by using a digital signature algorithm on your private key right and you want to keep your private key private at all times because you're going to use your private key to sign transactions signing transactions with your private key you are the only one who can actually do this because you can't get the private key from a message signature however using your public key you can anybody can very easily verify that a signature that's signed by you is in fact signed by you in our metamask our private keys are located in this account detail section you just hit uh show Private keys and type in your password and it'll get your your private key here and the address of your account is derived from this private key uh it's derived from this public key so if you think about it your private key creates your public key which then can create your address and there's a little barrier here or a big barrier here because your private key you want to keep private and your public key and your address can all be public information now remember how in our metamask we were able to actually create new accounts mine says account six cuz I've created a few but how is it actually creating those accounts well now that we know all this if we go back to our blockchain demo here what our metamask is doing is essentially taking our pneumonic or or that multi-word secret phrase and then just hashing it with some number so secret phrase plus 0 gets this and it'll set this as your private key and for our account one that'll be the private key or maybe it's plus one the exact algorithm that it's using doesn't matter but if you want to create a new private key where you just hit this create account button the way it actually picks this account is by taking this secret phrase and then just changing this number so if I go if I'm in my metamask I do create account this right now I'm on account six because like I said I made a whole bunch if I make account six right as if we just did the secret phrase plus 6 and created this new hash or this new private key and created this new hash and it uses this to make a private key this is why in your metamask if you share that secret phrase if if you share that pneumonic device they will have access to all the accounts that you ever created however if you share your private key it will just give them access to that single account secret phrase has access to all the accounts created in your metamask or your wallet your private key is access to that single account and then the public key or address anybody can have access to and it's cool for anybody to have access to so when I'm thinking about the security of my metamask or my wallet this is kind of the order that I think of it in the seed phrase or n or secret phrase is incredibly important protect this at all costs because if somebody else gets access to this they will have access to all of your accounts the second most important is the private key because if somebody gets access to that they will get access to a single account and then your public key or address which whatever it's public now that we know a little bit more about what's going on underneath the hood of these blockchains let's go back in our transactions and look at this gas thing again and we'll look to see what's actually happening here gas in particular can be a little bit tricky to wrap your head around so if you don't get it right away don't worry as we go through examples it'll start to make more sense so before I was saying let's just look at this transaction fee bit which is the cost associated with running this transaction if I scroll over this on ether scan I can see this thing that says Block Base fee per gas plus Max party fee per gas times the gas Ed which might be a little bit confusing here let's actually break down what's going on on ethereum with EIP 1559 in place and again this is going to be specific to ethereum as every blockchain might do it a little bit differently but if we click to see more we can see a number of useful values here we can see gas limit is 21,000 and usage is 21,000 so this transaction used 21,000 gas and we sent 21,000 gas along with it sometimes when sending a transaction depending on when it's sent and depending on what these Specific Instructions are it might actually use way more gas than what you want it to use so with your transactions you can actually set a limit hey I don't want to use more than x amount of gas I don't want to do more than x computational units and in fact if we go to our metamask and we click Send to transfer between accounts again and we pick you know 0.01 e or something next can actually hit this little button here here go to Advanced and we can actually edit some specifics of this transaction one of them is going to be the gas limit we can change this gas limit to maybe 2200 2300 or more or even less since sending ethereum takes exactly 21,000 gas metam Mass just defaults to setting into that but we also see these other interesting things we see a priority fee and a Max Base fee let's reject this transaction and let's look back at ether scan to talk about these So currently in ethereum according to e EIP 1559 every transaction on ethereum comes with something called the base fee this is the minimum gas price you need to set to include your transaction and you'll notice that these are priced in something called guay so what is a guay if we come to the site ethon converter.com and again there's a link to this in the GitHub repository we scroll down we can see wey guay and ether 5 put one ether in here I can see how much one ether is in terms of guay and in terms of wayy one ether is equal to 1 2 3 4 5 6 7 8 n nine zeros so that's it's 1 billion guay is going to be one ether and then 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 and then 18 zos is away these are just easier ways of referring to really really small amounts of ethereum so if we look at our gas fees we see that the base fee is 0.00004 gay and this obviously would be an even smaller number if this was in units of whey so if we take this number and we put it into our calculator we can see that this is equal to 40 way or 0.0 a whole bunch of zeros for ether the max fee here refers to the maximum gas fee that we're willing to pay for this transaction and you can actually see that our Max fee is a little bit higher than what we actually ended up paying our Max fee was 2.21 32 something something and the gas price we actually paid was up here now your transaction might of course be a little bit different then additionally we have a Max priority fee this is going to be the max gas fee that we're willing to pay plus the max tip that we're willing to give to miners now currently in ethereum this base fee ends up getting burnt and we can see on ether scan exactly how much is getting burnt here and if we pull up our calculator again we can grab this gas fee multiply it by the amount of gas we used and we can see that this is indeed how much ethereum we actually ended up burning we go back to ethereum converter paste it in we can see that these two numbers are indeed equal this means whenever you send a transaction a little bit of ethereum is removed from circulation forever or it's considered burnt So currently in ethereum part of your ethereum part of your transaction fee actually gets burnt and then the other part goes directly to miners so to figure out exactly how much went to miners we could do this number minus the burn amount and this is how much ethereum was paid to an ethereum minor for this transaction you'll see down here transaction type 2 EIP 1559 this is the EIP 1559 version version of these transactions like I said every blockchain is going to have a different fee burning and and fee and gas process and they're all going to be a little bit different but the sum of it is blockchains have limited block space for transactions the gas price that costs for your transaction to be included in one of these blocks changes based off how much demand there is the base gas fee for ethereum will go up and down depending on how many people are sending transactions and how many people want to be included in a block if a ton of people want to be included in a block that means a ton of gas is obviously going to get burnt we've left a link to a video in the GitHub repository with this section from this YouTuber who does an amazing job breaking down this EIP 1559 and more about how this gas model actually works I highly recommend you pause this video and watch that video to understand more the base fee gets programmatically algorithmically adjusted to try to Target for all the blocks to be 50% full if they're more than 50% full this base fee automatically goes up if they're less than 50% full this base fee goes down now this is a lot of the basics of how this transaction works and it can be a little confusing so let's do a quick refresher of everything in here there's a unique transaction hash that uniquely identifies this transaction on this blockchain we can see the status we can see the block number that it's confirmed on one other thing we want to look at if we scroll up we see block number and block confirmations this is how many blocks have been mined since this block was included like we saw with our blockchain demo the longer the blockchain gets the harder it is to tamper with and the more secure it is typically you'll see some processes say they'll only do something after 20 block confirmations 30 Block confirmations or or Etc the reason that they wait for these block confirmations is because they want to make sure that that transaction is actually included and we can actually see the block that our transaction was included in and all the other transactions with it different details about how much gas was used the gas limit Etc time stamp is when the transaction happened we can see from and to we can see the value and then we can see the transaction fee which we see right here is Block Base fee per gas plus the max priority fee per gas times the gas used and we see all the details of the gas down here gas price is the cost of one unit of gas gas limit is the max amount of units of gas that we're willing to pay in this transaction the usage is how many actually got used the base fee is going to be the base Network fee per gas so 40 way per one gas used the max gas is the max gas price we're willing to pay and Max priority is going to be the max gas price plus the tip that we give to Miners and then we can see how much is burnt and then we see transaction savings which which is the difference between how much was actually used or paid for and then returned so for example in this transaction the gas price we ended up picking was a little less than our Max gas price here so the gas price we ended up using was a little less than our Max priority fee here so we had some savings compared to that we can also see that this was an EIP 1559 transaction we can see our nuns here which was NS zero because the transaction that I'm showing is our first NS and then of course we can see the input data for transactions that are just sending ethereum the input data is going to be blank but you'll see that when we get to Smart contracts the input data is not going to be blank and it's going to be one of the most important features of these transactions you'll also notice that there's a state tab this is an advanced Tab and it shows the different states that are changed based off of this transaction we're going to ignore this one for now now that we know how the blockchain itself Works under the hood let's talk about some blockchain fundamentals and we actually covered all these topics in a previous free code Camp video so let's go to that if the first time you listen to this some of these Concepts seem a little bit hard to grasp don't worry about it as we continue and as we move on with this course they'll start to make more sense when you see them used in real examples I definitely would recommend going back and re-watching and Rel listening to the parts that you don't quite get and asking questions in the discussions tab of the GitHub repository awesome so now that we know all the cryptography pieces and all the little nitty-gritties of how the blockchain actually works and how our signatures work and how everything sticks together let's talk a little bit about how this works in actuality and what's really going on now for a lot of this each different blockchain has slightly different algorithms and slightly different metrics and criteria for doing a lot of this stuff so when we're talking about these specific implementations keep in mind the exact algorithm might be a little bit different but the concepts are all still going to be exactly the same hashing and hash function is going to be the same no matter where you look a decentralized blockchain is going to be the same no matter where you look how it's actually implemented is going to be a little bit different now traditionally when you run an application you know be it a website or something that connects to some server you are interacting with a centralized entity and unlike how we saw with the blockchain with multiple different peers it's going to be run by a single centralized group now it still could be run on many different servers but all those servers are still going to be controlled by the same centralized group blockchains as we saw run on a network of different independent nodes when we saw Pier a pier B Pier C those were different examples of different independent users running the blockchain technology on their own node now when I use the term node I'm usually referring to a single instance of a decentralized system so when I say a single node when I'm talking about a blockchain I'm talking about one of those perer A's Pier B's perer C's running that blockchain software I'm talking about one server running this technology and again it's this network it's this combination of these nodes interacting with each other that creates this entire blockchain what makes these so potent too is that anybody can join the network and that's why there's decentralized the barrier to entry is a little bit of Hardware requirements you're getting the correct materials to run the software and then you running the software anybody can join these networks and participate and that's what makes it truly decentral in fact you can go to GitHub right now and run your own ethereum node in a few seconds now in the traditional World applications are run by centralized entities and if that entity goes down or is maliciously bribed or decides that they want to shut off they just can because they're the ones that control everything blockchains by contrast don't have this problem if one node or one entity that runs several nodes goes down since there are so many other independent nodes running that it it doesn't matter the blockchain and the system will persist so long as there is at least one node always running and luckily for us most of the most popular chains like Bitcoin and ethereum have thousands and thousands of nodes and as we showed in our demo if one node acts maliciously all the other nodes will ignore that node and kick that out or or even punish it in some systems because they can easily check everybody else's note and see okay this one is out of sync with the majority and yes majority rules when it comes the blockchain each blockchain keeps a full list of every transaction and interaction that's happened on that blockchain and we saw if a node tries to act maliciously then all their hashers are going to be way out of whack and they're not going to match everybody else this gives blockchains this incredibly potent IM mutability trait where nothing can be changed or corrupted so in essence we can think of a blockchain as a decentralized database and with e theum it has an extra additional feature where it also can do computation in a decentralized manner now let's talk consensus proof of work and proof of stake because you've probably heard these before and they're really important to how these blockchains actually work when we went through that blockchain example and we did that mining feature this is what's known as proof of work proof of work and proof of stake fall under this umbrella of consensus and consensus is a really important topic when it comes to blockchains consensus is defined as the mechanism used to reach an agreement on the state or a single value on the blockchain especially in a decentralized system I briefly alluded to this consensus mechanism in our blockchain example when I said if one changes something and the other two don't then majority Will Rule and kick that one out this is part of that consensus mechanism now very roughly a consensus protocol in a blockchain or decentralized system can be broken down into two pieces a chain selection algorithm and a civil resistance mechanism that mining piece that we were doing or or the proof of work algorithm is what's known as a civil resistance mechanism and this is what ethereum and Bitcoin currently use please note that depending on when you're watching this if eth2 is out then it's no longer proof of work now one of the other reasons that I absolutely love working in this industry is that we are changing things and we are building things and we are growing this network all the time and as of September of 2022 ethereum chain actually migrated from proof of work to proof of stake in an event called the merge and I actually stayed up till 3:00 a.m. to watch this event it was a ton of fun watching watching all the little nodes work together and do this change and actually go live but in any case ethereum actually moved from proof of work to a proof of State Network now proof of work is known as a civil resistance mechanism because it defines a way to figure out who is the block author which node is going to be the node who did the work to find that mine and be the author of that block so all the other nodes can verify that it's accurate civil resistance is a blockchain's ability to defend against users creating a large number of pseudo Anonymous identities to gain a disproportionately advantageous influence over said system and in layman's terms it's basically a way for a blockchain to defend against somebody making a bunch of fake blockchains so that they can get more and more rewards now there are two types of civil resistance mechanisms that we're going to talk about here namely proof of work and proof of stake let's talk about proof of work a a little bit more in-depth first in proof of work this is silver resistant because a single node has to go through a very computationally expensive uh process called mining which we demonstrated earlier to figure out the answer to the blockchain's riddle of finding that correct nuns or or whatever the blockchain system has in place in proof of work this works because no matter how many pseudo Anonymous accounts you make each one still has to undergo this very computationally expensive activity of finding the answer to the proof of work problem or the proof of work riddle which again in our demonstration it was finding a Nuns with that first four zeros but again each blockchain might change the riddle or or change the problem to be a little bit different in fact some of these blockchains make this riddle intentionally hard or intentionally easy to change What's called the block time the block time is how long it takes between blocks being published and it's proportional to how hard these algorithms are so these problems actually can change depending on how long they want the block time to be if a system wants the block time to be very very long they just just make the problem very very hard if they want it to be very short they make the problem a lot easier we'll talk about Cil attacks in a little bit and how they can affect the system but with proof of work it's a verifiable way to figure out who the block author is and be civil resistant now you need to combine this with a chain selection rule create this consensus now there's some consensus protocols that have more features but very very roughly these are the two pieces that we're going to look at the second piece is going to be a chain selection rule how do we know which blockchain is is actually the real blockchain and the true blockchain now Bitcoin uses a consensus algorithm called Nakamoto consensus which uses a combination of proof of work Cil resistance and the longest chain rule which is their chain selection Rule now I do want to point out that when you go out and you leave this course and you leave the curriculum a lot of people will just say bitcoin's consensus algorithm is proof of work and this is technically a little bit inaccurate proof of work is just a piece of bitcoin's consensus algorithm where the actual consensus algorithm is called Nakamoto consensus which includes that combination of the longest chain Rule and the proof of work Cil resistance I just want to give you the heads up that in the real world a lot of people will use them interchangeably it's not exactly correct but we'll give them a pass the decentralized network decides that whichever blockchain has the longest chain or the most number of blocks on it is going to be the chain that they use this makes a lot of sense because every additional block that a chain is behind it's going to take more more and more computation for it to come up that's why when we saw in our transaction we actually saw confirmations the number of confirmations is the number of additional blocks added on after our transaction went through in a block so if we see confirmations as two it means that the block that our transaction was in has two blocks ahead of it in the longest chain now I do want to point out that a lot of people use proof of work as a consensus protocol and I do want to say that this is a little bit inaccurate but sometimes people use it interchangeably proof of work is a piece of the overall consensus protocol which in Bitcoin and ethereum 1's current case is Nakamoto consensus Nakamoto consensus is a combination of proof of work and this longest chain rule both equally and very very important now proof of work also tells us where these transaction fees and these block rewards go to remember how when we made this transaction we had to talk about gas and a transaction fee so who's getting paid who is getting this transaction and this transaction fee is going to the miners or the validators in a proof of work Network they're called Miners And in the proof of stake Network they're called validators they are a little bit different and we'll get into that when we talk about proof of stake in this proof of Works system all these nodes are competing against each other to find the answer to the blockchain riddle remember in our example it was to find a hash that has four zeros at the start and again depending on the blockchain implementation that riddle is going to be a little bit different but all the nodes are trying as many as possible to try to get this answer first why because the first node to figure out the answer to the blockchain re is going to get that transaction fee they're going to get paid from that now when a node gets paid they actually get paid in two different ways one is going to be with a transaction fee and another piece is going to be the block reward remember how we talked about alternating the gas price or the gay on our transaction well that's the transaction fee that we're going to pay to these blockchain nodes for including our transaction the block reward is given to these nodes from the protocol from the blockchain itself you've probably heard of the Bitcoin having before the having is referring to this block reward getting cut in half and it's supposed to be cut in half roughly every four years this block reward increases the circulating amount of whatever cryptocurrency that is being rewarded for example on ethereum the Block reward is giving out ethereum and on bitcoin the block reward is giving out Bitcoin so these nodes are competing against each other to be the first one to find this transaction to be the first one to find the answer to this problem so that they can be the ones to win both this block reward and your transaction fee some blockchains like Bitcoin for example have a set time when they're no longer going to give out block rewards and the miners or the nodes are only going to get paid from transaction fees now this gas fee again is paid by whoever initialized the transaction when we got our funds from the faucet there was some server and somebody else was paying the transaction fee for us however when we sent ether from one account to another our first account actually paid some transaction fee to send that ether in proof of stake there's also a gas fee but it's paid out to validators instead of Miners and we'll talk about that in a little bit now let's talk about two types of attacks that can happen in these blockchain worlds let's talk about the first one being the cibil attack the cibil attack is when a user creates a whole bunch of pseudo Anonymous accounts to try to influence a network now obviously on bitcoin and ethereum this is really really difficult because the user needs to do all this work in proof of work or have a ton of collateral in proof of stake which again we'll talk about in a bit the other more prevalent attack is what's known as a 51% attack now as we saw as part of our consensus protocol these blockchains are going to agree that the longest chain is the one that they're going to go with so long as it matches up with 51% of the rest of the network this means that if you have the longest chain and you have more than 51% of the rest of the network you you can do what's called a fork in the network and bring the network onto your now longest chain now Cil attacks obviously are when a single node or a single entity tries to affect the decentral of the network by pretending to be multiple different people although they're just the same person or entity and like I said it's really difficult to do in proof of work and proof of stake so you can see now that blockchains are very Democratic whichever blockchain has the most Buy in and is the longest is the blockchain that the whole system is going to corroborate when nodes produce a new block block and add it to the longest chain the other nodes will follow this longest chain that the rest of the network is agreeing with ADD those blocks to their chain and follow up so very small reorganizations are actually pretty common when a blockchain picks a block from a different longest chain puts it on and then has to swap it out for another block and and continue with a different blockchain however if a group of nodes had enough nodes or enough power they could essentially be 51% of the network and influence the network in whatever direction that they wanted this is what's known as 51% attack and it's happened on blockchains like ethereum classic which is not ethereum this is why the bigger a blockchain is the more dentalized and the more secure it becomes so after you watch this video and you become a blockchain engineering expert I definitely recommend you run a note as well because you are going to increase the security of the network as a whole by running a node so proof of work is fantastic because it allows us to very easily protect against these civil attacks and keep our blockchains decentralized and secure however it has some drawbacks as as well proof of work costs a lot of electricity because every single node is running as fast as they can to win this race to get the rewards this leads to obviously an environmental impact now since proof of work in Nakamoto consensus a lot of other protocols have taken this idea and gone in a different direction with a different civil resistance protocol a lot of them with the intention to be a lot more environmentally friendly and the most popular one right now is proof of stake there are some chains that are already using this proof of stake protocol and that are live and thriv driving some of them are like Avalanche salana polygon polka dot so let's talk about proof of stake now again this is a different civil resistance mechanism instead of solving this difficult problem proof of stake nodes put up some collateral that they're going to behave honestly AKA they stake in the example of ethereum 2 nodes put up some ethereum as a stake that they're going to behave honestly in the network if they misbehave in the network they are going to be slashed or removed some of their stake obviously this is a very good civil resistance mechanism because if you try to create a whole bunch of anonymous accounts then each one of those accounts you have to put up some stake and if you misbehave you're going to run the risk of losing all the money that you put up as collateral in this system miners are actually called validators because they're no longer binding anything they're actually just validating other nodes now unlike proof of work which every node is racing to be the first one to find the Block in proof of stake nodes are actually randomly chosen to propose the new block and then the rest of the validators will validate if that node has proposed the block honestly as we saw with our cryptography lesson it's usually very easy for other notes to verify if a proposal or a transaction is honest now proof of stake obviously has some pros and cons as well Pros are that again it is a great civil resistance mechanism and a great way to figure out who the author of a block should be the other Pros are that it's way less computationally expensive to figure out the new block because instead of every every single node on the network trying to do this only one node needs to do this and then the rest of the nodes just need to validate it the cons are that it's usually considered a slightly less decentralized Network due to The Upfront staking costs it costs to participate now this gets into a little bit of a philosophical battle on how decentralized is decentralized enough and I think that's up to the community to decide and as we progress I think we'll learn more and more about how decentralized is decentralized enough the general consensus amongst blockchain Engineers though is that proof of stake is is very very decentralized and very secure now there's another term that might be the first time you heard it a layer one we're going to talk about layer ones and layer twos in terms of scalability really quickly as well a layer one refers to any Bas layer blockchain implementation bitcoin's a layer one ethereum's a layer one Avalanche is a layer one these are the base layer blockchain Solutions a layer two is any application that is added on top of a layer one added on top of a blockchain some examples of layer twos are going to be chain link arbitrum or optimism arbitrum and optimism are very interesting because they are layer twos that also look to solve this scalability issue arbitrum and optimism are what's known as rollups and they roll up their transactions into a layer one like ethereum we're not going to go too deep into rollups and how they actually work but all you really need to know is that they solve some of the scalability issues by being another blockchain that people can make transactions on still on kind of this base ethereum layer now they're different from side chains because side chains derive their security from their own protocols rollups derive their security from the Bas layers so arbitrum and optimism for example is going to be just about as secure as ethereum we're going to let Kira go deeper into these layer ones and these layer twos and these rollups and all the differences between these in a later lesson all right so we just talked about a lot of stuff so let's do a quick recap before moving on cibil attacks are prevented due to protocols like proof of work and proof of stake 51% attacks grow increasingly harder with the size of blockchain so you should run a node consensus is the mechanism that allows a blockchain to agree upon what the state of the blockchain is sharding and rollups are solutions to scalability issues on layer ones a layer one is any base blockchain implementation like Bitcoin or ethereum a blockchain scalability problem is that there's not always enough block space for the amount of transactions that want to get in them this leads to very high gas prices and again gas prices are how much it costs to interact with a blockchain so that's it for the blockchain basics and the blockchain explainers with just this information you now can go off into the world and start working with blockchains and interacting with blockchains with at least some level of knowledge as to what's going on you should be incredibly proud of yourself for just making it this far definitely be sure to give yourself a pat on the back and a round of applause now that we've got gotten a lot of the basics and the fundamentals out of the way let's start jumping into the coding aspect this is where you're going to learn how to actually build these smart contracts how to build these trust minimized agreements in these blockchains and in these smart contract platforms this next section this solidity Basics the solidity fundamentals section will give you all the skills to start actually coding solidity and understanding how these smart contracts work underneath the hood so at this point absolutely give yourself a high five maybe say hi in the GitHub discussions maybe say hi in the community on Twitter on Reddit Etc and be proud of just making it this far the journey has really only just begun but you've already learned so much let's begin the next section and let's jump into the code throughout this course so far we've briefly mentioned a couple of terms layer 1 or L1 layer 2 or L2 and rollup so Patrick mentioned earlier that we'll be working on sepolia to deploy our smart contracts and interact with them throughout this course but we will also be deploying to and interacting with our contracts on ZK sync sepolia sepolia is a layer one or L1 testnet and ZK sync sepolia is a layer 2 or L2 roller but what do these terms actually mean so a layer one or L1 is a blockchain in its purest form where there are nodes that contribute to Cil resistance and help the chain reach consensus as Patrick was describing earlier the L1 is the base layer of the blockchain ecosystem that works without any additional plugins it's often referred to as the settlement layer because it's the layer of a blockchain ecosystem that all plugins layers or additional components eventually write back to examples of L1 chains include Bitcoin BNB chain salana Avalanche ethereum is the chain that we be most commonly working with throughout this course and when we talk about layer 1es or l1's we're most often referring to ethereum you can think of this L1 as like the Hub of the ecosystem for example in the evm OR ethereum ecosystem the ethereum Mana is that Hub of the ecosystem and anything that hooks back into ethereum is known as a layer 2 or L2 so a layer two is anything that is built on top of the L1 makes sense right the first layer of the ecosystem is the layer one the second layer of the ecosystem is the layer two it's important to note here that apps deployed to the L1 are not considered l2s for example the popular decentralized exchange Unis swap is not considered to be an L2 but an app deployed on ethereum this means that its smart contracts are directly deployed on ethereum a layer 2 or L2 is any application that is built outside of the L1 and then hooks back into it there are different types of L l2s such as L2 applications for example chain link like Patrick was describing earlier chain link is a decentralized Oracle Network that brings offchain data onchain in a decentralized way another type of L2 is event indexing networks like the graph which enables applications to access onchain data but the most popular type of L2 is an L2 chain or rollup and when people mention l2s or layer tws they are most often referring to rollups but what actually is a rollup aart from the fruit snack for you Americans out there blockchain rollups are an L2 scaling solution that increase the number of transactions on ethereum without increasing the gas costs this is achieved by rolling up multiple transactions into one hence the name roll up we'll explain a bit more about how this actually works in a second but first it's important to understand why we need L2 chains or rollups so in an Ideal World we need blockchain systems to have three properties we need them to decentralized I.E not controlled by a single centralized entity we need them to be secure so the system is protected against security vulnerabilities like 51% attacks where a malicious actor has control over a majority of the network over 51% Cil attacks where a malicious actor creates multiple nodes to gain control again by having a majority both of these attacks mean that the malicious actor can control the network to pass through any transactions they like or reorder transactions and also so replay attacks where the same transactions are sent more than once if you don't understand how these vulnerabilities work do not worry but we will leave some resources in the GitHub associated with this course if you would like to know more and finally scalable meaning that the system can grow without sacrificing speed or running costs this is known as the blockchain tralama the blockchain trama states that A blockchain system can only ever have two out of three of these properties for example if the system is secure and decentralized then scalability will be sacrificed as is the case with ethereum ethereum inherently has a scalability problem it can only process approximately 15 transactions per second and as ethereum is gaining in popularity the number of transaction requests is increasing the gas cost to pay for these transactions is increasing to jump the queue and avoid long wait times if blockchain systems are to reach mainstream adoption gas prices need to be reduced even in the face of high transaction volumes enter rollups rollups aim to solve the trilemma problem by increasing the throughput of ethereum without sacrificing either the decentralization or the security of the system this is achieved by processing the transactions off of the L1 blockchain and how does this work when a user submits a transaction to a rollup such as ZK sync an operator picks up this transaction an operator is a general term and it can refer to a node a set of components or entity responsible for processing the transactions this operators job is to pick up the transactions order them with other people's transactions and then bundle them together compress them and then submit them back to the L1 such as ethereum and so if ethereum rolls back so does the rollup therefore they have the security of etherium by bundling the transactions together this enables rollups to handle transactions efficiently because the gas cost associated with the transaction is split among all of the users all of the transactions in the transaction batch the validity of this transaction is then checked on the L1 and this can work a little differently depending on the type of rollup there are two main types of rollup and the difference between these two lies in how the rollup checks the validity of the transaction how they check it is legitimate rather than fraudulent the two main types of rollup are optimistic Roll-Ups and zero knowledge or ZK Roll-Ups let's start with optimistic Roll-Ups optimistic Roll-Ups assume that the offchain transactions are valid by default they're pretty optimistic operators can propose what they believe to be the valid state of the rollup chain after this there is a time period known as The Challenge period during which operators can you guessed it challenge the rollup transaction operators can send a challenge by Computing a fraud proof if they notice a potentially fraudulent transaction this fraud proof involves the operator playing a call and response game with another operator until they narrow down the dispute to a single computational step this computational step is then executed on the L1 and if executing this Step results in a different outcome the state of the blockchain is different the challenging or disputing operator wins The Challenge and the fraud proof succeeds if the proof succeeds the rollup will re-execute the batch of transactions and their operator responsible for the incorrect transaction inclusion will be penalized this is usually done using some kind of staking mechanism where operators send tokens to a Smart contract that are held to say yep I'm going to act honestly and then if they don't their tokens are taken away from them this is known as slashing which Patrick has mentioned previously and this works the same on optimistic rollups if the transaction proposals are not invalidated during that challenge period Then the proposals are assumed to be correct so now let's move on to zero knowledge or ZK rollups zero knowledge or ZK rollup Solutions prove each transaction batch to be correct using validity proofs or ZK proofs ZK proofs in this context are a complex mathematical cryptographic problem and at this stage we do not need to understand how they work we can just think of them purely as some math magic that just works ZK proofs involve two participants the prover which is the entity that is trying to prove that they know something and the verifier which is the entity that is verifying that the prover does in fact know the answer to the problem the answer to the problem is often referred to in ZK proof world as the witness in the context of ZK rollups the prover is an operator and the verifier is just an L1 contract so for each transaction batch that is submitted to the L1 a validity or ZK proof is computed by approver and verified by the verifier or the L1 contract this ZK proof then confirms the transaction validity as we said this is just some maths magic but if you like to understand a little bit more about how that works we will leave some references in the GitHub repo but essentially what happens the problem is boiled down to a single mathematical equation meaning that the prover can then prove that their input satisfy this problem and then the verifier can say yes the output is as expected and the proof succeeds but again you don't need to understand how that works at this time you can literally just think of it as some math magic and so to summarize Roll-Ups help scale ethereum by processing transactions off chain bundling them together and then submitting them back to ethereum with some kind of proof which is different depending on whether it is an optimistic rollup or a ZK rollup one of the types of operators associated with Roll-Ups is a sequencer the sequencer usually refers to the operator which is ordering transactions and sometimes bundling them together now in some rollups this sequencer is in fact centralized so it's controlled by a centralized entity this can be problematic because it can lead to things like censorship where the centralized entity is stopping some users transactions from being passed or it can manipulate the order of transactions for their own gain so something like you being unable to withdraw because they're blocking your withdrawal transaction could occur the other issue is that if the sequencer is centralized then if the sequencer goes down then no one will be able to pass through any transactions at all withdrawals can't happen and this can be extremely problematic because what if withdrawals are halted for a day a week a year forever are the funds then worth anything if you can't withdraw them and these are just a few problems with sequences being centralized and this is why projects like ZK sync are working right now to decentralize their sequen L2 chains or rollups are graded based on certain properties and given a stage now for this section we are going to be going through the L2 beat website which you can see at L2 beat.com scalings summary and here you can see all of the different chains their stages and lots of different information that we will be going through in a second so the stage of a rollup is a categorization framework based on vitalic proposed Milestones it is an opinionated assessment on the maturity of the rollup by the l2b team and its purpose to create an incentive for projects to work towards decentralization and they have proposed three stages stage zero full training wheels in stage Zero The Operators and a security Council predominantly manage the rollup this is like a committee of members who can make decisions in the case of bugs or problems or upgrades and so in stage zero the management of the rollup is pretty centralized what about data availability dat data availability refers to the confidence a user can have that the data required to verify a block really is available to all Network participants so in terms of rollups this transaction data needs to be available in order to be able to verify the transactions so for stage zero rollups there needs to be open-source software to enable State reconstruction of the L1 data to ensure both transparency and also the verification and finally in stage zero in the case of an unwanted upgrade users have less than 7 days to exit the system exiting in this context refers to the users withdrawing their funds from the system and in stage zero this usually requires some kind of operator coordination so some entity is going to have to help them exit the second stage is stage one bit confusing with the two but it's called stage one enhanced rollup governance so in stage one the rollup is starting to be governed by smart contracts the Security Council is probably still in place for things like bug resolution but it is starting to become more decentralized in stage one the rollup has a fully functional proof system with a decentralized fraud or validity proof submission system now in stage one a user can exit without coordination from an operator in the case of these unwanted upgrades now the final stage stage two is no training wheels smart contracts now fully manage the rollup it's pretty decentralized at this point and so the fraud or validity proof system is completely permissionless and users are now given ample time to exit in case of unwanted upgrades there usually is some kind of Security Council where its role is strictly confined to addressing errors that can be adjudicated on chain meaning that users are now protected against governance attacks and so if we look through this l2b nice little table here then we can see what stage all of the different rollups are at so for instance ZK sync eror is a stage zero rollup so if we click into this then we can see a summary of this roll up and you'll notice here this pretty little pie chart let's go through what this means this pie chart is a nice little visualization of the risk analysis for this rollup so let's go through all of these little pizza slices so First Data availability so can the L2 State be reconstructed from the data that ZK sync submits to L1 and because it's green yes it can so the difference in state before and after the bundle of transactions is submitted is published on chain so the proof can be constructed State validation so have we checked that these bundle of transactions is legitimate rather than fraudulent has the state or the state differences been validated to be correct and in the case of ZK sync yes because they use ZK proofs they use a plon zero knowledge system which is just the fancy algorithm with kzg commitments this is all just like the mathematical magic that happens but yes it's proved to be correct so it's green zoom out of touch so that we can see the text box but sequencer failure so first of all what's a sequencer a sequencer is a type of these operators that we we were talking about earlier and it usually refers to the operator that is ordering the transactions and sometimes a sequencer can bundle the transactions together as well but in general it's talking about the ordering of the transactions so what happens if this sequencer goes down can I a user get my money out so users can submit transactions to the queue but you can't force them through they still need the sequence of there to get their transactions through the sequencer can't pick and choose transactions and select actively skip them but it could stop processing any transactions at all so if it's down then no one can get any transactions through and no one can withdraw their funds move their funds or do anything no transactions can go through so it's yellow because they can submit them to the l1q but they can't force them through essentially so that's why it's yellow proposer failure so the proposer is another type of operator and it's operator responsible for proposing the new state of the rollup so what happens if this goes to what if we can't propose new state so because they have a whitelisting system on ZK sync only whitelisted proposers can publish state routs so new state of the blockchain on the L1 so in the event of a failure then no one can get their money out withdrawals can't happen no transactions can happen so this is obviously a big problem so it's spread and finally exit window so like we were saying earlier the exit window is how long does a user have to withdraw their funds to exit from the system to not be using the chain anymore and so for ZK sync in the case of unwanted upgrades the contracts are instantly upgraded and so there's no window for users to exit so it's red so if we zoom out again and we look at this page then we can see a nice summary of the rollup so we can see the total value locked the activity on the Chain onchain costs so like the gas costs the Milestones so for instance on the 13th of March ZK sync era started using blobs you don't need to know what blobs are at this point but they're super cool so I'm going to give you a quick teaser we will be covering blobs in a later part of this course so stay tuned for that but essentially blobs are like massive massive chunks of data which aren't submitted to ethereum they're like a side card to the transaction they tag along but they're not stored on chain forever because they're massive instead a hash of all of the data is submitted to ethereum to compute the proofs so you can see for Roll-Ups how useful this is because if you've got a massive bundle of transactions then you can have all of that information without having to store it all on chain introdu of the bjam Prov this is just their prover the code and they had their Alpha launch of the chain which is cool and then you can see the risk summary and the risk analysis that we were going through earlier now if we scroll down to rollup stage we can see that it's a stage zero rollup and so you can click in and see what requirements they have met and what they need to do to move to a stage one so we were staying with those permissioned operators earlier so they can censor withdrawals so that needs to be fixed and then also in the case of upgrades they're not given any time to exit the system like we were talking about earlier now the final thing to say about rollup stages and l2b is that these stages do not reflect the security of the rollup it is purely an opinionated assessment of the maturity in order to push these protocols towards decentralization now because the batches of transactions are submitted and proven on ethereum and so that is everything you need to know about l1s l2s and rollups that was a lot of information for you all so now is probably time for you guys to take a break and try and digest something with that information because I know there are a lot of new terms here if you need to watch again go ahead because there is a lot of information here that is pretty complex and so as Patrick says and will say a lot of times throughout this course go get yourself a snack go get yourself a drink a coffee some ice cream take yourself on a little walk and have a break and then come back when you're all refreshed and we can continue because it is time for us to make our very first transaction on ZK sync testet and I'm super excited about it so I will see you in a second for that the final section oh no second to last and now it's time to make our very first transaction on ZK sync testnet the ZK sync testnet is sometimes called ZK sync sepolia ZK sync era testnet I'll probably use the terms interchangeably but ZK sync seoa ZK sync testnet they're all the same thing some of the things that we're doing here are going to be repeated from earlier in the course but repetition is key in order to get this information drilled into your brain so first let's go ahead and add ZK sync ofoia to our metamask so that we can see the transaction summaries see our balance and things like that from inside metamask okie dokie the very first thing that we need to do is we need to add ZK sync superia to our metamask so that we can see all of our transactions and everything that's going on inside our wallet including our balance so what we're going to do is we're going to head to chain list.org and make sure that we have got this include test Nets box checked and then we need to search for ZK ZK sync and here we can see ZK sync sepolia testnet which has got the chain ID of 300 so if you click in here and then we're going to connect our wallet and we're going to confirm that the site can have permissions to our wallet and then we can click approve to allow this site to add a network so this is going to add the network to our metamask and then we are going to switch over to ZK sync sepolia when we click inside our wallet you'll be able to see a summary of the balance and all of the tokens nfts and activity going on inside our wallet and it's that easy that simple now the second thing we want to do is we want to be able to see transactions and contracts in more detail like we did on seoa with ether scan so the block Explorer equivalent to Ether scan on ZK sync and ZK sync aoia can be found at explorer. ZK sync. for main net and then if we switch over in this little drop down to ZK sync era AIA then it's seo. explorer. ZK sync. for zync sepolia and if we grab our wallet address then we can paste that in the search here and we'll be able to see a summary of our account so when we send our first transaction it will come up here so now what we need to do to send our first transaction is get some funds and this is going to be our first transaction is getting funds so there are actually two ways that we can get test net funds on ZK sync sepolia the first is a bit like sapoia and we can use a faucet directly faucet foret I never know how to pronounce it but these can be a little bit temperamental the one that's recommended on the ZK sync documentation here requires an API key and there's another one that requires us to sign in with GitHub both things that we don't really want to do so we're actually going to use a different method which is bridging but Kira what is bridging let me tell you right now so what we're going to do is we're going to get some funds from sepolia we're going to get some sepolia eth in the same method that we did so before and don't worry I'm going to take you through step by step how to do it again and then what we're going to do is we're going to bridge those funds over to ZK syn ofoia but I still haven't explained to you what bridging is let me do that now bridging means taking the funds from one chain and then getting them on the other chain now we're not actually taking those funds and literally moving them we're using a mechanism now there's two main types of bridging mechanisms the first is a locking and unlocking method and what happens here is that the tokens are locked on the source chain so they're locked inside a smart contract and then they're unlocked on the destination chain they are released from a smart contract and sent to your wallet from the destination chain now you might imagine that this could be a bit of a security concern because what if the smart contract is hacked and my tokens that are locked on the source chain contract are taken now this can happen but you just have to make sure that the protocol you're using is heavily audited and tested now the second method is a minting and Burning Bridge and what happens here is on the source chain the tokens are burned so they sent to the zero address they're taken out of circulation they're destroyed they are no longer and then tokens are minted on the destination chain they're given to the user on the destination chain they're created they're brought into existence and if you don't understand what I mean by burning and minting don't worry this will be covered extensively in a future course we go through ERC 20s minting and burning and all of these different things and tokens later down the line so you don't need to know 100% how it works all you need to know is that the tokens are actually removed removed on the source chain and then created on the destination chain now here the bridge protocol needs to have control over the supply of the tokens in order to be able to burn them and mint them so for instance an example of this is cctp created by the circle team where usdc is burned and minted in order to create a bridge in which their Bridge implements a burn and mint Bridge mechanism and this can occur because the circle team have control of the usdc supply but enough about bridges for now and so let's continue and actually Bridge our funds from sepolia to ZK sync sepolia and what we're going to do is we're going to get some sapoia eth from a faucet and then we're going to bridge it to ZK syn seoa to get some ZK syn seoa eth that's a lot of words let's do that now so like I said the first thing we need to do is we need to use a faucet what we're going to do is we're going to use the Google Cloud sapoia faucet as of recording this this is the best faucet to use but if you check the GitHub repo associated with this course we will keep it updated with the best faucet on spia for you guys to use so head there if you want to check what the current best one is as I said this is the best one for right now so we're going to select the network as sepolia and then I'm going to go into my metamask and I'm going to click this little button to copy my address associated with my wallet and I'm going to paste it in here and then I'm going to click this button that says receive 0.05 seoa e so you may have had a little flag come up that says you need .1 e on Main net and what you need to do is just wait around 10 to 20 minutes and then come back and try again and this is to prevent some kind of like Cil attack where people creating multiple multiple accounts and then just draining the faucet by using newly created wallets instantly to try and get funds so now our test not tokens are on the way and we're actually doing a transaction on sepolia as before so these are the all the steps that we've already done and so now we've sent the tokens and we can check inside our wallet and what we'll have to do is switch over to sepolia testet and you can see amazing we now have 0.05 sepolia e and now we need to take those tokens and we need to transfer them to ZK sync seoa to get some ZK sync sepolia eth how do we do that we need to use a bridge so we're going to head to portal. ZK sync. ibridge to bridge our funds and this is going to be a lock and unlock method Bridge up in this right hand corner we're going to click this little down arrow and then switch it to ZK sync sepolia test snap Okie doie we are going from ethereum seoa test net to ZK sync sepolia testnet I'm going to transfer 0.025 sepolia eth to ZK sync ofoia first of all I need to connect my wallet so you can connect so click connect your wallet confirm that you'd like to connect okay so now that we've connected our wallet we can click continue and then we're going to click I understand proceed to bridge because we have made sure that our wallet does support ZK sync aoia testnet because it's metamask it does so I understand now we can just confirm the transactions it's good practice to read through so yes this is the amount I wanted to send from my sepolia testnet account to my ZK sync apoia testnet account by the way notice here the addresses are the same so we'll click bridge now then we can confirm this transaction in metam mask and now we can see a nice little visual of this transaction occurring okay so now that it says the transaction is complete I'm going to head back over to the zkn sepolia block Explorer and I'm going to paste our wallet address into the search bar and we can see that we have in fact done our very first transaction amazing so we can see here it's proess on ZK sync and we can see that we've gone from our L1 address on sepolia to our L2 address on ZK sync with a value of 0.025 eth with a fee a very very small fee and so we're going to click into the transaction hash and you can see here the information about the transaction including the hash the status which we're going to go through in a second the block number the batch so that's like the bundle of transactions from to our addresses on the different chains the tokens transferred the input data the value which was the amount that we sent the fees gas limits nons and when it happened so four minutes ago so what does this status mean it says on ZK sync era it's processed but then on ethereum it says this weird thing or it's like sending validating executing how come I have the funds in my metam mask and it's processed on ZN K but on ethereum like this doesn't make any sense K what is going on I'm confused us well let me explain to you so if we head back over to the ZK sync documentation and we head to ZK sync stack Concepts finality and that will explain to you what these two little sections mean so finality in a blockchain system as it says here refers to the time taken from sending the transaction to when the transaction is considered settled so therefore it can't be altered reversed cancelled and so if on ethereum this is approximately 13 minutes now what about on ZK sync era or ZK syn ofoia so finality is tied to ethereum finality as we were explaining a little earlier so from the time taken to sending a transaction to when the L1 smart contract updates the L2 State what is this time frame and so this has a couple of steps that it's breaking down here so first of all after the users submit the transactions they need to fill up the batch that takes a few minutes that batch of transactions needs to be committed to ethereum then a proof needs to be generated and submitted and verified by the ethereum smart contract and then finally the batch is finalized and this can take approximately 24 hours and these steps correlate to these sending validating the proof and then executing and finally achieving finality that's what these steps are referring to is this breakdown here now you may say to me K that makes sense it makes sense to me that it takes approximately 24 hours for all leave this to happen so how come it says it's processed on ZK sync era and you still haven't really explained to me how come I can see about in here you just told me that it was going to be 24 hours and yeah that sounds super confusing and the answer is again in the ZK sync documentation this instant confirmation section so even though the finality is around 24 hours you can consider your transactions submitted as having instant confirmation so that they can be instantly displayed in the UI even though they're kind of unconfirmed and you can consider these assets as immediately transferred and you can make further transfers but you should be cautious and wait for full finality because things can be rolled back and you shouldn't consider them fully received until you have full finality and so that's why here we have this instant confirmations where we have the funds it says it's processed on ZK syn era but it's not fully final the transactions haven't been validated using the ZK proof and so that's what these steps are referring to here so now you have sent your very first transaction on ZK sync aoia that is amazing now there is a lot of information to digest here but the very last thing that I want to explain to you is why we are doing this why are we interacting with ZK syns ofoia why are we going to be deploying our contracts to ZK syns ofoia throughout this course now I just want to make a brief disclaimer to say that ZK sync are kindly sponsoring updraft in order to bring you the highest quality most amazing content to become the best smart contract developers in the world now here at cyphon we would only ever recommend to you tools and chains and applications that we think are the best and that we ourselves would use and so there is a number of reasons that we will be using ZK sync and ZK sync ofoia to deploy and interact with our smart contracts and working with throughout this course let's give a little breakdown of this right now because I don't expect you to just take our word for it you can make your own judgment we'll give what you our reasons why and then you can understand the reasons why we are going to be doing this so as we have discussed ZK sync era is a layer to ZK rollup and there are four main reasons that we think that you guys should be using ZK sync error first of all security so as we were saying earlier the security of ZK sync error is directly inherited from ethereum if ethereum detects an issue and rolls back so does ZK sync error the transactions are verifiably legitimate as ZK sync uses cryptographic validity proofs to prove that the transaction is legitimate secondly it's evm compatible now when you compile your smart contract it doesn't compile to evm by code which you don't really know need to know what this means but instead said it compiles down to era VM bite code which is like a ZK sync special version the ZK sync compiler K Suk can compile and understand solidity and this means that you can take your smart contracts that you've written in solidity and deploy them to ZK sync era without really making any adjustments there are a couple of really tiny nuances here but we will be walking through them so you don't need to worry about that at all thirdly ZK sync supports ethereum wallets out of the box so no need to create a special wallet what does this mean for you just means that you don't need to create anything special you can just use your metamask as we were earlier and your address will be exactly the same which again we saw earlier the address on ethereum will be the same as on ZK sync era your address on sepolia will be the same on ZK sync sepolia and there's nothing you to do it happens automatically now the fourth reason and in my opinion the best reason is that it is lowc cost and scalable as we were talking about earlier due to the transactions being bundled up together the gas costs is split among all of the transactions in the bundle meaning that is super low cost and what does this mean for you it means that users interacting with your protocol don't have to pay really high transaction fees as the network grows you're not going to have issues so when everyone else is deploying their protocols to ethereum and then down the line as the system grows like we want it to and we're gaining more and more users they're going to have to Port their users over to a rollup solution which hopefully is also verifiable like ZK sync using ZK proofs now you because you guys are clued in because you're here are updraft won't have to do that cuz you guys are already on ZK sync so as the system grows you're not going to have any problems your users are not going to be faced with really high transaction fees you're not going to have really high transaction fees in order to interact with your contracts or upgrade them and this is the true power of ZK sync and that's why ZK sync are our recommended chain and thank you again for ZK sync for sponsoring if you'd like you can also deploy to your own favorite rollup whether that's arbitrum optimism or scroll or any of the other rollups that are evm compatible out there and so now you have everything that you need to know about l2s and rollups and ZK sync era and why we will be using it throughout this course and so that was a lot of information again you can go ahead and take a break in order to digest this information but I will pass you back over now to Patrick and I'll see you again later in this course so that's it for the blockchain basics and the blockchain explainers with just this information you now can go off into the world and start working with blockchains and interacting with blockchains with at least some level of knowledge as to what's going on you should be incredibly proud of yourself for just making it this far definitely be sure to give yourself a pat on the back and a round of applause now that we've gotten a lot of the basics and the fundamentals out of the way let's start jumping into the coding aspect this is where you're going to learn how to actually build these smart contracts how to build these trust minimized agreements in these blockchains and in these smart contract platforms this next section this solidity Basics the solidity fundamentals section will give you all the skills to start actually coding solidity and understanding how these smart contracts work underneath the hood so at this point absolutely give yourself a high five maybe say hi in the GitHub discussions maybe say hi in the community on Twitter on Reddit Etc and be proud of just making it this far the journey has really only just begun but you've already learned so much let's begin the next section and let's jump into the code welcome to the solidity fundamentals course solidity as we mentioned in the blockchain basics course is the most dominant smart contract programming language and once you get the skills to code solidity and work with solidity you will be able to go out and become a smart contract developer security researcher and enter this blockchain world as a very technical person I'm so excited for you to go through this because these are the steps that will make you a phenomenal blockchain engineer so welcome to the city fundamentals myself and Kira will be the instructors for this course and if you missed these already let's once again start with the best practices for working with this course so let's begin our journey by talking about some best practices that way you can get the absolute most out of this course and be as effective as possible now you're either watching this on cyphon updraft or on YouTube and I encourage everybody to watch this on cyphon updraft because we've got a ton of features to make the learning experience that much easier for you so if you are watching this in Cypher up trp though there's a couple links I need you to be aware of the first one in the top right is going to be the GitHub resources page this will bring you over to what's called a GitHub repo or a GitHub repository or basically a site that has all the code and all the information and basically all the materials that you're going to need to learn everything in our curriculum you could basically think of this as your Bible for the duration of your blockchain developer Journey additionally in this GitHub there's a discussions tab right here that you can click on and in here is where you can ask questions discuss with other people taking the course interact with members helping out and it's where you can discuss anything that you're having trouble with then on the other side you'll see this tab called written lessons if you cannot stand the voice coming out of my mouth you can just flip over to that and just read the course curriculum as well if you prefer the written content over the video content and it's good to go over to the written lessons anyways to maybe copy paste some stuff if you scroll down here right now it's blank but if anytime there's an update to a video something's changed in the video and we haven't swapped out the video yet you'll see a little updates section with information saying hey the video says this but you should do this instead now like I said this is a very fast-moving industry and sometimes things change and sometimes things need to be updated so when you're watching one of these videos be sure to look for the updates tab at the bottom and then additionally whenever you're working with the code that we're working with I will give you a link to the finalized Edition that you can use as a reference as well to make sure that the code that you're working with actually is going to match what we are going to build additionally if you think you found something that is different or doesn't quite work be sure to make a discussion for it in that GitHub repo like I said it's going to be your bival additionally there's a link to join the GitHub discussions this is your platform to ask questions engage with the community and learn with both other people taking the course and also our Tas who are going to be helping you out along the way additionally there is a link to the Discord for more realtime communication I urge you to ask questions in the GitHub discussions as well because those are going to be indexed going to make them much easier to Google search later and have them show up as opposed to Discord Discord is still phenomenal for you to join them for those of you watching on YouTube hello you should scroll down to the description and in the description are going to be links to these resources as well and additionally a link to cyphon updraft if you've been watching you've already seen some of the advantages that cyphon updraft has including written lessons single videos and there's also ways to track your progress instead of having to scrub on a giant YouTube video so for all of you who are watching this on YouTube definitely be sure to go over to cyphon updraft sign up there and watch the curriculum there because your learning experience will be much better but leave this video playing in the background on YouTube so we get the bump from the YouTube algorithm thank you that being said as we go through this course we're also going to teach you some best practices on working with artificial intelligence how to best prompt these AI so that they can give you the best results just keep in mind they sometimes get things wrong and it's a good idea if you are going to use an AI to fact check it with a human or another resource so be sure to say hi in the discussions and maybe meet some like-minded peers and additionally once we do get to the coding portion of this course it's a good idea to code along with me as I'm explaining things so having the video up as well as your coding screen is a good idea so you can follow along with me at I'm explaining it if you're watching this on cyphon updraft you can just click the little video pop out button and have the video pop out as such en code next to it all of this is to say if you run into an issue jump to that GitHub repo and make a discussion we will also be giving you some tips very soon about how to best make a discussion yes asking questions to other human beings is a skill and we're going to try to teach you to be the most effective because asking well formatted questions is not only the secret to being a fantastic AI prompt engineer but all also becoming an incredibly successful developer we're going to learn how to ask well-formatted questions and whenever we post on discussions or forums or whatever we're going to work on formatting them as best as possible take breaks I cannot tell you how many people have tried to rush through these courses and be like Oh I'm going to finish in a single weekend your brain doesn't work like that your brain needs time to absorb the information so take breaks maybe every 25 minutes to a half hour take a f- minute break or maybe you like working in longer chunks maybe take a whole hour and then take a 15 20 minute break don't try to rush through the whole video in a day you're not going to retain the information go outside go for a walk grab some ice cream get some coffee go to the gym your brain needs time to have the information settled maybe every 2 hours just step away maybe be done for the day work at whatever Pace makes sense for you everyone's going to have a different learning Pace there is no right speed for this course I've had people take my courses in 2 weeks in 3 months in 6 months it doesn't matter pick a pace that you can do and stick to it not only work at your pace make sure that I'm talking at a pace that makes sense for you there's a little gear icon in the YouTube video here where you can change the speed of how I'm talking and how fast the video is going so if I'm talking way too fast for you then you can slow me down but if I'm talking too slow then you can speed me up and if you're watching this on cipon updraft you have the same dials as well in the bottom right hand corner additionally if English isn't your native language we have seven different subtitles in the cyphon updraft video player as well so make the adjustments you need to make me go the speed you want me to go and of course this course is modular so you can Bounce Around topic to topic and go to where you want to go if you don't want to do any full stack stuff then skip that section if you want to go right to the advanced stuff do that like I said go the pace and take the learnings that you want to do and after every lesson it might be a good idea to go back and reflect on each lesson to really make sure the knowledge gets engraved repetition is the mother of skill and we're going to be repeating a lot of smart contract development now the last bit here is in the cyphon updraft platform we're going to have quizzes that you can take to help see if you learn the knowledge that you were supposed to learn if you're watching this on YouTube you don't have that so go sign up for Cypher updraft and then play the YouTube video in the background so the YouTube algorithm bumps us up but additionally at the end of every section if you go to the GitHub repo associated with that section and you scroll down there's going to be a bonus nfts section with a link this will bring you to a coding Challenge on chain that you can actually solve to Mint yourself in nft a badge of honor proving that you gained the knowledge that you were supposed to these are optional challenges that you can do to try to make sure that you actually learned what was meant to be learned here and if you do solve them you get a very cool nft along with it don't know what an nft is don't worry we'll teach you later blockchain development and open source development world is incredibly collaborative so be sure to use tools like of course the GitHub discussions tab ethereum stack exchange the decentralized Q&A Forum piranha issues on different teach you to unblock yourself on this and really anything in life plus syncing with other people in the space makes it way more fun before we get started an important note the GitHub repo is going to be the cyphon slf foundary full course that we work with you may see references to a GitHub repository with a different name such as Foundry full course f23 or chain Excel Foundry full course but this the GitHub repo that you should be working with sometimes the names of our GitHub repositories or these links will change so just be sure to use the GitHub resources in Cypher updraft or if you're watching this on YouTube the links that we provide to you so that you always know that you are on the correct link now that we're getting to the coding part I need to stress to absolutely use the GitHub repository or go to the GitHub resources associated with Cipher updraft if you're on the GitHub repo right now and you scroll down to this section down here welcome to remix remix simple storage and this is going to look a little bit different when you come to it you can click on the GitHub repo associated with this lesson this will have all the code that we're actually going to be working with for this section as well as a read me section which is going to have a lot of notes on how to actually work with the code and instead of making issues and discussions on this repository here if you have an issue please use the discussions tab of The Foundry full course here or use any of the areas that we've laid out in the questions section we're going to teach you how to ask questions so that they have the highest probability of being answered by either somebody else in the community by an AI or by a forum additionally please be sure to check out web 3d. for more information as well I highly recommend that you pause the video right now and make accounts for first of all GitHub and then at least stack exchange ethereum additionally chat gbt is a great resource to make an account for just remember that it will often get things wrong and isn't quite up to date find you don't need to make an account for but it often gets things wrong sometimes as well typically for each coding section I'll give you a brief rundown of what we're actually going to be building and in this lesson we're going to be building this exact smart contract and we're going to be building your first smart contract ever and we're going to deploy it to a blockchain at the end of this section you are going to have deployed your first smart contract ever so be sure to get to the end so so you can deploy your first smart contract we're going to be using something called an IDE called remix to deploy and interact and work with this smart contract which is going to be very exciting it's highly recommended to get the best experience out of this is for you to follow along and you to code with me you can change my speed on the YouTube video if I'm coding too fast or I'm coding too slow but you taking the time to write out the code as I code along with you is going to ingrain the knowledge into your brain repetition is the mother of skill and I want to make sure you come out the other side with skill to actually code this we're going to be using a tool called remix you can either Google search it or you can just come to the GitHub repo or web 3d. education and click this link to remix which will pop open the remix web ID so let's go ahead let's jump in and let's learn to deploy our first smart contract at the end of this lesson you will have deployed your first smart contract you'll have written your first bit of solidity and we are very excited to get through this part welcome to the remix IDE or the integrated development environment this is where we're going to learn to write a lot of our code in the beginning if you want you can go ahead and accept to help out remix here and if you've never been to the remix website before it'll give you a tutorial walkthrough of some of the features that remix has to offer for example it has a solidity compiler solidity is the programming language that we're going to be using in this course to code our smart contracts where and we need to compile them when we've written the solidity we'll learn about that in a little bit we have a tab here where we can actually deploy our contracts to a blockchain and we have all these different folders and scripts since we can actually write JavaScript and typescript in remix as well but don't worry about those too much for now because I'm going to be explaining everything that we're going to do remix is an incredibly powerful tool because it has a lot of features that allow us to really see and visualize what our smart contracts do eventually we're going to move off of remix to a local development environment however remix is a tool still used by some of the top Auditors and smart contract developers in the space when they want to quickly check something out and additionally it's fantastic for learning the fundamentals of solidity the left hand side is where we're actually going to start interacting with remix if we bring our Mouse up to the top this little file explorer is where we're going to have all of our files and where we're going to write our solidity or our smart contract code if you want you can leave all these folders in here but I'm actually going to go ahead and delete everything so that there's less for me to work with or or deal with so I'm just going to go ahead and rightclick and delete everything in here just so I can start completely from scratch again if you want to leave all of these in here feel free to do so doesn't matter I just think it's cluttering up my mental space a little bit now we have a blank remix project and the first thing that we're going to want to do is create our first file to start writing and deploying our solidity smart contract we're going to go ahead and click the create new file right here and type in simple storage. Soul doou tells our compiler that this is going to be a solidity contract a solidity file and we're going to be writing solidity inside of this file which again solidity is the most popular smart contract programming language and you'll see we actually get popped up a simple storage. Soul on the right hand side which you can type in and actually write our solity code now right below the file explorer button is a little search icon which allows us to search for different code in all of our contracts so for example if I type in hello in here and I copy that paste that into the search bar hit enter we can see that it found this line hello in our simple storage. Soul let's go ahead and delete that right below that search icon is this solidity compiler and you'll see a bunch of different stuff pop up which tells us about our compiler configuration and we can see even more advanced configuration if we hit the drop down we're not going to hit that for now let's go ahead and double click this solidity compiler over here so we can just see the simple storage. soulle I'm also going to click this hide terminal button so that we just see our simple storage. soole now the first thing that we want to do in all of our solidity in smart contracts is write the solidity version that we're going to be working with solidity is a constantly changing language and we want to be very specific about what version we're going to be using to write our smart contract as each version does different things to write your version you're going to do pragma solidity and then type your version for most of this course we're going to be using 0.819 as that's the most current addition of solidity however getting used to working with different versions of solidity is really good for you as you're going to be working with different versions of solidity no matter where you go certain versions of solidity are considered more stable than other versions right now there's a popular tool called Slither which recommends using 0.818 so if you want to default to 0.818 for this course feel free to do so we're going to be using a couple different versions as we code so this line says we're stating our version now these two slashes here stand for what's called a comment in solidity and this allows you to write anything after the two slashes and when we compile or run our code it will just ignore what's in here so we could type blah blah blah whatever we want cats are cool and it doesn't matter you can write anything in here I highly recommend as we're going along you should write comments in your own code as well for you to refer to later on and additionally feel free to copy all the code that you write and paste it locally so that just in case your browser cache refreshes or something you won't lose all the work you've done so so before you lock off for the day copy paste this into a text file so that you can have it for later but a good comment for here might be this is the version now writing our version like this in solidity tells the solidity compiler that we're only allowed to use 0.88 when compiling this however maybe a new version comes out and we're okay to use anything newer than this version to tell the compiler that we add this little hat this little carrot which says this contract only works with 0.818 or anything greater than that this means 0.819 would work when 0.820 comes out that one would work however 0.8.7 would not work if we were working with 0.818 or above if we don't have the carrot this tells the compiler that only 0.818 will work with this code if we want to use solidity versions within a range we could do something like this we could say we want our version to be greater than or equal to 0.8.1 18 but less than 0.9.0 this would tell the compiler that any version between these to is a valid version for example 0.9.1 would not work neither would 0.9.0 because these are not strictly less than 0.9.0 great so now we know how to do compiler versions now the next thing every smart contract needs to start with is something called the spdx license identifier now this actually isn't required by the compiler it'll actually throw a warning if we compile and it won't error it's fine if you don't have this however it's highly recommended this is a way to make licensing and sharing code and IP of your contracts a lot easier from a legal perspective I have a link to more about how licenses work in the GitHub repo associated with this section of the course MIT is known as one of the most permissive licenses it basically means anybody can use this code and pretty much do whatever they want with it I wouldn't worry too much about the licenses right now but let's actually go back to 0.8.9 and on the left hand side let's scroll down down to this compiler button and open this back up even right now now that we don't even have any code we can actually go ahead and compile this contract now you might see a red squiggly and you might see a warning here but don't worry about that for now to choose our compiler version We scroll up to this section and we can choose the compiler version that we want to work with most of the time though if you just hit compile simple storage. or you hit this big compile button it'll automatically choose the version for you for example if I scroll down but I hit compile it'll automatically flip up to 08.19 and we were able to go ahead we were able to successfully compile this code now it says no contract compiled yet because we haven't put a contract in here yet we just put the version of city that we're working with compiling our code means taking our human readable code and transforming it into computer readable code which is essentially a bunch of zeros and ones or it's bite code computer code is very specific instructions for the computer to use or in our case the blockchain to use for our contract we'll learn later about Machine level code and op codes and evm codes in a much later section of this course Additionally you can hit command s or control s which will also save and compile you'll see I kind of have a trigger finger and I will out of habit hit command s all the time because as somebody who codes a lot I need to make sure I save all the time otherwise things might not work as intended as you saw if we use a different version of solidity and we hit the compile button it'll automatically flip back but for example let's say I wanted to use 0.8.7 anything greater than that and we're on compiler 0.8.9 and we hit compile it won't change however if I use something less than 0.8.7 and we hit compile it'll change because it wants to automatically select a solidity version that is appropriate for the version that you chose again I want to use 0.818 and I'm going to hit compile and and we're good to go now we're going to go ahead and start writing our contract and to get the full screen view again we just go ahead click the solidity compiler so that we can just see our code here to start writing our contract we're going to use a keyword in solidity called contract this tells solidity that the next piece of code is going to be the name for our contract that we're going to create you can think of a contract very similar to a class if you're familiar with JavaScript or python or Java or really any objectoriented programming and we're going to go ahead and give our contract a name here we're going to call ours simple storage and then we add this little open and closed curly braces or curly brackets everything inside of these curly brackets is going to be considered part of this contract simple storage now if we hit enter we go back to the compiler and hit compile we can see once again this little green check mark pop up this means our compilation has been successful if we were to remove for example this curly brace and hit compile we would see we would get this error compation failed with one error and if we scroll to the bottom it'll tell us where the error actually is and we'll get a little red popup saying what line the error is actually on we'll learn about debugging these errors in a little bit but let's add the curly brace back go ahead back to the compiler compile and we're good to go hypothetically we could deploy this smart contract right now this is a valid contract although it doesn't do anything but but congratulations technically with just this little piece of code you've written your first smart contract I spelled version wrong so we're going to correct that city has many different types of things that you can build in these smart contracts many different data types or just types if you go to the solidity documentation at docs. solidity l.org again link to this in the GitHub we can select the types section on the left hand side to learn more about solidity types if you want to get a holistic view of all the different types you can go ahead and read this documentation some of the basic types are going to be Boolean Boolean uint and an address and bytes bites is a lower level type which we'll talk about in a little bit a Boolean is some type of true false value a uent is going to be an unsigned integer AKA a positive whole number meaning no decimals no fractions a integer is going to be a signed whole number meaning it could be positive or negative but again is a whole number number and then we have an address which is going to be well an address it's very similar to if we open up our metamask and we click this account here it's going to be something like this there are some other types as well and ways to create your own custom types but we'll learn more about that later on we can use these different types to Define different variables variables are essentially holders for different values and these values can have one of these types for example we could create a variable called has favorite number which would represent if somebody has a favorite number this has favorite number could be true or false either they do have a favorite number or they don't to tell solidity that this has favorite number is a true false or a Boolean we would add this Bull keyword before has favorite number so this has favorite number is going to be either true or false and to set its value we're going to give it this little equal sign and say true so now has favorite number is a variable that represents true we could also say has favorite number is is false meaning that somebody doesn't have a favorite number for a uent which again is an unsigned integer we could say uent favorite number equals 88 this means that this variable favorite number is going to be 88 a uint and int are actually special in that we can actually specify how many bits or bytes that we want to use for example we could say U 256 un 256 specifies this variable favorite number has 256 bits we're not going to go over bits and btes in depth right now but if you want to get a quick refresher we've left a link in the GitHub repo associated with this course to give you an overview of bits versus bytes and how they work an easier way to think about this is really just how big can it get the bigger the number over here the bigger this favorite number can be the maximum size is a ENT 256 and if you don't specify the U 256 it defaults to being a u 256 so this and this are the same thing this this same thing you could also have 8 Bits 16 bits 64 bits Etc often times it's better when we're writing our code for a readability standpoint to be as explicit as possible so you'll see me pretty much always writing U and 256 because I want to be very explicit with how many bits I'm using for U 256 even though they mean the same thing instead of a u 256 we could also have this be and int 256 and actually let's add that Boolean back up here now an INT can actually be positive positive or negative so we could have our favorite number be88 if we wanted to we can also have strings or text variables which I didn't name up here but I'll say why in just a minute we could say string favorite number in text equals 88 let's actually make this positive 88 even though an INT could be positive or negative I'll put this little semicolon here you'll notice that at the end of every one of these lines I'm adding this semicolon this semicolon is how you can tell solidity that a statement has completed so this semicolon is saying the end of this line is right here if we wanted to we could put all of our code on the same line like this and this would compile fine it just looks really ugly so we always want to put our code on a new line after the semicolon a string in solidity is basically text that represents well words so I could say 88 instead of having 88 in here to tell solidity that something is a string you have to put it in between quotes I could put really any combination of characters in here even like hello or follow Patrick on Twitter and let's actually do you 256 here favorite number and we'll do an INT 256 favorite int equals 88 this way we'll just have an example of all these different types on screen we can also do an address so we can say address my address equals and we can go into our metamask copy the address and paste it right into remix and add that semicolon and now we have our address type in remix and then finally down here we're going to say a byes 32 object favit bites 32 equals cat and we're going to put it in quotes just like we did the string up here and what's interesting about the string object is that strings are actually secretly just bytes objects specifically for text so a string can actually get converted to a btes object really easily because under the hood they're essentially the same thing bites typically look like something like xrex and then a whole bunch of random numbers and letters that represent the hex of whatever the btes is and can often be represented as strings like cat we'll talk about bites more in the future similar to U went 256 and into 56 you can have different size bytes like byes 2 byes byes four bytes 8 Etc all the way up to 32 you can also have just straight up btes and not have a number but that's a slightly different type and we'll go over that later as well a u like this and a u 256 are the same thing but a byes 32 and a byes with nothing are actually different so keep that in mind for now the largest bytes like I was saying is actually 32 so for example we can't do a bytes 64 and if we type that in Here remix actually goes hey there's an issue here and if we try to compile this we scroll down we'll again see this little error code here and this little error pop up it even gives us an output declaration error identifier not found or not unique it gives us the line and we can say ah Whoops a Daisy this should be a bytes 32 and we can go back and compile this for our simple storage contract let's say that we only want to store a favorite number this contract is going to be a contract that allows us to store our favorite number and some different people's favorite numbers as well so we're going to go ahead and delete everything except for the U 256 favorite number so we're going to go ahead and delete everything and boom and we'll pick a smaller favorite number just to make it a little mentally easier now these variables actually have default values so for example if I don't set my favorite number to anything and I have a line that looks like this you'll see that this actually compiles fine favorite number will actually get defaulted to zero and all of these types have a different default value un 256 is zero booleans is false Etc so saying U 256 favorite number and not having an equal sign after here is the same as doing U and 256 favorite number equals z so for now let's not initialize it to anything so that favorite number starts off as zero and remember as you're coding along here and typing along with me if you get confused make sure to write your own comments for example we can say favorite number gets initialized to zero if no value is given now let's go ahead and learn to make our first function basic solidity functions section functions or methods functions or methods are a subsection of code that when called will execute a very specific small piece of our entire codebase if you're familiar with JavaScript or python or any other programming language functions and solidity are exactly the same functions are identified by the keyword function let's create a function and name it store and we're going to have this function be responsible for actually updating our favorite number we're going to store a new favorite number so you first write the function keyword the name of the function and then you add these two parentheses whatever is in between these two parentheses represents what we're going to pass or send to our function or the parameters that we're going to send to our function for example we need to tell our store function what value it should use to update favorite number so we're going to tell our store function it should to take a un 256 and this variable that we're going to pass to it we're going to call underscore gorit number it's important that we give it a different name then favorite number up here and we'll talk about that in a little bit then we're going to say this is going to be a public function and we'll explain that soon too we want to put these little curly brackets in here as well and we're just going to say favorite number equals underscore favorite number and without going too deep into what this is doing we're saying I'm not going to explain public yet but we will in a minute but what we're saying is whenever you call this store function you're going to set our favorite number variable to whatever variable that we passed I'll explain why we do this underscore here as well in a little bit and with just this we can actually start to simulate what this smart contract will do and if our store function will actually work correctly so what we can do with just this code right here is come over back to the compile Tab and hit compile make sure that we get this green check Mark in that everything looks good and then we can go down to this deploy and run transactions tab our deploy and run transactions tab has a ton of different parameters in here on how to actually deploy and run with our transactions we're going to deploy this contract to a simulated virtual environment so we're going to deploy it basically to a fake environment we're not going to be deploying it to a test net we're going to deploy it basically in kind of an imaginary world in order for us to do this first make sure we're on this remix VM and for us we're going to just use the default which is the merge doesn't really matter which one you're on just so long as it's the remix VM this remix VM is a fake local blockchain where we don't have to wait for transactions to complete and we don't have to deal with any of the oddities on deploying our code to a real test net or a real main net and don't worry about the rest of these for now we also get an account here when we run on our fake remix VM we get automatically given an account with a different amount of ethereum for each account you can think of each one of these accounts similar to our metamask accounts in metamask except for these are fake imaginary accounts that remix just gives to us for our transactions including deploying contracts we're given a gas limit values that we can send and we also choose our contract depending on which one we've compiled since we only have one contract in here we only have one to choose from so on the left hand side to deploy our contract to this fake remix VM environment we're going to go ahead and click the deploy button if we scroll all the way down to the bottom now under this deployed contracts we can see we actually deployed a contract here simple storage we can see the balance of zero and we see this big orange button that says store and then un6 favorite number on our local blockchain this at blah blah blah here this is going to be the address of our contract similar to our wallets how they have different addresses every single contract has a unique address as well and if we hit this little copy button and we close this and we put as a comment here and we paste it we can see this looks exactly similar to an address such as what's in our metamask and then let's go ahead and open the deploy back up and we see that deployed contract is still there additionally if you hit this little show terminal button and you pull this up we can actually see we have this little comment here creation of simple storage pending and we have this green check mark here this is notating that we actually sent a transaction to deploy this contract similar to sending eth back and forth in order for us to deploy a contract we actually have to send send a transaction since we're doing this on the remix M this is a simulated transaction a pretend transaction inside of our remix environment you can even hit the little drop down and see even more information about this transaction you'll see a lot of familiar keywords like status transaction hash from to gas Etc deploying a contract uses the exact same process as sending a transaction for just eth the main difference is we populate this data or input field with a ton of that bite code and if you copy this input field or this data field and go ahead and make a comment in here you'll see it's a massive line and this massive line notates all the data associated with this smart contract all the machine readable code remember anytime we do anything that modifies any value on the blockchain we actually do that by sending a transaction deploying a contract is modifying the blockchain so we do it in a transaction which means yes we spend gas now this Big Orange button over here actually resembles our function store in our smart contract and if we add some numbers in here and we call it again if we pulled the terminal up we can see transact to simple storage pending and we see we sent a transaction which called this store if we do this again with a different number we call it we can see our terminal say oh you sent another transaction to update the state of the blockchain and if we scroll all the way up to our account you'll see that we have a little less ether in our account because we had to spend the gas associated with well a deploying this contract and then B calling these functions and then for example if I add this if I add five in here and hit store we'll send a transaction to store five on the blockchain now you might be thinking okay Patrick that's pretty cool but what is the value of favorite number you're telling me that this function store is updating favorite number but I can't really see it how do I know that favorite number has actually been updated to five well the reason we can't see it is that the visibility of our favorite number is defaulted to internal so us not having anything here or right internal are actually meaning the same thing and we'll talk about visibility and default visibilities in a minute but in order for us to actually see the value of our favorite number we'll go ahead and add the public keyword to this this changes the visibility of favorite number to public and like I said we'll talk about visibility in a minute but let's go ahead and compile this let's go ahead and delete this contract by hitting this x here and let's redeploy this contct cont with this new public keyword so let's go ahead and hit deploy and now if we scroll down and we open up our simple storage we actually now see a blue button labeled favorite number and if we click it now we can see it returns zero which makes sense because we know that you 256 is default to zero now if I go ahead and add five into here and hit the store button I pull up the terminal we'll see that we went ahead and executed that store function call that transaction that's going to take input this five as favorite number and set it to our favorite number now if I hit favorite number you can see it does indeed return five showing that we actually updated our favorite number with this function call and remember though I'm going to go ahead and do the scan and remember when I hit X here this is just removing it from this window here if you actually deploy a smart contract to the blockchain hitting X from this window doesn't do anything because once you deploy your contract it's immutable it's out there and you can't just delete it by clicking X and remix functions in Ables can have one of four different visibility specifiers in solidity public private external and internal if you don't give one of these keywords to your variables it'll get defaulted to internal public functions mean that they're visible externally and internally and you'll see here it says it creates a getter function for storage SL State variables this means that other people can call this function or call this variable when we didn't have a visibility for favor number it defaulted to intern which is why we didn't see this blue number pop up because internal it means that other contracts and people aren't allowed to call on this favorite number we have a little bit more here it says it actually creates a getter function for storage SL State variables when we add this public keyword here it's actually equivalent to us making a getter for this favorite number variable a getter function and I'll show you exactly what the function will look like in a little bit now keep in mind though everything on chain is technically public so setting a function or variable to private isn't a good way to hide what the value actually is there and we'll talk a little bit more about storage and visibility and and that much later just remember everything on these evm chains is actually public data this public variable just means any other contract can call this favorite number and see the value what's in favorite number and private means only the current contract can external functions mean they're only visible externally and this is only for functions not for variables and it means another function inside this contract couldn't call an external function and internal means only the current contract and its child contracts can call the function we'll talk about child contracts and inheritance in a later section so let's just keep it public for now the reason that we have this underscore here in this parameter is because we need to tell users that this variable in here is different than favorite number and there's a couple different conventions on naming local variables versus these what's known as state variables or variables outside of functions and we'll go over those later in the course now here's something that's really interesting as well remember how I told you earlier that sending ether is a relatively simple transaction right well let's see what happens when we call this store function and we update favorite number to five let's actually call it one more time and we hit the little drop down here let's go to gas and we'll see gas actually cost 27,000 gas which is a lot more than the 21,000 gas it cost to just send ether between accounts remember every time you update the state of the blockchain it's going to cost gas now what do you think will happen if we do more inside of this store function for example we say favorite number equals itself + 1 let's go ahead and compile this let's delete our old simple storage let's deploy this new one remember the last one cost 27 gas let's pull up the terminal and remix actually gives us a little tool tip and it's saying an infinite gas which we know is actually wrong but let's go ahead and add 1 2 in here and we'll hit store we'll see this transaction we'll scroll down we'll see gas is actually a lot more it's way more gas it's 50,000 gas with just adding this line here now technically I'm not telling the full story here because there are some other gas costs associated with the first time you run a function but it's still more right and that's what's important here so so let's go ahead and delete that line and go back to our old function here now let's talk about something called scope for a second so if I create a variable in here called un 256 test VAR equals 5 and I create a new function called something make it public could I access the test VAR and then maybe change it to six or seven what about the favorite number VAR what about the favorite number variable could I access that to seven well let's go ahead and see what happens if we try to compile this we try to compile we actually go ahead and get an error in our compilation Undeclared identifier whenever you create a variable it can only be viewed in the scope of where it is if that's confusing just look for the curly brackets the reason that our something function can read the test farar is because this testar isn't inside of the curly brackets of something the reason it can't read the testar is because testar was created way up here inside of these curly brackets outside of something but favorite number wasn't created inside of these curly brackets so how come it knows what favorite number is well something is inside of these curly brackets in favorite number was created inside of all of these curly brackets if favorite number was created inside of here it wouldn't be able to access favorite number because again favorite number is inside of this scope and not this scope if you create a variable like testar inside of store you can only access this test bar inside of this store function and not anywhere else the easy way to know what the scope of a variable is is just look for the curly brackets so let's go ahead and delete this something variable and and let's delete this test far and let's recompile now like we were saying earlier when we add this public keyword to favorite number it's the exact same as if we created a getter function to return this favorite number so let's actually write a function similar to what this public keyword is creating so we're going to say function retrieve make this a public view function and we'll talk about that in just a second and we'll say it returns a uent 256 and we'll add the curly braces here and we'll say say return favorit number and often times when these Auto suggestions come up like this you just hit enter and they will automatically do it so if we do favorit and then I just hit enter boom automatically like that now I'm going to hit command s which is equivalent to me going to the compile Tab and hitting compile now if I go to the deploy Tab and let's deploy this contract now we scroll down we now see we still have that store function we have our favorite number function and we have a new blue button called retrieve right now they both start off as zero and then obviously if we update this to five by calling store yep I called store these are now both return five since favorite number is the actual variable and retrieve is just returning whatever favorite number is now as you can see here these two functions are blue but this one is Orange what's the difference why are the colors different well the key is actually with this view keyword here solidity has a special keyword which notates functions that don't actually have to run or don't actually have to send a transaction for you to call them and those two keywords are going to be View and pure a function marked view means we're just going to read state from the blockchain for example in our retrieve function we're just going to read what the favorite number variable is our store function isn't reading it's updating something so and it's changing the state of the blockchain so we have to send a transaction since our retrieve function does doesn't have anything inside here that updates anything it just returns favorite number we don't need to send a transaction so if you add this view function in here it disallows any modification of State for example I couldn't add favorite number equals fait number + one if we go ahead and try to compile this we'll get an error function cannot be declared as view because this expression potentially modify state so we'd have to remove this line or we'd have to remove the view keyword so view functions disallow updating State your functions disallow updating State and they disallow even reading from state or storage this favorite number here is what's known as a storage variable because it's stored in a place called storage we'll talk about that in a later section but if this was labeled pure we'd see we get a little red underscore here because favorite number is reading from State instead of returning favorite number would return something like seven so this would be an example of a pure function this would be an example of a view function because we're reading from State again we'll explain the difference a little bit later and like I was saying before if we call a view or a pure function we actually don't need to spend gas since we're not modifying the state that's why these buttons over here are blue they're representing view or pure functions functions that we can call without having to send a transaction for example if I pull up the terminal here and I pull this this up and I call retrieve we do get another function but it's just a call and it looks different than if I hit the store which has this little check mark they're different because the store is obviously sending a transaction and the retrieve is actually just making a call and not sending a transaction however something weird is going on here if I hit retrieve and I go into the details of this call I can see oh what's what's this why is there an execution cost it says cost only applies when called by contract what's going on there the reason for that is because if another function that does update state that does require a transaction calls retrieve that transaction does need to pay the gas of reading and calling this retrieve function so calling a view or pure function actually does cost gas only when a gas cost transaction is calling it so we can go ahead and call these as much as we want it costs nothing but if another function that does cost gas calls it it's going to cost something for example if our function store here then went ahead and called retrieve like this since store cost gas you're telling this function hey also call this retrieve function which is more work for it to do and since it's more work it's going to cost more gas so for example if we delete this contract over here let's go ahead and compile this let's go ahead and deploy this with this retrieve in here so let's go ahead and look at these These are now zero we'll store five in here we'll select the drop down we can see how much gas we actually sent 50,000 gas let's go aead and drop this now close this out let's remove the retrieve line let's compile we'll hit deploy simple storage these are both zero We'll add five hit store pull up the terminal hit the drop down look at gas it's still 50,000 but it's actually a little bit less than before although I'm pointing at gas we really should be looking at transaction cost because gas is really just actually how much we're sending whereas transaction cost is how much gas the transaction actually cost but in any case it was a little bit less without the retrieve function now I've kind of been glossing over this a little bit but this returns keyword specifies what this function is going to give us when we call it so when we have this returns keyword in our retrieve function here we're saying whenever we call this retrieve function we want to get returned or we want to be given this favorite number of type un 256 we want to return a un 256 from this function now our contract as is is pretty good it does one thing pretty well it's it allows us to store our favorite number update that favorite number and then view that favorite number and in fact let's go ahead and make this an internal variable and we'll have the retrieve function be the way to get this we can have this public but for now we're going to set it up like this and I'll tell you why we're going to set up like that in the future but what if we wanted to be able to store not just our favorite number but other people's favorite numbers as well well what we could do is we could create something called an array or a list of favorite numbers what we could do is we could say instead of just one un 256 we could have a list of un 256 called list of favorite numbers this bracket syntax here identifies that we have a list of un 256 or a list of numbers or an array of numbers an array of numbers is going to look something like this it's going to have maybe the first element is going to be zero maybe the second favorite number is going to be 78 maybe the third favorite number is going to be 90 now arrays are very common in computer science and programming and an array in solidity is exactly the same as an array in any other programming language if you're unfamiliar with arrays arrays or lists are actually zero indexed so the zero here is actually at index zero so we refer to this object here as the zerith object right this could be 77 and this would be the zero withth object the 78 is going to be the first element the 90 is going to be the second element and so on and so forth it's very common in computer science to actually start counting from the number zero and arrays start counting from the number zero we'll learn to play around with arrays more in just a minute so this list of favorite numbers is great but how do we know who favorite number each section is this is our list of favorite numbers how do we know who 0er is who 78 is who 90 is ETC well maybe what we would do instead of just having a raw list like this let's go ahead and comment this line out maybe we could create a new type called a person in solidity you can actually create your own types using the struct keyword so we're going to say struct person and do little curly brackets like this inside of these curly brackets we can Define what this struct person custom type is comprised of and we're going to say for every person they're going to have a un 256 favorite number and a string name now something important to note is oh whoops we have two favorite numbers here remember what we learned about scope since this favorite number is inside of these curly brackets these would Clash a little bit so what we're going to do instead is we're going to rename favorite number up here to my favorite number and we're going to copy paste that down here as well so we're we're renaming this state variable this storage variable to my favorite number and just keeping it down here that way we can have favorite number inside of this struct in any case we created this new type of type person which is a combination of each person has a favorite number and each person also has a name now similar to how we can have a u at 256 a Boolean a string an in 256 Etc we now have a type of person and this is similar to each one of these oh and we're also going to have to update the retrieve down here with my favorite number instead of favorite number now since we have our own new type we can actually create a variable of type person the exact same way we created a variable of type my favorite number so we could say person visibility will be public my friend equals and we'll put person here and put some parentheses here because when you're working with custom types you have to Define both on the left side and on the right side what type it is and in here we would assign a favorite number and a name so we could say seven and Patch like that so now Pat is going to be a person with a favorite number of seven and a name of Pat see the first parameter goes to the first item in the person struct and the second parameter goes to the second item I like being a little bit more explicit when working with strs and actually what you can do is you can put little brackets here instead and you can say exactly what value you're going to assign to what section so I can say favorite number is going to be seven and name is going to be at and we can hit command s or just go straight to compile to see if it worked correctly get that little green check mark Now by doing this we've created our own type person and we've created a variable named Pat with a favorite number of seven and a name of Pat now if we were to go ahead let's delete this old simple storage and let's deploy our new simple storage and we scroll down we now have a new blue button since this is a public variable called Pat and if we click the button if we call this variable we'll see favorite number of seven and string name Pat you can also see this zero and this one which shows the index of each one of these variables or parameters zero is for favorite number one is for name if we added another one maybe bull is cool bull is cool would be at index 2 whenever you create a custom type like this solidity will automatically index them similar to the way that we index our list or our arrays favorite number zero name one whatever's next would be two Etc now this is great for one friend but what if you have a lot of friends which I know a lot of you do because you're taking this course which automatically means you're cool maybe what if you have your friend Mariah that you would like to add to our smart contract like this and her favorite number is 16 or maybe your friend John you'd have to copy paste the line add John in here his favorite number is going to be 12 so on and so forth it might get very tedious to have to write variables for all of these people for all of these friends this obviously isn't a great way for us to create lists of people or lists of our friends so instead of this we can actually use this array syntax that we just learned and create an array of person or a list of persons so I'm going to comment all these out for now and a quick tip here if you're on a Mac and you highlight a couple if you're on a Mac and you hit command backs slash or command question mark it'll automatically comment or uncomment those lines if you're on a Windows I believe it is control slash but you might be able to Google what the actual keyboard shortcut is this is a keyboard shortcut I use all the time so what we're going to do now is we're going to create a list or an array of persons so exact same as we did it up here we'll say our type first is going to be type person array so we're a type person array then we'll State our visibility which is going to be public then we'll get our variable name which is going to be list of people like this so we've created a person array with visibility public and the name list of people and we'll just leave it blank for now so it'll get defaulted to being an empty list which would look like this now if I were to go ahead and deploy this let's delete the last one let's compile deploy we scroll down we select this we now see we have our retrieve blue button and we also have this blue button for list of people when you create arrays with a public keyword instead of being able to see the whole array with this list of people button you actually have to put in the index of the element you want to work with and you get to see that exact element it wants to take a u 256 as an input parameter however obviously our array is blank so if we say what is the person at the zerith index it'll say well nothing because you have a blank array well what about the first index well nothing what about the second one well nothing no matter what you put in the box right now it's going to return nothing we'll show you how to add to this array in just a second this kind of array is known as a dynamic array because the size of the array can actually grow and shrink in solidity a dynamic array is signified by what's inside of these little brackets here if we added a three in here this would be a static array we're saying this list of people can only have a maximum size of three so we can only put three persons in this array Dynamic array static array can have any size can only go up to three any size up to three any size up to four hopefully you get the picture we're going to work with a dynamic array because we're going to want to add a arbitrary number of people to this person array so let's create a function that will allow us to actually add people and update this array and let's delete this comment so below our retrieve function we'll create a function add person and this is going to take two variables as input it's going to take the name of the person that we're going to add it's going to take the favorite number of the person that we're going to add as well as the name so we'll say string memory name and I'll explain this memory keyword in a little bit and we'll do uint 256 uncore favorite number and let's do and let's do underscore name and we'll make this a public function and what we're going to do inside of this ad person function is we're going to take this list of people object and call the push function on it arrays come built in with a function called push which allows us to add elements or add person to our list of people array so what we're going to do is we're going to say list of people. push and we'll add these little parentheses here and we're going to push a new person onto this array now what we could do now let's comment this out for now now what we could do is we could create a new person person new person equals person name favorite number like we did above oops excuse me these are backwards person memory new person which we're going to ignore that for now and then just do list of people. push new person we could do this this is valid syntax and I'll explain this memory keyword in a little bit this is going to create a new person and we push to the list or we could just add this person right into this push piece here so we could delete this line instead of creating a new person on its own line we could say list of people. push person then we'll add in here favorite number name since we're calling this person favorite number name inside of this push object solidity is smart enough to execute this line of code first create a new person and then execute this line to push our person into this list of people object so this function should allow us to push new people into our list of people array so what we can do now is let's compile this let's deploy this let's delete the old one we'll hit deploy now we see if we call our list of people at zero we'll get nothing back because it starts off as a blank array but now we have this new add person function where we can you can kind of see very faintly it takes a string name and a un 256 a favorite number so we can add Patrick 7 we'll hit add person which if you have your terminal you'll see we made a transaction and now if we hit list of people at zero we see we have indeed added a person to the zero withth index Patrick has a favorite number of seven and his name is Patrick obviously if we hit one we'll get nothing back and this will just stay up but if we add another person maybe John 16 add person now at list of people index one we now see John 16 so zero it's going to be Patrick 7 1 John 16 2 is nothing so nothing happens now we've talked about this a little bit already but if we go ahead for example and maybe delete this semicolon and we go to try to compile and we scroll down you'll see we get this error parser error expected semicolon but got bracket instead and it gives us this little red exclamation mark and the line that it's having an issue with all these red errors mean that your code isn't compiling and you can't actually deploy this to the blockchain because solidity doesn't know how to turn this human readable code into machine readable code so we need to add this semicolon here recompile so we get no errors now interestingly though if we go to the top and let's say we delete this SPX license identifier now we compile we scroll down we get a yellow box and it says warning instead of error says warning spdx license identifier not provided source file blah blah blah interestingly though if we compile this we actually let's delete our last symol storage we can deploy this so something important to note is warnings are just that they're just warnings they won't prevent you from deploying or compiling your code errors will prevent you from deploying or compiling your code now even with that being said though it is good to try to remove all of the warnings because the warnings are generally there for a reason they're warning you that you might be doing something bad and sometimes if you have a bug in your code simply just listening to the warnings would have solved it so it's best to listen to the warnings here so to summarize if it's red it's broken if it's yellow you might want to check it out and additionally when it comes to these errors and These Warnings this is where using our Ai and Google searching skills can really come in handy let's say for example I ran our code I get this error I read the error and I don't really understand what's going on here what we can do is we could maybe copy this error and use any of the search features that we talked about resources for this course we can use chat gbt or find GitHub discussions stack exchange ethereum and piranha and I'll explain what each one of these is good for later in the course but for example let's go and try out find find is an AI search engine for developers what it does is it first does a Google Search and then it reads all those links and based off the links it reads it tries to give you an answer so what we could do is we could say I am getting this compiler error in solidity how do I fix it we hit this little dropdown put any code or context here we'll paste our error this is the error like this and we'll go ahead and hit search we get a pretty verbose response on what's going on with our code we can actually take this a step further and we could copy our entire code base and we could paste it under here we say code I usually put three back ticks before and after any code that I use and I'll teach you why in the future well let's go ahead and hit enter and research it actually is able to read our code and say one way to fix the error is to Simply add a semicolon at the end of the line where you push the new person to the dynamic array list of people and we can see if we do indeed get a way to just copy our ad person function and we can scroll down and just paste it on top with it being fixed and we can also say concise because it's being a little too verbose for us we'll hit enter again and it wasn't that concise but a lot of these AI tools like I said are still in beta but this was a good example of how using an AI tool like this can actually help you detect bugs like I said often times they will still get things wrong which is why it's important for you to know about GitHub discussions stack exchange piranha Etc later in the course I'll explain more about how to ask good questions how to do good AI prompting how to format your questions and how to search and learn more one of the key pieces of being a really good software engineer or a good prompt engineer is less about actually knowing the information and more about knowing where to find the information so throughout this course I want you to practice using these resources because they're going to help you be a much stronger developer much stronger prompt engineer and just be better at everything that we're going to go over in this course if find or chat gbt gives you a poor answer be sure to use the GitHub discussions if you have a question specific to this course be sure sure to use the GitHub discussions or if you have a more general question about solidity about Foundry or anything like that you can use one of these resources again I'll go over this more later but great job you've done your first bit of prompt engineering congratulations you don't have to understand this section fully now one thing that we didn't really go over and we kind of glossed over was this memory keyword and you'll notice if we actually delete this keyword and you try to compile we get an error data location must be memory or call data for parameter in function but none was given now the evm can actually read and write to several places and the number of places it can read and write from are actually constantly changing some of the most important ones are going to be stack memory storage call data and code and for now you can go ahead and just look at this easier addition because a lot of these other places are more advanced so for now we're just going to look at the stack memory storage call data logs and then chain data for those of you who want to go ahead and jump ahead and learn a little bit more quickly we have an article associated with this lesson which goes deeper into all these different places that the evm can read and write keep in mind that this is accurate as of recording and often times the evm is upgraded to add more places we're not going to go over all of these areas right now but we are going to go over some of the big ones which are call data memory and storage and this is going to be a little bit Advanced here so if you don't understand this section the first time don't worry about it just keep pushing through it'll make more sense as you go later on in the course call data and memory both mean that this variable is only going to exist temporarily it's only going to exist for the duration of the function call any anytime we call AD person with a different name we can only access this name variable that one time that we call this function if I call AD name hatrick 7 and now I try to list of people at zero obviously we see Patrick at favorite number seven we can actually never access that Patric variable ever again because it existed in memory it existed for a very short period of time just for that single call we could also have call data here and we'll go ahead remove this deploy the drop down and do the same thing we'll add Patrick and actually you don't even need the quotes Patrick do 88 add person we'll see if it's in there sure is call data and memory both mean temporary variables inside of functions most variables automatically default to memory variables strings are a special type in solidity so you have to specify memory or call data and it has to do with the way arrays work in memory but we'll talk about that much later in the course now the question obviously then follows okay well if call data and memory are both temporary variables why have two what's the difference between these two well let's try something let's have this be a memory variable and in here we'll say name equals cat so we're going to reassign whatever people put in here to Cat Let's compile this looks like it compiles fine now let's do call data and try to compile ah we get an error type error type literal string cat is not implicitly convertible to expected type string call data the difference between memory and call data is that a memory variable can be changed it can be manipulated if we pass a memory variable to a function we can go ahead memory and I hit and I hit command s to compile this is valid solidity this is not if you pass a call data variable you cannot modify it call data is temporary variables that cannot be modified memory is temporary variables that can be modified and storage is permanent variables that can be modified my favorite number was actually implicitly converted to a storage variable since it it's added in this state context outside of a function if you create a variable that's outside of any function inside of a contract it'll automatically be a storage variable and let's delete this line let's compile let's deploy again delete this deploy we know it's a permanent variable because we can hit retrieve and we can always access what is in favorite number so if we store 1 2 3 we hit store we can hit retrieve and we can access 1 2 3 so this variable 1 2 3 exists outside of function calls now even though I said there are more places like stack code log return Etc we can only make these variables call data memory or storage and like I said we'll explain that later in the course so let's go ahead let's add this back to memory because that's normally what you'll see now the next question that logically follows is oh okay Patrick well why do we need to put memory here but we don't need to put memory over here in fact if we try to put memory there we get an error data location can only be specified for array struct or mapping types but memory was given like I was saying earlier arrays strs or mappings are considered special types in solidity and the way that memory management works under the hood makes it so that we have to put this memory keyword un 256 is known as a primitive type and solidity is smart enough to know where to put this favorite number always under the hood like we were saying earlier a string is actually an array of bytes and so so as we just saw with the air we need to put the memory keyword for arrays so then the next question is okay well what about the storage variable can I put that here no you can't put that here either since this is a function solidity is smart enough to at least know that ah okay this is a temporary variable that you're working with it's got to be memory or call data it's not going to be storage since this name is only going to exist for a short duration so you got to pick one of these other two so the summary of this section is that structs mappings and arrays need to be given this memory keyword string is an array of bytes so it needs this memory or call data keyword so this code is starting to shape up it has a lot of functionality here we can store variables we can add people but it has a bit of an issue if we have this contract and we want to say oh what was Kelly's favorite number let's say we have four people on the array let's have Pat 7 John 8 Mariah 10 and Chelsea 22 or 200 132 and we ask the question ah what was Chelsea's favorite number well the way we would do it is we'd have to actually Loop through this list of people to find Chelsea so we'd say okay what's at zero ah okay that's Pat that's not Chelsea what's at two Ah that's John what's at three Ah that's Mariah excuse me what's at three Ah that's Chelsea favorite number 232 okay perfect I found Chelsea but obviously if we had a thousand people in this array that would be a very tedious process and that would take a long time for us to find the person that we wanted so the question then is is there a better data structure than a list or an array to use that makes it much easier to access and find the information about the people that we want and the answer to this is using a mapping you can think of a mapping as a dictionary it's a set of keys with each key returning a special set of information about that key so it's similar to a dictionary if you look up the wordthe the wordthe will have a whole bunch of text of Associated only with the word thee so let's create a mapping type and you'll see how it works in practice so we're going to create a mapping like this with this mapping keyword and we'll say the key is going to be a string and It'll point to a u 256 so this is going to be our type obviously what comes after the type our visibility so let's just go ahead and do public for this as well and I like to be very explicit with my naming so I'm going to say name to number sign finding that this mapping Maps someone's name to their favorite number and now with this we have essentially a dictionary where every single name or every single string is going to map to one number so for example if we looked up Chelsea we'd automatically get returned the 232 that we're looking for instead of having to iterate through this list so let's add some capabilities to our ad person function here so that we can update our mapping so we have this list of people. push which add someone to the array let's also update this so it will also add somebody to our mapping to do that we'll say name to favorite number and we put these little brackets in here to specify what the key is and we'll say underscore name and we'll assign that to underscore favorite number what this line is doing is now it's saying all right in our mapping up here in our name to favorite number mapping anytime you look for that person's name you'll you'll automatically get their favorite number back and now you have a much quicker way to access people's favorite numbers just by knowing their name so let's go ahead let's compile this let's deploy this let's delete our old one we'll deploy this now we have this new name to favorite number blue button and so let's go through the same problem so let's say we have Pat 7 John 16 Mariah 32 Chelsea 232 now same thing list of people zero returns Pat list of people one John so on and so forth or we could just go down here and let's say let's look up Chelsea and we automatically get 232 we get Chelsea's favorite number back automatically same thing if we look up Pat we get seven if we look up JN we get Mariah and if we look up cheesecake we get nothing back in a mapping the default value for all the keys is zero so if you look up a key or a word that we haven't added in the mapping yet it defaults to the default value of whatever that type is since RS is a string to U at 256 U at 256 default type is zero if we look for a key that we haven't added we get zero back so now that we've added all this functionality we're looking pretty good we really like the way that our contract is set up we have our my favorite number which is a internal variable but we have a way to read it with retrieve we have our new typing person we have a public list of people array we've got a public name to favorite number got a way to update the favorite number retrieve the favorite number and add people to both our list and our mapping now in the future you'll hear me say that you should never do this before you write any tests before you get it audited but for now this is just a dummy contract that we're going to deploy on a test net so we don't really care but let's go ahead and learn how to actually deploy this to a real test net this is going to simulate what deploying to a real network with real money is going to look like are you ready you should be this is going to be incredibly exciting after you do this successfully you should 100% tweet about it on Twitter on LinkedIn on lens protocol on whatever social media you want it's important to celebrate your small wins surprisingly it'll help motivate you moving forward so first off let's make sure this actually compiles okay cool we've got a green chat Mark there's no warnings there's no errors fantastic now let's go back to the deploy Tab and we'll delete this down here and we'll scroll up and we're going to change the environment we're in this remix VM and we're actually going to move to injected provider metamask remember this remix VM is kind of this fake world that remix gives to us in injected provider metamask means that we're going to literally inject our metamask into this remix we're going to inject our metamask into this website we're going to allow this website to interact with our metamask we'll first get prompted by metamask to pick the account we want to use I'm going to use account one and hit next and we're going to go ahead and hit connect similar to the way we connected to the faucet if we scroll up to our metamask we now see oh it says your account is not connected that's because I'm currently on account two let's to account one and we do indeed see that account one is connected and now before where we saw kind of this fake account with fake ether we see our actual account with the actual amount of spolia e that we have make sure that again be sure to use whatever recommended test net we have in the GitHub repo for us we're using sapoia don't worry about the rest of these for now so make sure you're on the correct test net to deploy to a tant you're going to need some seoa eth so if you haven't been to the faucet be sure to head over to the faucet to get some eth remember you can find those in the GitHub or web 3d. education now in remix what we're going to do we're going to do the exact same process we use to deploy to the virtual remix environment we're going to do that to deploy to the test set environment so we're going to go ahead hit the deploy button and metamask is actually going to go ahead and pop up this is similar to what we saw with the blockchain example with signing transactions we're actually going to sign and send a transaction on the test set it's similar again to us sending ether to ourselves the difference here is though that our data section has a ton of information here all this data is associated with sending this transaction but this one has all of this contract information encoded in machine readable code or our compiled code in details we can see all the pavement information associated with this transaction we can see exactly how much gas it's going to cost to deploy this contract on chain but again we're on the suppo test work so this is fake money anyways to actually deploy this we're going to go ahead and hit the confirm button and now we're going to have sent our function if you have the terminal up you can see we have this call created and it says creation of simple storage pending with this view on ether scan button if you click the view on ether scan button you'll get brought to this ether scan page with this transaction going through on spolia you'll see it's currently being indexed by Ether scan but there's a good chance it already went through and back in remix it actually goes ahead and gives us this green check mark saying that we did indeed deploy this contract you might have to wait a few minutes for this to complete because again we're sending a transaction to a test net blockchain and the blockchain needs to actually produce the block with our transaction in it but if we wait a few minutes on either scan we'll eventually see a success status with block confirmations on this block section here and exactly the same as what we saw with sending e to ourselves we see all this information about the transaction transaction hash status block time from to BL BL Etc but if we scroll down this input data field is much bigger than anything we've seen before because again this is all the data associated with creating this contract and of course we see more gas fee information because again deploying a smart contract to the chain is modifying the blockchain so we have to spend gas now if we come back to our remix and scroll down we're able to see our simple storage contract and we're able to copy the address that it's at so if we copy this address we go back to Ether scan we can even paste this into the bar here and we can see this contract that we went ahead and deployed ether scan is smart enough to know that this transaction created a new contract remember this has to be on The seoa Ether scan not the main net ether scan because we sent this on the seoa test net so now that we have this contract created we have all the exact same functions that we had in our virtual environment but these functions are actually on a test net with a contract that we actually deployed now we can do all the exact same things we were doing on our fake remix environment on this test environment for example we can call retrieve which doesn't send a transaction it just reads off the blockchain and we get zero same as what we got before if we look up a name like Pat in name to favorite number we get nothing back cuz we haven't updated anything if we add zero in here for list of people we get nothing back as well metamask didn't pop up here because these blue buttons are view functions View and pure functions like we said don't send transactions now let's go ahead and actually send a transaction let's update the blockchain let's update our contract by storing a new favor number so let's do 7878 and we'll hit store and we'll press this orange button you'll see you'll get prompted with metamask actually popping up saying okay let's update the blockchain let's send this transaction and if we go ahead and hit confirm the exact same thing happens we'll get this transact to simple Storage storage transact to simple storage. store pending view an ether scan this little check mark we view it we can see the transaction indexing on ether scan and after you wait for a little bit the trans action will go through and now if we hit the retrieve button we can see we have now stored 7878 onchain if we copy the contract address again we paste it into sapoia ether scan we scroll down after a few minutes we'll actually see a second transaction come through we see two transactions associated with this contract the first transaction obviously is the contract creation transaction and the second transaction is us actually calling the store method ether scan is smart enough to know that this is the store method it's not always smart enough to know that but for this one it's smart enough to know and we see that we actually updated our contract and remember in the future please use these test Nets sparingly we're just starting out and we're just learning so it's okay for us to send these transactions here though but let's go ahead and let's keep going because name to favorite number of Pat still returns nothing list of people zero still returns nothing so let's go to add person we'll do Pat 16 we'll hit add person mamass pops up obviously because we're updating the state of our contract we'll hit confirm we see transact to simple storage. aderson is pending it looks like it has succeeded so now if we do name to favorite number of Pat we see 16 get returned and if we do list of people at zero we see we get Pat whose favorite number is 16 and guess what at this point you've successfully deployed a smart contract to a real testet congratulations you should be incredibly excited for yourself be sure to give yourself a pat on the back maybe go for a walk maybe have an extra cup of coffee or an ice cream because additionally you've also interacted with that contract with these buttons and remix that allow us to send transactions to update the state of our contracts congratulations you're a solidity developer but we've got a lot more to go and like I said make sure to celebrate these little wins celebrating little wins will motivate you and excite you to continue to move forward so be sure to take the time to Pat yourself in the back congratulations if you've got this far there's a ton more for us to learn but just you getting here is a fantastic achievement in itself now here if we wanted to deploy to a different test net all we would have to do in our metamask is switch to a different test net like Linea Gilli since we don't have any Linea Gil we actually can't deploy this to a test net but if we used a faucet to get more Linea gorill eth that's how we would deploy it additionally we could do the same methodology for deploying to ethereum main net or any other main net that you want to work with throughout this course the difference here is obviously you just need to buy some ethereum to actually deploy this smart contract remix will automatically update to whatever Network you're working with for example right here it says Ah you're working on the main network but if we were to switch to gelli it would say ah you're working on gelli but if we were to switch again it would say ah you're working on lania in the future we'll learn to add different networks so you can learn how to deploy to any other evm compatible network that you want to so you should be incredibly excited right you just deployed a smart contract to an actual Network now as we mentioned in blockchain Basics deploying to the ethereum main chain has gotten incredibly expensive and to help scale ethereum and these evm chains we're working with these rollups these layer twos to actually execute our transactions and these l2s are where we're going to deploy our contracts as well so now I'm going to teach you how to deploy to an L2 to deploy to ZK sync in particular and when you go to actually deploy smart contracts and actually work with different networks this is probably going to be the process that you're going to take as well nowadays most contracts are not deployed to ethereum mainnet because it's so expensive a lot of contracts are instead deployed to an L2 and as they gain traction maybe only then they're deployed to ethereum so we're going to take our simple storage contract and we're actually going to learn how to deploy it to the L2 ZK sync as well now if you followed along with the blockchain basics you've already learned how to add ZK sync to your metamask however if you have haven't done that we're going to go ahead through that as well now you have learned to work with different faucets right if you're working with the GitHub resources associated with this course the GitHub repo and we scroll down in here we can obviously come to the test net facets which might look a little bit something like this to work with ZK sync there's actually going to be two different ways we're going to work with getting test net funds the first way is using a DK sync faucet which will work the exact same way as doing a saoo faucet but the other way will be actually using the bridge now I will caution that sometimes these free faucets can be a little bit fickle so if any of these aren't working for you be sure to make an issue on this GitHub repo come to the GitHub discussions make a discussion and say hey I'm having a hard time deploying my smart contract to ZK sync and we'll make it easier for you then but if you want to go ahead and click the network faucets like here and walk through this you can absolutely do so but we're actually going to teach you how to do the bridge if you've already bridged funds over to ZK sync you can go ahead and fast forward to the part where we actually deployed the smart contract but I'm going to go ahead and show you the bridge again just in case you skipped over blockchain Basics so we're going to come to this portal. zy. ibridge website again you can find this in the GitHub repo associated with this course the GitHub resources if you're watching this on cyphon updraft it'll be that little button we taught you in the best practices section so we're going to go ahead and agree and we're going to go ahead and we're going to click connect wallet and this is going to be real similar to what we did in metamask we're going to hit connect wallet we're going to select metamask here and it's our metamask is going to pop up maybe we have to add in our password here we're going to go ahead next and connect and to get started we want to make sure we are on the sepolia test Network right and again if you don't have seoa eth you can come back here the gcp faucet as of recording is the best faucet you use any of these other faucets as well again if these aren't working let us know in the GitHub discussions or make an issue on the repo so you do need to have sapoia eth in your metamask and what we're going to do is we're actually going to bridge over we're going to transfer our sapoia East over to this L2 this layer 2 ZK sync so what we're going to do is we're going to click this ZK sync button at the top right and change to zky sync sapoia test net and now we should see Bridge from ethereum spolia testnet and the reason I want to show you how to do this is because this is actually going to be the exact same process that you're going to take when you're bridging to l2s in the future when you're bridging to these other chains on Main knit on real Bridges Etc so actually going through this will give you practice on how to actually do this now like I said if you're having a hard time getting the test net don't worry too much about getting this done correctly however I highly encourage you to get this done and highly encourage you to try to be successful here so that you can go boast about it on Twitter but so what we're going to do in my wallet I have 04 sapoia eth we don't really need a whole lot of ZK sync sapoia to deploy smart contracts so I'm just going to move over 0.1 ethereum seoa test right even 0.1 is probably plenty of ZK sync sapoia test to send over so go ahead and do that and remember we are working with a testnet wallet there's no real money associated with my wallet and we're going to do from ethereum seoa testnet to zky sync seoa testnet and we're going to go ahead and we're going to select continue you'll we want to read this little warning here says make sure your wallet supports ZK sync impo a test Network before adding funds to your account otherwise this can result in loss of funds see the supported see the list of supported Wallets on the ecosystem website since we're using metamask metamask is supported I understand proceed to the bridge and we're going to see we're going to bridge from your sapoia testnet account to your zync seoa test account we go ahead and select bridge now we're going to teach you later how to make sure that this transaction is actually sending your funds to the right places but for now since this is test net we don't really care we're just going to go ahead and hit confirm and we're going to send our funds over now your transaction is submitted we will have to wait a little bit for this transaction to complete you can see a little estimated time at the bottom here while we're waiting if we haven't done this already we want to go ahead and add that ZK sync sapoia test Network to our metamasks so what we can do is we can come up to we can go back to the resources page right The Foundry full course we can go ahead we can scroll down to this chain list section which will be right underneath the testnet faucets and if we click this link this will bring us to the chain list website where we can actually add Wallet information to our metamasks later on in the course we'll teach you how to do this manually and we'll teach you what all the parameters mean but for now we're just going to go ahead we'll click a button and life will be easier so in this little search networks section we're going to look up ZK sync sepolia we'll hit enter oh we'll also hit include test Nets and we'll see this zync aoia test net chain ID 300 this is the chain ID we're looking for and then we'll go ahead and select connect wallet our metam mass will pop up we'll choose the wallet we want to connect with and then we'll see this menam Mas pop up here it'll say something like add site allow this site to add a network it'll say network name Zing aoia testet this URL might be a little bit different but this one looks like it's it's fine chain ID currency symbol Etc we'll go ahead ignore These Warnings this is just a test net so it's fine and we'll go ahead and select approve once we hit approve we'll see this allow this site to switch the network suia to ZK sync suia test net we'll go ahead and select switch Network and now if we go to our metamask and we select it we'll see this little drop down we are now on the ZK sync sapoia test app like this cool now if we go back to our Bridge after some time will eventually see this transaction completed here and if we go to our metamask here we'll actually see the funds inside of our metamask 01 testet ZK sync sapoia eth fantastic so now that we have that we can actually go back to our remix and learn how to deploy this to ZK sync testnet okay before we go back to Patrick and learn how to deploy our smart contract on ZK sync apoia I just want to come in very quickly and explain to you a little bug that there is with the ZK sync plugin so if we have our setup exactly as you had it with Patrick where you have just your simple storage. Soul smart contract and then you went to the ZK sync plug-in and then you hit compile which is akin to in here with the solidity compiler compiling the simple storage if you hit compile right now you'll see that in the deploy tab which is the same as this deploy tab for regular deployments when we did it with sepolia you'll see that there are no smart contracts ready for deployment yet and it's saying that we haven't compiled a solidity contract yet even though it has a tick here and it says that we comp piled it and this is because of a small bug which basically means that you need to have your smart contracts inside of a contract's folder so if we just create a new folder we call it contracts and then we Chuck our contract inside the contracts folder and then we head back to the ZK sync plugin and then we hit compile simple storage and then if I zoom out a touch and then I click accept accept accept then I'll be able to go ahead and deploy my simple storage and compile correctly so if you just make sure that all of your smart contracts that you write are inside of a contracts folder you'll be good to go so back to Patrick to explain you through that step by step in a little bit more detail and I'm really excited for you to learn this because nowadays this is how all the pros do it so you're going to be learning right now the exact same type of layer 2 or rollup that the professionals deploy to we're going to deploy to this zero knowledge rollup called ZK sync and we're going to learn some of the differences on how to actually deploy to this test Network now in the future deploying to this test network will probably be the exact same process as what we just did right you'll come to deploy you'll go down you'll switch this to injected you'll hit deploy and boom and everything will work exactly the same but as of right now ZK sync is a little bit different so we actually have to use a plug-in to work with ZK sync so we'll come down to this plug-in manager and we'll look for ZK sync and we'll see this ZK sync module that will go ahead and activate now on the left side here you'll see a new ZK sync little tab on the left side that we're going to go ahead and click and we're going to see a setup pretty similar to what we were working with before with the deploy and run transactions tab except for this is going to be down in CK sync let me just zoom in a little bit we see a couple of different sections we see compile deploy interact and transactions and then at the bottom see a little environment that we can kind of pull up this environment section down here is the exact same as this environment section up here in the ethereum deploy and run this compile up here is the same as this compile for solidity this deploy here is going to be kind of the same as this deploy section here and then this interact and transactions will make sense very soon so what we're going to do now is we're going to first compile this simple storage. soulle and if you have more files in here for whatever reason just select the simple storage. soul and just go ahead and hit compile so this is actually going to compile now as of recording if we hit compile we'll hit compilation failed solidity compilation failed logs can be right in the terminal log and the reason for this is because because the compiler we're using is this ZK silk latest and as of recording this is 0.824 this is because this using ZK so latest only works with very specific specific versions of solidity so if we come to the GitHub repo associated with this course we can go ahead we can scroll down to or scroll up I guess to welcome to remix remix simple storage we can scroll all the way down to ZK sync L2 deploy we can see this ZK sync compiler Edition 0.824 we'll go ahead and copy that we'll paste that into our simple storage contract and then we'll go ahead and compile here in the future I imagine that this will just automatically work for the different versions of solidity but then you'll see a popup that looks something like this permission needed for file manager this is asking us if we want to give this simple storage. Soul permission to the ZK sync era compiler we're going to go ahead and hit remember this choice and we're going to go ahead and accept and we'll go back up we'll just hit compile again and even though it's still got the red squigglies this has indeed compiled correctly uh we to get rid of those red squiggly we just can come back to the solidity compiler and compile it with this new version of solidity cool so now that this has been compiled our deploy tab opens up and we can now see a deploy button for our simple storage contract so this is where we're going to deploy our contract and with remix we had this remix VM button up here but for ZK sync we're going to go down to the environment down here and we're going to switch from remote devet to local devet this is essentially the REM mix VM equivalent of the ZK sync environment and now we're going to go ahead and select deploy now as of recording this remote devet is broken hence this little red dot here so instead we're not going to test this we're going to go ahead and deploy this right to the test net it's the test net anyways so we're going to come down to environment and we're going to switch from remote devet to wallet and we're going to get this button that says connect wallet and we're going to go ahead and click it we'll select metamask and as normal our metamask will pop up let me zoom out a little bit I'm going to go ahead and connect my account and I'm going to make sure that I'm on the ZK sync sapoia test net if I'm just on spolia and not the ZK sync sapoia test net deploying this won't work so be sure you're on the ZK sync sapoia test net here ZK sync seoa test net then what we can do is we can go ahead and deploy and if we wanted to verify our contract Auto magically we could go ahead and select this verify contract as well we'll learn more about verification and what it means in the future for now I highly recommend you hit verifi contract so now we're actually going to deploy this to the ZK sync test Network you ready you should be so let's go ahead let's hit deploy and verify our menam mask will pop up asking us to give a signature we'll have a whole bunch of stuff in here we don't really care again this is a test net a test account so we'll go ahead and sign this and after a brief delay we'll see this huge output that looks something like this this huge huge H output and in this output let me pull this up a little bit and if it's green and you see verification successful that means this contract was both deployed and verified successfully so what we can do then is we can grab this contract address and we can go to the ZK sync sepolia Explorer this is going to be similar to that ether scan project that we were working with before and we can paste that new address that address that we copied from this button right here into the zync explor so remember though be sure you're on sea. explorer. zync and in here we can go to contract and we can see whoa we have our simple storage. soul codebase in here oh my goodness that's so exciting we've actually deployed a smart contract to the ZK sync test net ZK sync is a zero knowledge rollup and is a really cool really badass L2 so you should be incredibly proud because a lot of developers actually haven't gotten this far well done you should be very very exciting now similar to working with solidity and with ethereum on this deploy and run transactions tab on ZK sync we see these same buttons right we see ad person list of people my favorite number ret retrieve Etc when we select these blue buttons in here we'll see the output in the terminal over here and obviously if we were to go ahead and call one of these orange buttons for example storing 77 when we hit store of course our metamask will pop up if you want to go ahead and test some of these out go for it just remember test Nets can be a little bit fickle they can be a little bit slow but if we go ahead and confirm looks like it went through almost right away I can hit retrieve again and the 77 Returns on our side so with this you have now just deployed a smart contract to ZK sync you should be so excited not only did you bridge test net funds over to ZK sync but you actually deployed a smart contract as well now you should be incredibly proud of yourself and the web3 community is proud of you too so what I want you to do if you do have a Twitter if you don't that's fine but you should sign up for one I want to hear from you the ZK sync Community wants to hear from you the web3 community wants to hear from you and be excited with you what you can do in the get a repo associated with this course you can scroll down go ahead to the welcome to remix scroll all the way down even more and get to this tweet me button if you go ahead and click this you'll be opened up into a what's called a tweet intent now I'm not logged in here but if you are logged into Twitter you will it'll automatically populate a tweet for you that looks like this I just deployed a smart contract to the ZK sync test net thanks Patrick alphy and cyphon updraft we absolutely love to hear from you all so definitely be sure to send us a tweet get excited with us and be proud of yourself for deploying a smart contract to the ZK sync test head you are becoming a pro so quickly all right and with that you have deployed a smart contract to the l2s which are faster and much cheaper than the ethereum chain while still having a lot of the security and properties of ethereum you should be incredibly excited with yourself so let's go ahead and close out this section with a little recap now I've mentioned this a couple of times but whenever we compile this code it compiles it down to something called the evm or the ethereum virtual machine don't worry too much about exactly what this means but essentially the evm is a standard for how to compile and how to deploy smart contracts to a blockchain any blockchain that is evm compatible you should be able to deploy solidity code to some examples of evm compatible blockchains and layer 2s which again we're going to go over working with layer twos more in the future are going to be ethereum polygon arbitrum optimism ZK sync and more just note that it's important to double check the blockchain before you launch to it for example ZK sync is evm compatible but a couple of keywords don't actually work with ZK sync now let's do a quick recap of everything we learned in this lesson and and then after we do this be absolutely be certain to take a break maybe go get some ice cream go get that extra coffee or whatever you like to do the first thing you want to do in any smart contract or solidity code that you write be sure to write the version that you want to work with and above the version be sure to add the spdx license identifier if you're not sure what version to use for now just default to MIT then you have to create your contract object and name your contract a contract is similar to a class in other programming languages anything inside of the curly brackets for the contract is part of that contract there are many different types in solidity like U 256 string Boolean int Etc if we want to create our own type in solidity we can use what's called a struct you can create arrays or lists in solidity you can create mappings or dictionaries or hash tables in solidity where if you give it a key it'll spit out the variable associated with that specific key we can create functions in solidity that modify the state of the blockchain we can also create functions in solidity that don't modify the state of the blockchain view and pure functions don't modify the state of the blockchain we can also specify different data locations in our parameters of our functions but we can only do that for special types like strings structs and arrays call data and memory mean that that variable is only temporary and will only exist for the duration of the function call Storage variables are permanent and stay in the contract forever function parameters can't be storage variables since they're only going to exist for the duration of the function call whenever we hit compile in our smart contracts it actually compiles our solidity code down to evm compatible bite code or machine readable code we'll learn more about those specifications later and last but not least congratulations on your first contract here all right let's get started now with our lesson three remember everything is in the GitHub repository or the web3 dev. education we scroll down once again we can scroll to lesson three and again a lot of this is undone but it'll be done for the actual video scroll down to lesson 3 and we have lesson 3 remix storage Factory all the code that we're going to be working with is in this remix storage Factory f23 GitHub repository all of the GitHub repos associated with this course end with f23 which stands for Foundry 2023 I'm going to first do a brief walkr of what we're going to be coding for this lesson so for now just sit back and relax and enjoy for this lesson we're going to be working with three new contracts our original simpl storage. so which we're going to do a slate modification to a new five storage. soulle or add five storage. and a storage factory. Soul our storage factory. is actually going to be responsible for deploying new simple storage contracts yes other contracts can deploy contracts not only is this going to be able to deploy other contracts but it's going to be able to interact with other contracts as well what we could do is we could deploy this to a remix VM deploy we'll compile all of our code go to a remix VM scroll down to select the contract we're going to select storage Factory not simple storage deploy this see that contract that we just deployed down at the bottom and you'll see our top function is this function called create simple storage contract where if we pull up our terminal and we click create simple storage contract you'll see we get a new transaction at the bottom and this transaction is the transaction that we deployed a simple storage contract from our storage Factory contract now we can actually go ahead and interact with our simple storage contract remember in simple storage we have a function called store which takes a favorite number we can actually call this store function on our simple storage contract from our storage Factory contract using this F store function so we'll add the index of our simple storage contract which since we only deployed one so far it'll be at inex zero and we'll say our new favorite number is 1 23 and we'll hit F store and we'll click SF store at 0123 SF store stands for storage Factory Store so we're going to store the number one two three on index0 and again don't worry about this making too much sense yet we're going to explain this all in a minute now if we hit sfg of zero we'll go ahead and get back 1 2 3 we're saying let's get the value of the simple storage contract stored at index 0 and we do indeed get 1 two 3 additionally we have this list of simple storage contracts array or list and it's only size one right now but if we type in zero here we get back the address of that original simple storage contract that we deployed additionally in this lesson we're going to learn about a ton of incredibly important solidity features such as Imports and inheritance without further Ado let's get froggy and one more time of course remember all the code is available in The Foundry full course f23 of the chain Excel org or on the web 3d. education site once it's up so here we are back in remix with our simpl storage. if you skipped over the last section and want to get that contract just come to the full repository go down to lesson two go over to the code in the GitHub repo associated with this course the remix simple storage f23 and just copy and paste everything into remix yourself to make sure you've done it correctly be sure to hit compile we have our simple storage contract that we created in our last lesson which is great it allows us to store our favorite number and it allows us to store a list of people who have different favorite numbers also a mapping and some other different functionality with interacting with people's favorite number but we want to go even further with this we want another contract to actually deploy this simple storage contract for us and interact with it contracts interacting with each other seamlessly and permissionless is a feature of smart contracts and blockchain development that's absolutely essential and crucial and one of the reasons why blockchain development is so powerful the ability for contracts to interact with each other seamlessly is something known as composability smart contracts are composable because they can easily interact with each other this becomes even more important when we get to topics such as defi where we can have incredibly complicated Financial products and instruments interact with each other seamlessly because they're all using the same smart contract interface so we're going to keep our simpl storage. soole the exact same way it was from the last lesson and we'll update it in a little bit but let's go ahead and create a new contract called storage factory. Soul so let's go ahead and get this contract set up now we're going to be doing this a lot and when we work with AI pair programmer now we're going to be doing this a lot and when we work with AI pair programming this is going to be a lot easier for us to do but for now repetition is is the mother skill so let's keep going first thing we need to do is what if you want to pause the video and add the first two things you should put at the top of every sity smart contract right now go ahead but for those of you who didn't pause let's go ahead and do spdx license identifier MIT and then let's do pragma solidity 0.818 or 19 or whatever you want to do you know what let's do 19 what do we do in simple storage we did 18 let's do 18 and then we'll do contract so this this will be the third thing actually contract storage Factory like this and I hit command s but you can also go in compile like so and I'm also just going to add the carrot here meaning we're going to use 0.818 but any version greater than that also works as well awesome now this storage Factory contract is going to be deploying a simple storage contract so let's create a function that can actually deploy or create a simple storage contract so we'll say function create simple storage contract and we'll make this a public function and we're going to have this create simple storage contract function deploy a contract and then save it to a state variable or a storage variable but the question is okay well how does the storage Factory know what the simple storage contract even looks like how does this contract know about this contract how does this contract know that this contract even exists the first way that we could do this is we can actually go to our simple storage. Soul contract and start highlighting from the contract word and scroll all the way down to the end of the contract copy it command C or rightclick copy go back over to storage Factory and Below pragma solidity but above contract storage Factory pasted in here if we go ahead and command s or compile this you'll see that this actually goes ahead and compiles successfully huh so this is to show you that yes right now in our storage factory. Soul we have contract simple storage which ends here and we also have contract storage Factory down here so this function is going to deploy a simple storage contract but we're going to save it to a storage or state variable and we're going to do it the exact same way we've been saving any variable first thing remember like remember how we did U 256 public favorite number this was in the format type visibility name we're going to do the exact same thing the type of a simple storage contract is going to be simple storage and the reason that solidity is going to be able to identify this keyword is because it's the same name as contract in the same sense that our struct keyword allows us to create a person type the contract keyword allows you to create a new type as well a type of simple storage contract so simple storage for now we'll just give it a visibility of public and we'll give it a variable name simple storage now this is going to be a syntax you're going to see a lot and it might be a little bit confusing the first couple times you read it the difference between these two is very subtle the difference between simple storage on the left and simple storage on the right is very subtle it's simply that the S is lowercased over here and the S is capitalized over here solidity is case sensitive so these are actually different word simple storage here is referring to the contract simple storage here is referring to the variable you'll often see people use the syntax when working with contracts where they name the variable the exact same as the contract itself if this is confusing to you you can do my simple storage instead of simple storage with lowercase so either one of these works it's good to get used to this as such but if that's confusing you can do my simple storage now in our create simple storage contract function we're going to say simple storage equals new simple storage like this this new keyword is how solidity knows to deploy a contract so with just this code alone if we go to the compile tab we compile this this doesn't de compile we can go to deploy we need to make sure we're on the storage factory. Soul on the right hand side we'll scroll down to the contract we can actually deploy our storage Factory like so hitting the deploy button and remember you can see the transaction in the terminal here and we can scroll down to the contract right now there's two buttons we have our blue view function simple storage because again the public keyword automatically gives the variable name a getter function or a view function and of course we have our crate simple storage contract orange button because it is actually a transaction right now simple storage returns nothing the zero the default value for an address which is the zero address and if we call create simple storage contract we get see a green check mark meaning that transaction went through now if we call the simple storage blue view function we see we indeed get an address here we have deployed our simple storage contract from another contract oh my goodness so congratulations now you know how a contract can deploy another contract awesome job but the thing is like I was saying if we just add all of our contracts into the same file and we have these massive contracts all interweave between each other it can get very cluttered and very confusing so is there a better way we can actually arrange and organize our code other than this and this is actually even a little bit redundant since we already have our simple storage. Soul if I changed something in here then I would also have to go and change it in here and that's too much work for me as an engineer I will work incredibly hard to be incredibly lazy so instead of doing this we can use what's called an import if we go ahead and delete our contract simple storage in our storage Factory here so that now we just have the storage Factory contract we can go ahead and use the import keyword to import simple storage. soulle so we can do import do SLS simpl storage. and a little semicolon here this import /s simpl storage. is the exact same as if we had this giant simple storage in here so this import simple storage. is a shorthand version of copy pasting that simple storage. soulle into this contract and now we're able to have simple storage. in its own file and storage Factory just import it from simple storage making our lives much easier it takes our path package or GitHub which we'll explain in a little bit and and copy paste whatever in that file at the top of our file literally solidity for us is copy pasting everything in here and sticking it up here so we can go ahead run this again let's compile delete our old contract onun remix VM let's be sure we're on storage Factory we'll go to storage Factory we'll deploy it scroll down click here simple storage starts up as nothing create simple storage oh my goodness look we deployed a contract huzzah great work so now that we're starting to work with different files there's a number of things we want to consider first one is actually the solidity version so right now we're using 0.8.1 with no carrot and in storage Factor we're using 0.8.1 with a carat if I were to for example move the solidity version of this down to 0.8.6 and go to compile this with a different version remix is actually going to remix is actually going to automatically bump this up to 0.8.9 or actually remix is actually going to automatically bump this up to 0.818 if on the simple storage because 0.818 is the version that works for simple storage and it still is compatible with storage Factory however if I were to take storage Factory and move it to 0.7.0 and try to compile it's going to try to compile this with 0.7.5 and our simple storage with 0.7.0 and it's not going to be able to do it for both and so we're going to get a compilation error so when working with multiple files it's important to keep the version of solidity in mind because you want to make sure that all of your contracts can actually compile together so this is great and all but right from the get-go I want to teach you the more advanced import that you should always use so this is good but we actually never want to default to this we want to default to something called named Imports let's say our simple storage. Soul contract had a ton of other contracts like contract simple storage 2 simple storage three simple storage 4 and these were all massive massive contracts as we have this right now import simple storage. Soul would import everything from here simple storage simple storage two simple storage three simple storage 4 and if these files were incredibly big when we deploy our storage Factory it would have to calculate all this extra computation making the deployment of our storage Factory more expensive if that's confusing to you don't worry about it right now additionally in the future these can import from weird places that aren't compatible with storage Factory again that's not going to make sense quite yet and that's okay but in any case there's a way for us to not import this whole file but only a very specific contract or a specific section of our simple storage. soole so instead what we can do is in our import statement we can specify the exact contract that we want to import from this file so in our simple storage. let's say we do have these other contracts in here we could say we only want to import simple storage not simple storage 2 not not simple storage 3 not simple storage 4 by saying import these little brackets here simple storage from simple storage. and this goes ahead and compiles correctly we could also import multiple contracts from our simple storage for example we could do import simple storage simple storage 2 from simple storage. this way we only import the exact specific contracts that we want from these other files and I promise you in the future always referring to named Imports instead of this type of imports will save you a lot of headache in the future so always default to this never default to this just by learning this you are already better than 80% of the current solidity developers so congratulations but all right fantastic so we've learned about Imports we're able to import our simple storage from simpl storage. soulle We're importing it in the more advanced way congratulations now already here you might actually start running into some questions right and we're going to get more and more advanced with this course and you're going to have questions which is a good thing if you don't understand stuff that means you're thinking critically and you're approaching the subject matter the right way so this is where we're going to jump into again doing a little bit of an AI chat example so for example on this line let's say you're a little bit confused and you go what's the difference between simple storage here and simple storage here I don't understand so let's learn how to work with chat chbt or any AI buddy to ask them to help clarify so we're going to go ahead I'm going to hit command a or you can just highlight everything command C to copy or rightclick copy we'll go over to chat gbt and in here we're going to ask the question hi I'm having a hard time and let's zoom in understanding the difference between the simple storages on this line and here's where we want to be very specific when we're talking with AIS so I'm going to hit shift enter so that it doesn't actually send the question to chat TBT but I'm going to put three back ticks shift enter again and actually I said we're going to copy the whole thing but let's just copy this this single line and paste it in here shift enter again three back ticks again adding this delimiter tells chat gbt that this is a block of code and it makes it easier for chat gbt to be able to understand that this is a block of code and I'll hit shift enter twice and if you have a lot of code you're not going to be able to copy your whole contract because a lot of these AIS can only understand so much in a question but this is small enough that we can actually just go ahead and copy the whole thing bring it back over to chat gbt and say here is my full code and then we'll do again shift enter three back TI shift enter paste shift enter three back Tis so now we have a little a AI prompt here that we can ask in chbt and and I don't have this in here yet but in the GitHub repo associated with this lesson I will add this AI prompt in here so let's go to the bottom and I was saying you need to use shift enter but I guess you could just use enter that's fine let's go ahead and click the send button and it'll send it the question so now it'll start outputting here and let's see what it says and this is where we can already start to see the power of these AI buddies as learning buddies we see in the given code simple storage is a variable of type simple storage which is a contract defined in simple storage. Soul tells us what the line is doing it clarifies the differences a little bit more and a lot of this beginner basic stuff AIS are really good at once we get more and more advanced AIS are going to start breaking apart but at least for the beginning of this course AIS are going to be incredibly helpful and Incredibly good at explaining a lot of these what we could do if we wanted to is we could also go ahead and copy this prompt we could go over to something like bard paste it in here and ask bar the same thing and here's already a good example of where an AI can get things wrong if we scroll down it's telling me you can use simple storage variable to interact with the new simple storage contract for example you could call the set function to set the value on stored data variable or you could call the get function to get the value of the stored date variable uh there is no stored data variable so I don't know where it's getting that from so just remember keep in mind that AIS can get things wrong and that when they do there are other forums that to use as well like I said we're going to be learning about them as we go on like stack exchange ethereum piranha or like I said of course the discussions Forum of this course so if Bard or chbt or whatever AI buy you're working with gives you something confusing be sure to go to the GitHub discussions or ask on one of these forms now as you can see though right now every single time we call create simple storage contract we're going to deploy a new simple storage contract but we're going to override it in this simple storage right so if we go ahead and deploy this right now scroll down here simple storage at the zero address create okay now it's at a new address create again okay now it's at a new address we're not keeping track of all the different addresses that this simple storage contract is being deployed to so let's actually create a running list of all the different simple storage contracts that we're deploying so instead of having this variable be just a single simple storage contract let's have it be an array or list of simple storage contracts and we'll change the name to list of simple storage contracts so now when we deploy it instead of saving it like this we're going to do what we did before in our last section we'll say simple storage new simple storage contract equals new simple storage and then we'll push it onto our Dynamic array so we'll say list of simple storage contracts push new simple storage contract so let's go ahead and compile this okay looks good let's go ahead and deploy this we'll delete our old one we're on the remix VM great storage Factory and look at this you can even see make sure we're on storage Factory okay great we'll go ahead and deploy that awesome we get list of simple storage contracts which now has this U 256 input which allows us to choose the index of the variable we'll go ahead and create simple storage now we go check the zerith index have an address if we check the first index nothing happens if we call create again which sorry if I have the terminal up I'll call create again again now there is one at the first index and since I called it twice there's also one at the second there's nothing at the third I'll hit create again there's no one at the fourth oh at the third excuse me awesome so now we actually have a running list of all of our simple storage contracts now let's learn how to actually interact with other contracts from a contract for now we can think of our storage Factory as a sort of manager for all these other contracts so let's learn how our storage Factory contract can actually call the store function of the simple storage that it deploys so let's create a function called SF store which is going to stand for storage Factory Store and it's going to take two variables a u 256 undor simple storage index and a un 256 uncore new simple storage number I'll make this public like this now in order to interact with a contract you're always going to need two things and we're going to refer to this a lot you're going to need an address and you're going to need the ABI now this is technically a lie you really just need the function selector but we're going to learn that way way later in the course for now just think okay I always need the address and I always need the ABI the ABI stands for application binary interface the ABI will tell our code exactly how it can interact with another contract we'll go deeper into the ABI later on in this course but for now if you go to the compile tab you H compile and you scroll down there's this little button at the bottom that says copy abi2 clipboard or you can also go to compilation details you can see a ton of information about the compilation details such as the bite code with the op codes some metadata the name but also the ABI which tells us the ways we can interact with this contract if we hit the drop down for the zero we see there's an input create simple storage contract which is one of our functions and you see state mutability which we'll talk about later but if we had another drop down we see list of simple storage contracts and the other drop down we'll see SF store these as you know are the buttons that we can press when we deploy this contract right so if I redeploy this we see those exact three buttons these are the three buttons that were inside of that ABI this is how remix knows to put three buttons here because it looks at the ABI and sees that there's three buttons so in our code here our compiler knows what the Abi is so in our code here the compiler automatically knows what the ABI is because the compiler is the one that generates the ABI and we know where the address is because we have a list of all of our addresses that we're keeping track of up here so the reason we have the ABI is because we're importing our simple storage contract and actually let's delete this simple storage 2 we don't really need the simple storage 2 so when we compile simple storage we automatically get the ABI for solidity in the future we'll learn other ways to get the API so down here let's get a simple storage contract to interact with from our list and to do that we'll say simple storage my simple storage equals list of simple storage contracts at index simple storage index like this since this is an array of simple storage contracts we can just automatically get the contract itself like this however let's say that instead of this being an array of simple storage contracts this was an array an array of addresses called list of simple storage addresses like this you don't have to code along with me for this section just go ahead and follow along and watch if we had a list of addresses and this would be to be a little bit different but we had a list of addresses instead we could say simple storage my simple storage equals list of simple storage addresses at the index and then do something called typ casting and we'd wrap this in parentheses like so let me zoom out a a little bit so this is something we'll learn about a little bit later so basically what we're doing is this list of simple storage addresses simple storage Index this line returns an address and we're wrapping that address in simple storage like so if this is a little confusing for you now don't worry too much about it we will learn about it more later now that we have our simple storage contract we can actually call the store function directly on this contract so now we can say my simple storage. store and we'll add the new simple storage number and this is great if we were to deploy this contract right now though and call this SF store function though we wouldn't be able to read the new variable that we just updated our simple storage contract with so let's create a function that allows us to read from our simple storage contracts as well so we'll create a function called SF getet which will take a un 256 uncore simple storage index is an input parameter we'll make this a public view function that will return a uint 256 uint 256 and we'll say simple storage my simple storage equals and we'll use this exact same syntax that we used above to get the simple storage index equals list of simple storage contracts at the simple storage index and now we're going to do return my simple storage and again if you see these autocompletes that come up you can just hit tab but. retrieve so perfect now let's go ahead and compile we'll go ahead and delete the old deploy we'll make sure we're on storagea factory. we'll hit deploy and we see storage Factory down here now let's go ahead run through that exact same exercise so we'll pull up the terminal just to see our transactions go through we'll hit create simple storage let's see that it's actually there at the zeroth index okay cool we see an address there so now let's store a new variable at index0 so at this address so we'll say at index zero we'll store the number 1 2 3 and actually before I hit this button if we go down here we hit zero we get nothing back right but now if I hit SF store with index zero favorite number one two three looks like the transaction did go through now if I hit SF get we go ahead and get 1 two three so our storage Factory contract was able to create its own simple storage contract store a variable in that contract from the storage Factory and we were able to read back the number 1 2 3 all from within our storage Factory contract feel free to pause right now and play around with adding different values creating different simple storage contracts so that you really understand what's going on you can also feel free to hit the little dropdowns and read more information about these transactions just as a recap in our storage Factory contract we have a function called create simple storage contract which creates new simple storage contracts from the storage Factory contract the reason it's able to do this is because we're importing from from our simple storage. file using something called named Imports we're only importing simple storage we're not importing anything in these other contracts then we use SF store to store a new number on one of those simple storage contracts using the index in our array it can do this because we have the address and the ABI the list of simple storage contracts automatically compact with the address and the ABI and then finally we can read back those simple storage values that we stored now we can make this sfg function even more condensed since this list of simple storage contracts simple storage index returns an object of type simple storage we can actually delete this whole line copy this paste it here and delete this line and this will work exactly the same as what we had before go ahead and save or compile you'll go ahead and get that green check mark there this do retrieve is saying we're going to call the retrieve function on whatever this is and this whatever this is is of type simple storage contract we can actually do the same thing up here by deleting this part copying this line except for the semicolon and pasting it over the my simple storage and hitting save or compile awesome great job so far awesome now let's say you really like this simple storage contract you love all the functionality except for one thing you wish that the store function didn't just store the favorite number you wished it added five so for some reason you want a contract that does everything this contract does but just adds five whenever you call store for some reason you want everyone's favorite number to be five larger than what they think it is well one thing we could do is we could just copy paste this into a new file but again that's kind of too much work for me I'm a lazy engineer but let's go ahead and see how we can approach this problem so let's create a new file and we'll call it add five storage. soul and same thing since this is a new contract we're going to follow the exact same tips we're going to do spdx license identifier MIT we're going to do pragma solidity 0.818 let's even do the little carrot here and we'll do contract add five storage like so we compile great looking good oh I'm getting a warning spdx license spelled license wrong so let's spell that right okay cool looks good so like I said the first thing that we could do is we could copy paste everything in here and then just change the pieces that we don't like in our ad storage this is a little bit redundant a little bit too much work and we are Engineers we want to work as hard as possible to be as lazy as possible so how can we do that well this is where we can do something called inheritance we can have our ad five storage contract be something called a child contract of our simple storage contract and we can have our ad five storage inherit all of the functionality all of the functionality of our simple storage contract so first of course in order for our ad five storage to know about our simple storage contract we're going to go ahead and have to import it so we're going to do import and we're going to do once again the named Imports because we're Advanced solidity Engineers so we're going to say import simple storage just the simple storage contract froms simpol storage. Soul now if this slash is confusing to you don't worry we'll learn about directory structures later on in the course and then we'll say our contract add five storage is simple storage now our ad five storage is going to do what's called inherit everything from simple storage and our ad five storage is going to have all the same functionality as simple storage we can actually see this directly if we go to compile let's go ahead and delete our previously deployed contracts we're on the remix VM let's make sure we're we've selected ad five storage adiv storage. let's go ahead and deploy it and if we scroll down we can actually see oh my goodness it's got all the same buttons as simple storage even though the contract itself doesn't have anything defined that's because we inherited all the buttons we inherited all the functionality of simple storage into ad five storage if you want a contract to inherit the functionality of another contract you just import it in and then say your contract is that other contract now we can keep going though and add our own custom functionality into ad five storage that's not in simple storage so for example we could say function say hello it's going to be a public and it returns a string memory and again you need the memory keyword because strings are special in solidity and we can just say return hello like so this will be a public pure it's not a view because we're not reading from storage and again if that dissertion is a little confusing to you don't worry too much about it now but if we go to deploy it let's delete our old one we'll deploy this one we see we have all the functionality of simple storage plus this say hello function great but let's delete that for now let's say instead of wanting to add additional customization you actually love every function in here except for one remember the reason we wanted this adiv storage. soulle is because we actually want to change the store function to have it add an additional five to people's favorite numbers maybe you're mischievous and you want people's favorite numbers to be five greater than they are well to add this ad five customization to that store function we can do something called overrides to do overrides there are two keywords that we need to be aware of those are virtual and override if I were to try to create a store function for our ad five storage right now what do you think will happen well let's try it out so let's say function store un 256 _ new number public if we try to compile this right now we'll actually get an error even if there's nothing in this store function we roll over we say from solidity type error overriding function is missing override specifier and remember if you get lost or confused an error like this is something perfect for you to ask chat or maybe even find we could say I am I'm trying to compile my solidity code but I'm getting this error we can copy this whole error here paste it in here and then in additional context we'll just add the code like this we'll hit search see what it gives us we'll say and it looks like find was able to find the answer the error message indicates the function store in the ad five storage contract is missing the override specifier which is required because it overrides a virtual function from the simple storage contract thanks I'll explain what find is giving us in just a minute it's right we need to tell solidity that it needs to override the store function in simple storage we want to be very explicit and say hey do this store function and not what's in simple storage doole so let's go ahead and add the keyword override now though if we just add that keyword we go ahead and try to compile we still get an error trying to override a non- virtual function did you forget to add virtual in order for a function to be override a bowl you need to add this virtual keyword in the base class or the parent class so in simple storage we need to add virtual to store this virtual keyword means that this function is overridable any function that doesn't have this keyword you can't override now our store function is overridable and we've specified that we are indeed going to override the store function now if we go ahead and compile we'll see everything compiles successfully all right great so now let's just add the functionality to store remember since ad five storage inherits everything from simple storage this means that we even have access to my favorite number so what we can do is we can say my favorite number equals underscore new number plus 5 we'll compile this and now let's try it out we're on remix VM we want to make sure we're with add five storage we'll delete the other ones we'll deploy scroll down hit the drop down retrieve currently return zero now if we store to pull up the terminal to make sure we're actually sending transactions we'll hit store and now if we hit retrieve we see we indeed get seven back because 2 + 5 is 7 we add five we hit store retrieve now returns 10 So This Is How We Do inheritance and override functions and that's it for this section you've learned a ton of incredibly powerful features and solidity so let's do a quick recap of what we learned this section we learned that with the new keyword we can actually deploy contracts from other contracts we learned that we can actually import other contracts which is essentially the same as copy pasting the code into this file we also learned this thing called named Imports which is going to make you look even better than most of the sidity devs out there we learned that we can interact with other contracts so long as we have the address and the ABI the simple storage type automatically comes with the address and the API so we can just access it like this we didn't learn too much about the ABI but we'll learn more about it later we learned that if we want to make a child contract and inherit the functionality of some other contract we can just just import that contract and then use the is keyword in the contract declaration to override a function we need the override keyword and we need the base class or the parent class to have the virtual keyword on the function you want to override and that is the end of this lesson so be sure to give yourself a huge pat on the back take a break breaks are good for your brain go for a walk grab a coffee get some ice cream go tell your friends go post on Twitter you're getting more and more advanced with solidity very quickly so be sure to celebrate the little win to keep being excited and keep that Curiosity congratulations youve completed this lesson all right everybody welcome back we are now headed into Lesson Four this is going to be our remix fundme and once again you can find all the code associated with this lesson in the GitHub repository associated with this course and also web3 dev. education and let's do a quick walkthrough of these contracts before we actually start coding anything to see what we're going to be doing we're going to be creating one contract funbe doou we're also going to have another file called price converter dossou and we'll talk about that in a little bit the fundme contract is going to be our main contract this is going to be an example of a crowdsourcing application or a way to raise money you can think of it as a web 3 decentralized Kickstarter will allow users to send ethereum polygon Avalanche Etc or really any native blockchain cryptocurrency into this contract and allow the owner of the contract to actually withdraw all the funds for them to go spend on their new project and we are going to actually deploy this contract to a test net and remember use the test net transaction sparingly but if we deploy this to a test we scroll down we actually see that we have a couple of buttons and a new color button we'll actually get a new red button for our fund function a red button indicates that a function is payable and we can send native ethereum or polygon or Avalanche or whatever the native cryptocurrency of the blockchain we're working with is We additionally will indicate a minimum USD amount to send to the contract so funders have to spend at least $5 worth of ethereum in order to call this fund contract so if we go up to the value section we can actually send some value with this transaction and again don't worry about this making sense yet but if I want to send 0.01 ether I'll grab that amount in way paste it into the value section here I'll scroll down I'll hit the fund button minimass will pop up I'll confirm we can see at the top the current balance of the contract is zero and we'll wait a little bit for the transaction to finish going through and after the transaction finishes going through we can see in ether scan we have a balance of 0.01 eth and we can also see that after remix after a slight delay then we can allow the owner of the contract to withdraw those funds right now the owner of the contract is also us and after this transaction goes through we'll see that balance removed from the contract and it'll go back into our wallet and as you just saw there if we held our metamask up for long enough eventually it would pop back into our metamask are you excited well you should be because after you complete this section you'll actually know most of the fundamentals of working with solidity we're going to be going over a lot of advanced features in this section and I'll let you know the specific parts that you don't need to fully understand quite yet there's going to be a couple parts where if it doesn't totally make sense just keep going with the course and as we get later into the course you'll figure out why they make sense but it might be a good idea to write down the questions that you have to ask either an AI on the GitHub discussions or web3 education. make sure of course to use the discussions Tab In The Foundry full course f23 to ask questions and interact with other developers who are taking the same course or go to web3 d.ed to learn more all right let's get froggy so the first thing that we want to do is let's once again delete everything in our remix so we can start from scratch so I have the contracts that we're actually going to be building in here you might have the simple storage the ad five extra the storage Factory Etc let's go ahead right click and just delete everything we're going to start completely from blank here so let's go ahead and delete everything in here all right great so let's go ahead and start creating our contract we're going to call it fun me. Soul one thing that's really good when you actually start building any code at all is to First write down down what you want it to do so what do we want ours to do we want to get funds from users into this contract withdraw funds to the owner of the contract or whoever has created this fundme contract and then we also want to set a minimum funding value in USD we don't want people to be able to donate just a penny so let's go ahead and set this up spdx license identifier identifier MIT do pragma solidity carrot 0.818 contract fun to me let's go ahead and delete these comments so before we embark on writing all of our functionality out let's just write down the functions that we want to buildt so we're probably going to want a function fund which is going to be the function they call to send money to our contract we're going to want a function withdraw which is going to be the function that the owner of the contract is going to use to withdraw the money that the funders send us and those are going to be the two main functions that our contract is going to need we're going to be implementing more functions than just this but these are going to be the main functions to interact with our protocol or interact with our fundme contract let's comment out withdraw for now and just start focusing on fund we want anyone to be able to call this fund function so we're going to make this public and we want this function to do what well we want it to allow users to send money and we want to have a minimum dollar amount that they have to send so the first question we need to answer is how do we send eth to this contract how do we have it when a user calls the fund function eth automatically gets sent into our contract whenever we send a transaction on the blockchain there's actually always a value field that gets populated and most of the time it gets sent with zero even before when we called the send function between our accounts when we added an amount in our metamask this amount value populated the value field of our transaction this value field is the amount of native blockchain cryptocurrency that gets sent with every transaction the first thing that we need to do to allow a function in solidity to accept this native blockchain currency in the first place is to make the function payable it's this payable keyword that makes the function look red in the remix UI just like how wallets can hold funds contracts can actually hold funds as well so whenever you deploy a contract similar to a wallet address it actually acts almost the same as a wallet address you can send money to it you can interact with it Etc and like we did in the demo you'll see this contract actually gain a balance just like a wallet you can access this value amount of a transaction using one of the globals in solidity called message. Val solidity has a number of these globally available keywords and functions and you can find these in the solidity documentation one of them is message. Val which is the number of way sent with the message if we wanted users to be required to spend at least one whole ether with this fund function we could use something called require to do so in order to do that we would add this line require message. value is greater than 1 E8 and there's a couple of things to unpack here 1 E18 is equal to 1 ether which is equal to 1 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 or put another way it's equal to 1 * 10 raised to the 18th in solidity a double asri or double multiply sign is how you do a power or an exponent this value here is the value in way of one etherum in your smart contracts and at the lowest level this is how they process numbers in this giant wave format so if we wanted people to be forced to send at least one whole eth with this fun function we would just say require message. value is greater than 1 E18 you can use something like econ converter.com see to convert one ether between ether way and gay is actually another value in between ether and wayy and we saw gay actually when we saw gas costs normally gas costs are shown in forms of gay this required keyword is a checker it's basically saying hey is message. value greater than 1 E18 if not then revert this transaction and if we want we could add a little revert message we could say like didn't send enough e we can actually deploy this we can actually compile and deploy this on a remix VM deoy scroll down and if we hit fund and if we pull up our terminal we hit fund we actually see we get this little X here meaning our transaction didn't go through and if we hit the drop down oh again same thing same thing we know that this error is because we have this require statement in here and our transaction is reverting or not going through so we know that with this transaction we need to send at least one eth or or 1 E18 way worth of eth in the value section of our transaction so if we scroll up we can actually just change the unit to Ether put one in here scroll down and now if we hit fund oh it doesn't go through because we have strictly greater than so excuse me Let's do let's do two now we scroll down we'll hit fund and we see we get a green check mark and we see the fundme balance actually has improved to two if we update the value to two again and we scroll down we had fund again we see our transaction went through and we have four we try do less like let's change this to way and we'll do you know th000 way scroll down we hit fund up it fails because 100 way is less than 1 E18 way right because 18 E18 way is this much way so obviously th000 or however much I put in is much less so this require says if this first section is false then go ahead and revert with whatever this second section is reverts can be a little bit confusing and a little bit tricky so what is a revert a revert undoes any actions that have been done previously and sends the remaining gas associated with that transaction back so what does that actually mean well let's say for example in our fundme contract we have a u 256 public my value and let's have my value initialized to one now in our fun function let's say my value equals my Value Plus 2 so every time this fun function successfully goes through we add two to my value however if we get to a revert statement even though we added two to my value previously since our contract reverts this would actually revert this action or reset it back to its initial state so if this transaction reverts my value would go back to one or whatever it was previously if we compile fundme we delete our previous deploys we're on the remix VM we'll deploy fundme we'll scroll down we have my value which defaults to one if we call fund right now without any value we pull up our terminal we can see the transaction failed my value is still one even though this line technically executed this line executed but then this line hit and it reverted what was done here so if we scroll back up though we go to Ether we'll put one in for now scroll back down now we'll hit fund oh needs to be more than once excuse me we'll add two here scroll back down now we'll hit fund that transaction did go through which means my value will now be equal to three and again if I set value to zero we call fund it reverts so my value is still three so then the question might be oh well did we spend gas to do this if my transaction didn't even go through well unfortunately the answer here is yes if you send a failed transaction you will spend gas because computers executed this line and then they executed this line and just failed so users can actually specify how much gas they send with every function let's say there was a ton of computation after this requir line we would need to send a a ton of gas to operate and run our fund function however once it gets to this require line and it reverts however much gas that we sent to execute the rest of the computation would just get refunded to whoever initiated the transaction like I said sometimes the refunds and some of that can be a little bit confusing so again for now just know that if a transaction reverts it undoes anything it does previously and you can consider the transaction failed however if you send a reverted transaction you will still spend gas but okay let's delete this value for now delete it from the global scope and delete some of these like that in fact every single transaction that we send will have these fields it'll have a nuns or the transaction count the account the gas price the gas limit that we've seen on ether scan a two aka the address that the transaction is sent to a value which is going to be this amount that we're talking about we'll also have data which is going to be what we send if we make a function call or deploy a contract and then it'll have this vrs components we're not really going to go over these VR ands because this is that cryptographic magic that's happening when a transaction is signed but just know that that's in there for sending value we can populate some of these fields the gas limit for example is populated to 21,000 data is going to be empty and then that two is going to be the address of the transaction we want to send to for a function call we can also still populate the way that we want to send so we can can call a function and send a value at the same time in remix it has a little drop down here way guay finny and ether we're going to ignore finny for now but of course we have our wayy guay and ether again where one ether is worth this much gay and this much way so right now our contract is pretty minimal right we're requiring the message. value is greater than one whole ether but we want to actually require that it's less than some value like let's say we want to have users spend a minimum of $5 as opposed to one whole ethereum so let's first specify that $5 we can do that at the top of our contract we'll say U 256 minimum USD equals 5 and we'll make this public instead of internal we'll update this minimum USD in the future to make this more gas efficient so what we want to do is we want to require that our fund function requires that the message. value is greater than let's say greater than or equal to minimum USD however minimum USD is in terms of USD or dollars and message. value is in terms of eth or way in terms of ethereum so how do we convert the amount of ethereum to its price in dollar this is where oracles and chain link comes into play the dollar price of an asset like ethereum is something that we've assigned to ethereum outside of the blockchain in the real world so in order to get this abstract concept of the price of the Native cryptocurrency of the blockchain working with so we need to use a decentralized Oracle Network or something called an oracle to get this price so before we keep going let's learn a little bit more about decentralized oracles chain link and how they work so that we can understand how to get the price of ethereum into our smart contracts as we've talked about blockchains are deterministic systems which means that they themselves can't actually interact with real world data and events they don't know what the value of an ethereum is they don't know what random numbers are they don't know if it's sunny outside they don't know the temperature they don't know who's President they don't know any of this information these blockchains also can't do any external computation maybe you have some amazing artificial intelligence model that you want to integrate with a smart contract smart contracts by themselves can't do anything with that as we've mentioned this is because blockchains are deterministic by Design This is so that all the nodes can reach consensus if you start adding variable data or random data or values that return from an API call different nodes could get different results and they would never be able to reach a consensus this is known as the smart contract connectivity problem or the Oracle problem and this is bad news because we want our smart contracts to be able to replace traditional agreements and traditional agreements need data and they need to interact with the real world this is where chain link and blockchain oracles come into place a blockchain Oracle is going to be any device that interacts with the offchain world to provide external data or computation to Smart contracts however the whole story doesn't even end there if we use a centralized Oracle we are reint introducing a point of failure we've done all this work to make our logic layer decentralized but if we get our data through a centralized node or through a centralized API or we decide we want to make the API call ourselves we are reintroducing these trust assumptions that we've worked so hard to get rid of we're essentially ruining the entire purpose of building a smart contract so we don't want to get our data or do external computation through centralized nodes those are bad news chain link is the solution here chain link is a decentralized Oracle Network for bringing data and external computation into our smart contracts as we mentioned before this gives rise to these hybrid smart contracts which combine onchain and offchain to make incredibly featur powerful applications chain link is a modular decentralized Oracle Network that can be customized to deliver any data or do any external computation that you like so for example a lot of people say oh I can just make an https call to some API and we'll be good to go the blockchain nodes can't make these https calls because they wouldn't be able to reach consensus if they called the node at different times or they did something else all the consensus would be broken so instead we need a decentralized network of chain link oracles to do this and then in a transaction this network of nodes will return the data to our smart contracts for us now chain link networks can be completely customized to bring any data or any external computation that you want how however doing the customization can be a little bit extra work there are a ton of chain link features that come out of the box completely decentralized ready to Plug and Play into your smart contract applications what are those features the first one is going to be chain link data feeds and that's the one we're actually going to be using for our application here chain link data feeds currently at the time of recording are powering over $50 billion in the defi world the way they work is a network of chain link nodes gets data from different exchanges and data providers and brings that data through a network of decentralized chain link nodes the chain link nodes use a median to figure out what the actual price of the asset is and then deliver that in a single transaction to what's called a reference contract a price feed contract or a data contract on chain that other smart contracts can use and then those smart contracts use that that pricing information to power their defi application we can see an example we can see an example at data. chain. link and you can change networks you can change price feeds you can change a whole bunch of information to see some of the most popular price feeds let's look at ethusd for example on E USD we can see this whole network of independent chain link node operators that are each getting different answers for the price of at USD they're getting aggregated by the network and then delivered on chain we can see how often they're updated these ones are updated for a 0.5 deviation threshold or a few hour heartbeat which everyone hits first we can see when the last update was we can see the number of Oracle responses Etc we can see the contract address directly on chain we can even look at the contract on ether scan we can see some of the history we can see all the responses of the different Oracles and then at the bottom we can see the different users and sponsors keeping this network up similar to transaction gas whenever a node operator delivers data to a Smart contract the chain link node operators are paid a little bit of Oracle gas in the chain link token right now these users of the protocol are sponsoring keeping these feeds up and are paying the Oracle gas associated with delivering this data on chain here's an illustration of what the current model of these data feeds look like a network of these chain link nodes each reaches out and gets the information about an asset and then signs the data with their own private key in a single transaction then one node will deliver all the data with all the different signatures to a reference contract if that node doesn't deliver the data another node will send it instead reputation is incredibly important when you're a chain Leake node operator if you miss data updates if you forget to send transactions you'll probably be quickly kicked off these networks and have no chance of making any more money in the future these data feeds are used by some of the largest protocols in the space such as synthetics Sushi swap compound and a with several B million dollar each we can take a look at an example over at docs. chain. link now the docs are probably going to look very different by the time you actually start looking at them because they change the docs pretty frequently so an easy way to get started here is maybe go to docs. chain. link and then over either on developer Hub or overview go to data feeds and this is where you can see most of what you need in the getting started section of the documentation and we can see an example of an entire contra ra that uses and reads from one of these tring price feeds we can even open this up in remix and work with it in remix it looks like this example is reading from a price feed on koven the reason we're actually going to use a test net to see this work is that there's a set of chain link nodes monitoring the test Network to to show you exactly how this works out once we get deeper into the course we'll show you how to actually run tests and work with Chain Lake nodes without actually being on a test net which will make your development much faster but I highly recommend walking through this section along with me so that you can see firstand how this actually works so let's go ahead faucets. chain. linken we're going to switch to the Coen Network and we're going to get some koven eth but remember look at the network flag and use whatever network is in the documentation so to get some Coen we're going to come to the faucet we're going to turn off test link we'll just stay with eth I'm not a robot and then send request once our Coen ethereum has reached our wallet we can go ahead and close and we can take a look in our wallet and see that we do indeed have 0.1 each on Coen now let's go back to our remix we'll compile this contract we go and deploy this on injected web 3 and again the reason we're going to use injected web 3 instead of JavaScript VM is that there's no network of chain link nodes watching our little fake JavaScript VM there are a network of chain link nodes watching the test net so we'll scroll down we'll switch contract to the price consumer V3 and we'll hit deploy menam M will pop up and after a brief delay we can see our price feed consumer down here and we can hit get the latest price which shows us the latest price of ethereum in terms of USD you may be wondering why the number looks so weird that seems like a really large number for the price of ethereum in terms of USD and this is because decimals don't actually work so well in solidity and we'll get to that in a little bit there's a decimals flag associated with this price feed address that tells us how many decimals to include with this price so also in the documentation however I know that this one has eight decimals so this is saying the value of ethereum right now is [Music] $3,262 it may of course be different when you go ahead and try this now there's a number of things that happen in this contract that I'll explain in our fundme example but if you want to take a look now and see if you can figure out what's going on I recommend you do so price feeds are one of the most powerful out of the-box decentralized features you can use in your smart contract to level them up especially for decentralized finance if you're looking for different addresses of different price feeds you can check the contract addresses section of the documentation choose the network that you want and then scroll down and then look some of the different addresses of the different price feeds for example this address will give you the price of 1in token in terms of ethereum this address will give you the price of the Apple stock in terms of USD and so on and so forth the next decentralized application right out of the box is going to be chain link VF or chain link verifiable Randomness function once we do our Lottery example a little bit later we'll talk about how Randomness can be manipulated in blockchain blockchains are deterministic systems which by definition means that they can't have Randomness if you can determine what a random number is it's not really random anymore is it so we need a way to get a provably random number by looking outside of the blockchain and oracles are perfectly positioned to do exactly that chain link verifiable Randomness function is a way to get provably a random number into our smart contract to guarantee fairness and guarantee randomness of applications many protocols like pull together axi Infinity ether cards avag gois and more use chain link vrf for lotteries randomizing nfts for gaming and for more we're going to do an example of chain link vrf in a later section once we get to the lottery section if you want to see if you can play with the randomness yourself right now I recommend you going to docs. chain. link evm chains and scroll down to get a random number in this will teach you how to get a provably random number into your applications the next decentralized out-of- thebox feature of chain link is chain link Keepers which is decentralized event driven execution as you've seen in order to kick off some type of transaction somebody needs to spend the gas and somebody needs to sit down and hit the go button or hit the transact button or hit the send button this is obviously a centralized Vector if you have a decentralized application that needs to run at specific times or after specific events are triggered chain link keepers are the the solution to this chain link keepers are chain link nodes that listen to a registration contract for different events that you specify to fire maybe you say every 10 minutes you want to do something or once a week do something or if the price of some asset hits some number or maybe a liquidity pool is at a certain level whatever event that you want to code you absolutely can the chain leag nodes constantly listen for these triggers to happen and check the different contracts for these triggers once a trigger returns true the chain link nodes will then perform whatever action that you tell the chain link nodes to do we're also not going to go over the chain link keeper examples right now because we're going to get to them in a later module however if you want to try them out go to docs. chain. linkum going and go to making compatible contracts and feel free to read the documentation and try it out yourself the last out-of thebox feature of chain link is the most customizable but also the hardest to get correct end to-end reliability is the ultimate promise of our smart contracts and we want and need them to be able to do anything we want to be able to take any input and get any output chain link functions is the last decentralized out of thebox tool and it allows you to make any API call in a decentralized context through a network of chain link nodes we're not going to be going over that at all in this video but be sure to check out the documentation if that's something that you're interested in to me chain link functions is going to be the future of Def and smart contracts and if you're looking to make something novel and if you're looking to make something that's never been done before I 100% recommend you check out chain link functions later on after this course or whatever you want to do as of filming it came out about a month or two ago and people are just beginning to build amazing things with chain link functions so be sure to check this out after or during the course we're going to be using the chain link Automation in a later section in this course again if you want to try these out in remix on a real test net you can go to the documentation and play with them here now I know we haven't actually written that much code but we've gone over a ton so I want to do a quick review in order for a function to receive receive native blockchain token like ethereum you need to mark that function as payable if you want to force a transaction to do something and you want it to fail if that wasn't done you can use a require statement a transaction that reverts means it undoes any work that it did previously and returns any gas to the user to get the value sent with a transaction you can use the solidity Global message. Val chain link is a technology for getting external data and computation into our smart contracts and most importantly getting that data in a decentralized context in this example we're going to be using a chain link data feed or a chain link price feed which is a decentralized way to get pricing information from Real World assets into our smart contracts now in order for us to figure out if the amount of ethereum sent with a transaction is greater than or equal to our minimum USD of $5 we need to convert the amount of ethereum into its value of dollars so how are we going to do that well the first thing that we're going to need to do is we're going to need to get the price of ethereum or Avalanche or polygon or whatever native block token that we're working with so let's create a function to do that we'll create a function get price and this function is just going to get the price of ethereum in terms of USD and then we're also going to create a function called get conversion rate rate which is going to convert a value to its converted value based off of the price for now we're going to make them both public functions so we can play with them test them and do whatever we want with them to get the price of ethereum we're going to use a chain link data feed and we go through the documentation to get that information and just know in the data feed documentation the feeds addresses has now its own section price feed addresses you can scroll down in here go to ethereum and then just look for ethereum spoo for spolum so in the documentation I'm going to scroll down using data feeds they've got an example here right in solidity and if you wanted to like I said you could easily open this up in remix now you can see this example in the documentation what's actually going on when working with a chain leag price feed there's a contract out there add an address and we're going to call this latest round data function on that contract gives us a whole bunch of data but we really only care about the price so we're going to want to do the same thing we want to reach out to that contract that's currently storing and having the price updated so since we want to reach out to and work with the contract we're going to need two things right what are those two things we need the address and we need the AI the address of the contract is going to be really easy we can get the address by going to the chain link documentation and let's go to this price feed addresses section so now that we're at the docs we're going to go ahead we're going to go back to the feeds addresses price feed addresses here and we're going to scroll down and once again we can see in sapoia test net we can see the ethusd address down here on the seoa testet so now that we have the address how do we get the ABI well before with simple storage we imported the entire contract from the top and we compiled and we got the API like that we could do that here but that's kind of a lot of code and we don't actually care about what the whole contract looks like we only really want to know what the functions are so we can call that latest round data function remember if we're on remix and we go down to the comp details the ABI is really just this list of functions that we can call on a contract the ABI itself doesn't actually need to include any of the logic it just needs to say hey these are the functions you can interact with and here are their inputs and here's whether or not they're payable and here's whether or not their view functions Etc like I said though this kind of is a white lie you can also use a function selector or some other ways but we're just going to ignore that for now how can we get the ABI there's a concept in solidity known as the interface if we go to the chain link GitHub we go to to Smart contract kit / chainlink we can see a lot of different contracts in the chain link repository we go to contracts now depending on when you watch this this location might be a little bit different be sure to use the GitHub repo to get the most upto-date Edition so we're going to go ahead and scroll down to SRC sv08 we're now going to do shared it was previously in this interfaces folder we do shared interfaces and we're going to grab the aggregator V3 interface. if we scroll down we can actually see a whole bunch of function declarations but none of them are actually implemented it's just function the name of the function some stuff external view blah blah blah but then just the semicolon and nothing inside of them this is what's known as an interface if you compile this this will actually give us that ABI because it defines all the different functions that you can call on a contract it just doesn't have any of the logic again we don't really even need to know what the functions do we just need to know how to interact with a contract and if a contract is deployed it'll have that logic in it deployment so what we can do is we can copy this whole thing scroll all the way to the bottom hit the copy button and paste it in our remix now hold on though if you're following along you don't have to copy paste it in here with me because I'm going to teach you something in just a minute that makes this a little bit easier this pasted code alert comes up since we're only working on test Nets here we're going to be okay that we don't have to worry about p a code alert if you want to take a second to read it please do but we're going to paste this code in here just like we did before with simple storage for now you don't have to follow along I'm about to show you an easier way just follow along and watch now that we have this interface aggregator V3 interface we can use this interface to make API calls because now we have the address and we have the API and we can even compile this and it'll compile fine so we can say aggregator V3 interface at address this and the combination of these two give us whatever code is at this address with all the functions from the aggregator V3 interface and just to test this out we can do something simple like verion since if we scroll up it looks like there is indeed a version function put a little semicolon at the end so let's actually go ahead and actually copy this line give it its own function called get version this we'll have this public view Returns what is the version up here return a un 256 return a un 256 paste that line in here aggregator V3 interface at its address verion we'll say return all of that now I'm going to go ahead and deploy this to the seoa test net just to show you what this would actually look like however I'm going to recommend you don't do that for now just know that this will work this way you won't have to wait forever for your transactions to go through on the test net so to do this I'm going to go ahead scroll to the top go to injected metamask change the contract from aggregator V3 interface to fundme going to go ahead and hit deploy my metamask is going to pop up I'm going to go ahead and hit confirm and we're going to scroll down and now we have a big blue button called get version which I'm going to go ahead and click and we can see we get a four return because at this contract address on the blockchain it has the functionality for get version returning for and for the rest of this lesson I'm going to be showing you guys and testing this on an actual test net however I recommend that you don't test all of these as I go along just watch me do them because again waiting for transactions on a test net can be really annoying sometimes a test net might be having issues because again it's people running them out of the goodness of their heart so for this lesson just follow along write the code with me and then maybe at the end deploy everything so this is a really easy way and a common way that people use to interact with other contracts outside of their projects they get the interface of that contract using the interface keyword they compile it and the compiler actually gives us an API and then you just wrap an address around with that interface keyword and you can call any function at that address and and this one of these things as we work with more and more it'll start to make more sense in the beginning it might be a little hard to grasp but just bear with me for now the more we do it the better you'll get don't get discouraged take a deep breath and exhale and let's keep coding and if this is confusing to you this is again where we can work with our AI friends or any of the forums that we're working with again very soon I'm about to show you how to ask really good questions and make really good prompts but one we could ask here is hey I'm confused how does this solidity function return the value four when I didn't Define any logic in aggregator V3 interface and I just posted that code from get version here because a common issue that I see new developers run into is they go oh wait wait how does this version return four my aggregator V3 interface doesn't have any code in it why why does putting an address in here make it work like what's going on and let's see if our AI is able to help us here so this is chat gbt version 3.5 again I prefer version 4 but this is the cheaper one and it says in the code you provided the get version function is calling the version function of an instance of the aggregator V3 interface contract it appears that the contract address here is being used to create an instance of aggregator V3 interface the aggregator V3 interface is an interface contract that defines a set of functions that must be implemented by another contract it serves as a way to interact with the contract at the given address by providing a common interface the version function being called in your code is likely defined in the actual contract that implements this uh and this is pretty much correct right and so it gives us some more context here this is exactly correct this address has a version function and us surrounding it with this aggregative E3 interface like typ casting it in these parentheses like this is just telling our solidity compiler hey there's a version function at this address or there's a a latest round data function or all the functions all the functions in this aggregator V3 interface are at this address if this address doesn't have a version function this would just break and this is a good example of again where we can actually follow up with these AIS they're typically very good at keeping context so we could even ask what would happen if that contract address didn't have that function and we see if the implementation contract at the given address does not have a version function or if it has a different function signature calling version on the contract would result in a compilation error or a runtime error so it wouldn't result in a compilation error but the transaction would revert so so this is pretty helpful here but again we always want to double check this so this is where we'd probably go back to the discussions forum and follow up there so now that we actually have the interface we can start calling these functions and calling these addresses however having a ton of these interfaces is really going to clog up our contracts and clog up our files and be really gross to work with is there a better way for us to do this well when we worked with simple storage yes there was we just went ahead and used Imports right but that's when we had all the code in our locally in our directory we don't have all the code locally we didn't create the aggregator V3 interface we didn't create the price feed cont contracts so can we do something like import simple storage. soulle but with a contract outside of our project well again we could copy paste it to its own file and import aor V3 aggregator V3 interface. so and of course we're going to use this named import syntax because we're awesome developers we could copy paste it like this and do exactly what we did before we could create a new file called aggregator V3 interface paste the code in there or we could actually import directly from GitHub if we go back to the documentation of assciated with using data feeds we scroll down to using data feeds here scroll down we see at the top they do this import like this import at chain link SLC contracts SRC blah blah blah now if you look at the top of the documentation this link here this import aggregator V3 interface from chain link contract cv8 shared interfaces blah blah blah this might actually be different than what we show in the rest of the video just for you be sure to use whatever the documentation says and whatever we have in the GitHub repo associated with with this course so in this video we might actually use chain link contracts SRC v08 interfaces aggregator V3 interface and we skip over the shared but you should just use whatever the documentation says and whatever is in the GitHub repo associated with this course as of now we're going to use this line with this shared keyword so just keep that in mind when we're going along with this this import actually has the same setup as as the path of what's in the GitHub repository so instead of us copy pasting from GitHub we can actually import directly from GitHub or mpm we can copy this line back in our remix we could paste it in like this remix is smart enough to know that this chainlink contracts is referring to the what's known as an mpm package chainlink contracts at chain link contracts is what's known as a package manager and it keeps different versions of combinations of code for us to download at chainlink contracts is created directly from chain link repository remix downloads all this code from mpm which is created from the GitHub so it essentially downloads it from the GitHub so us doing this import like this is the same as is just copy pasting the entire interface at the top of our contract and just remember again during some of this video we're going to have the chain link contracts SRC V Z8 interfaces aggregator V3 interface while other times we're going to have the shared keyword in here like I said be sure to use whatever the documentation and the GTO repo associated with this course says to use now we have this aggregator V3 interface that we want to work with we can go ahead and compile and bada bing bada boom so great so now that we have the interface here which will give a minimalistic ABI for us to interact with the contract how do we actually get the pricing information well again if we go back to the docs we can see right here gives us an example of the code we can use to get the latest price but let's write it ourselves just so that we know what's going on we'll say aggregator V3 interface and we'll actually create a new variable called price feed equals aggregator V3 inter interface contract at this address which again only works for sapoia now we can call this latest round data function on the price feed so we'll say price feed. late round data and if we look at the interface on GitHub we can actually see latest round data doesn't just return one variable it returns a whole bunch of different types of variables and to return multiple types we do some syntax that looks like this and we'll say uint 880 round ID and you can even flip back and forth between the documentation make sure you have it right int price which again we know an INT defaults to an INT 256 uint 256 started app uint 256 Tim stamp and then U 80 answered in round there's a lot of code in here since this function returns so many variables we have to set something up to capture them but we don't care about any of this other stuff we just care about price so what we can do is actually just remove them and leave the commas in there so we're going to remove started at remove timestamp remove answered and round and I hit command s to compile we're going to get these yellow squiggly lines which are warnings but we're going to fix them in a minute now we have in price equals Price feed. latest round data because we only care about getting the price from the return the reason price is an into 56 is because some price feeds could be negative now that we have the price this price variable is going to be representing the price of eth in terms of USD and it's going to return a number that looks like this because again slity doesn't work with decimals so we know that this price feed has eight decimals but it'll get a return like this boom like this it'll return a value that looks like this if we want to double check how many decimals there are in a price feed it actually has a decimals function which allows you to check that as well now as we know message. value is going to have 18 decimal places how do we know that well because we know that one ether is equal to this many way and this many way has 18 zeros 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 so this massive number is equal to 1 ethereum right 1 Point 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 so right now message D value and price actually have different decimal places price has eight message D value is going to have 18 so to get them to match up we have to do return price times 1 E10 or to add those additional 10 decimal places and yes I know we have a red line I'll fix this in a minute price as we know is a in 256 and message. value is going to be a u 256 so the types are actually different so we want to get the price in terms of U 256 instead of in 256 to convert them we can again do a thing called type casting there are a lot of different types that can be easily converted between each other not all types can be typ casted but an INT and a u 256 can be so to make our price a u 256 we would just do uint 256 and wrap price like this or we could just wrap both them like this now of course since we're not modifying any state but we are reading storage we can make this a view function and then we'll say it returns a uint 256 like so and now if we compile we get rid of all those errors and warnings now math can be a little bit tricky in solidity but the more you do it the better you'll get and the reason math can be tricky is because there aren't any decimal places so you need to only work with whole numbers the more you work with it the better you'll get though awesome so now we have a get price function which is going to return the value of ethereum in terms of USD as a uint 256 now all we have to do is convert our message. value in terms of dollars using this get price function to do that we're going to use our get conversion rate function this get conversion rate function is going to take a u 256 eth amount as an input and we're going to convert this eth amount to its value in dollars this will be a public view function that will return a uint 256 so first we're going to get the price of ethereum by doing u56 e price equals our get price function that we just defined and then we're going to do U into 256 eth amount in USD equals eth price times e amount and then we actually have to divide by 1 E18 the reason we divide by 1 E18 is because both of these have 18 decimal places and if we multiply 1 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 10 if we multiply these by each other where both of these are representing one we're actually going to get a number that's absolutely massive with 38 decimal places so we need to divide by8 to reduce it back down to what it should actually be an important rule with working with math and solidity is you always want to multiply before you divide the reason for this is since again only whole numbers work in solidity you were to do one divide by two you would end up getting zero so you always want to multiply first when we get to the foundary section of the of course testing all this math is going to be a lot easier if you're really struggling with some of the math bits right now I wouldn't let that slow you down because one of the things that AI is really good at is doing a lot of these math conversions but in any case this eth amount in USD is the number that we looking for so we can say return eth amount in USD and awesome now we have a get conversion rate function let's walk through this together just so that you can understand what's actually going on let's say we want to see how much one eth is worth well we're going to get the eth price which let's say it's $2,000 but it's going to be $2,000 with 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 10 18 zeros so eth price might look something like this so that means we're going to do this 2,000 with 18 decimal places times 1 E which is going to be 1 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 8 9 10 we're going to multiply those together and then since we're going to get an additional 36 zeros then we just divide by one E18 and that's how we would get $2,000 equals 1 E it's going to be 2,000 of course with 18 decimal places one of the good reasons for using whole numbers in solidity is that it's not possible to have decimal places so we don't lose any Precision which is really good so normally we should test this function before continuing but since we're doing all this on a test net and I promise you that I tested this all beforehand we're just going to go ahead and keep going so now that we've done all this work if we want to make sure that our users are sending at least $5 we can do get conversion rate of message. sender needs to be greater than minimum USD because get conversion rate takes an eth amount as input uses the pricing information to get the dollar value back and we're going to check to see that the dollar value of the message. value is greater than the minimum USD however since get conversion rate returns a value with 18 decimal places we need to update our minimum USD to say 5 * 10 raised to the 18th or we could also do 5 E18 or we do 5 times 1 E18 I personally like this 518 syntax but whatever works for you I'm going to deploy this to a test net just to demonstrate this working but again you do not have to so we're going to go ahead delete our previous deployments injected web 3 deploy mamass pops up going to go ahead and confirm after a long delay we'll get our deployed contract here we have all the stuff we can call get price and we can see the value of ethereum right now is this with 18 decimal places which is awesome so it's around $1,896 so if I were to try to fund this with maybe 100 way I know for a fact that 100 way isn't going to be enough so if we call this fund function we're actually going to get this gas estimation failed gas estimation error failed with the following message blah blah blah error execution reverted didn't send enough eth which is actually exactly the error message that we have here it's exactly what our error message is here in our require didn't send enough eth so if we try to fund it we're going to get didn't send enough eth and this gas estimation failed is a pretty common error that you'll see in remix and solidity and evm in general it's kind of just the boilerplate answer for something went wrong luckily we got the actual error message here so that we could debug here's what's actually going on now you see here we could still send this transaction like I said we would actually spend gas to send a failed transaction and this isn't something that we want to do so we're going to go ahead and cancel however if we did send maybe one 1 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 so if we go to Google actually we can even see like an eth to dollar conversion rate so if we sent 0.01 0.01 eth right now is worth $18 it might be different depending on when you actually do it so we send 0.01 e in our remix and we can do that by doing 1 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 so it's 1 e16 and we hit fund now we actually see metam Mass pops up we don't get that gas estimation error we can go ahead and confirm and we can see that our function is working as expected which is great it's reverting transactions that have less than $5 and it's letting transactions go through that have at least $5 awesome and if we select minimum USD we can obviously see that here and we can see we have 0.01 eth here fantastic and since we don't have a withdraw function here we actually can't pull it out which is another reason why I say hey maybe don't test this right now but great we've confirmed our get conversion rate is working so let's move on fantastic so what's the next thing what that we should do in this contract well we probably want to keep track of the users who send us money in this contract so we can keep an array of addresses called funders and keep updating that depending on who actually sends US money so up at the top we'll make an address array or an address list we'll make it public and we'll call it funders and anytime somebody sends US money we'll say funders do push message. sender like message. Val message. sender is another Global variable we can use in solidity which refers to whoever call this function the sender of the transaction to this contract so if we're on sapoia and we initialize a transaction from our metamask the message. sender is going to be this account right here and then maybe we want to even make a mapping of addresses to to make it easier to look up how much money each fun has sent so we'll make a mapping of an address to a a into 256 we'll call it public address to amount funded now something that's newer in solidity is you can actually name the types in your mapping so you could say address funer mapped to un 256 amount funded usually this is what's known as a little syntactic sugar it's just to make it easier to read what this mapping is Right fun to amount funded and then our variable name is very explicit address to amount funded now if somebody funds our contract we'll of course do address to amount funded the message. senders address plus equals whatever they previously have funded plus message. valal whatever they're additionally adding all right great and now we have a way for us to keep track of funders sending money to our contract and have an easy way with a mapping to look up how much they've spent in total now I know we've gone over a lot of Advance solidity here so let's do a quick refresher of what we've learned so far whenever we interact with a contract we always need the address and the ABI compiling an interface allows us to get that ABI very easily for us to interact with another contract when we combine the contract address with the interface we can easily call the functions on that contract chain link price feeds are an easy way to get data especially pricing data from The Real World into our smart contracts when working with math in solidity and the evm in general decimals don't work so we need to always make sure we're using the correct number of units whenever we interact with our contracts message. Val and message. sender are known as globally available units and solidity and they refer to the sender of a message of the current call or the number of ways sent with a message or transaction there's a whole bunch of these and you can view them all in the solidity documentation all right great so we've got a way to actually get this pricing information pretty easily however our code is getting a little bit cluttered with these get price and G conversion rate you'd think that these are functions that would be reused pretty often anyways for anybody looking to work with chain link price feeds so is there an easier way for us to work with this pricing information maybe doing some math like this is pretty common and we'd want other contracts to be able to import this conversion functionality and a way that we can do that is actually creating something called a library there's a site out there called solidity by example which has great examples of using libraries and what they work with libraries are similar to contracts but you can't declare any state variables and you can't send ether a library is embedded into the contract if all Library functions are internal otherwise the library must be deployed and then linked before the contract is deployed that's a little bit confusing don't worry too much about that right now using libraries can actually add functionality to different values and what do I mean by that well I mean we can have our get conversion rate function be a function of any value of type you 256 means we could take this get conversion rate and do something like message. value. getet conversion rate so we can create our own custom function with any type we could work with get conversion rate as if message. value was a class or an object or cont cont that we actually created to do this let's go back to our files create a new one create a new one called price converter soul and this is going to be a library a price converter Library so how do we create a library and what is a library well a library is going to be very similar to a contract we're going to start of course with spdx license identifier we're going to do pragma solidity and we'll give it a version of 0.818 the little carrot and instead of typing contract we're actually going to type library for the name of the library and we're going to call this Library price converter so libraries can't have any state variables and all the functions have to be marked internal so what we're going to do is we're going to go back to fundme doso zoom out a little bit we're going to grab get price get conversion rate and get version delete them well I hit copy first go back to price converter paste them in here and work with them in here of course we're going to need the aggregator V3 interface so we're going to go back to our funme we're going to copy this name import from aggregator V3 interface paste it in at the top here hit command s and we're going to go ahead and compile this successfully fundme is no longer going to compile but we're going to fix that in a little bit now the first thing that we're going to need to do in here is make these all internal so we're going to say internal like this we do internal get conversion rate and internal get version now that we have our price converter Library we can actually import it back in our fundme and attach it to a un 256 and let's actually delete this aggregator V3 interface line for now and we'll do import price converter fromprice converter doou and now to attach the functions in our price converter library to All U 256s we'll say using price converter or uint 256 of course if we compile our fundme we're going to get an issue because it doesn't really know what get conversion rate is so for now let's actually just comment out this line I'm going to remove these comments up here as well so what we can do now is we can do message. value. getet conversion rate get conversion rate and in your library whenever you're working with the library the first input variable for a library is going to be the type that you're using with the library so message. value is of type un 256 so this gets passed inside of get conversion rate as the first variable into U 256 eth amount even though we don't pass any variables inside of these parentheses here for get price and get version we don't really care to have an input parameter at all so it'll pass it in but not do anything so now instead of require get conversion rate of message. value we can actually do let's uncomment this line now and let's delete this line we can actually do message. value. getet conversion rate conversion rate and now if we compile this this is going to compile successfully this works because we're attaching the price converter library to all un 256s so now all U 256s have access to this get conversion rate function and since message. Val is a u 256 it can call doget conversion rate and it'll pass itself so that message. value as the first input parameter to the function here if we wanted another variable in here like U into six something else that would be the first parameter inside these parentheses so maybe like one 23 or something right this one 23 would be the something else but message. Val would still be the initial parameter which in this example would be eth amount so let's go ahead and undo that undo that but all right great we've moved a lot of the math into our own Library congratulations nice work one of the most common libraries that was used for a long time was this Library called safemath doso and in your solidity Journeys you'll probably see it pop up from time to time now we're going to go off on a little bit of a tangent here about safe math and the library safe math and this is an exerpt from my course last year so you might see stuff like rink B and some other stuff but just focus on the safe math stuff just know when we refer to the JavaScript virtual machine that's talking about the remix virtual machine one of the most common libraries that was used for the longest time was this Library called safemath dossou and you'll probably see it a lot of different places we're going to go off on a quick little tangent here and teach you about safe maath so let's close fundme and close price converter and let's create a new file called safe maath tester. soul and let's start with some basic stuff in here safe maath was all over the place before version 0.8 of solidity and now it's almost in no contracts what happened why is safe math no longer used as much well let's create sample contract this is a section that you don't have to follow along if you don't want to code along with me but if you want to you absolutely still can this is going to be a contract we are going to deploy on a JavaScript virtual machine uh we can use any version of solidity before version 0.8 of solidity so for example we'll use pragma carot 0.6.0 and we'll create contract safe math tester. Soul now if I create a un 8 I set it to public big number and I set this to 255 oops safe math tester let's go ahead and compile safe math tester with 0.6 7 ragma solidity the maximum size of a uint 8 is going to be 255 this is going to be the biggest number that we can fit in an U 8 and if I were to deploy this to a JavaScript VM or even a test Network save math tester let's go ahead and deploy it if I hit big number we're going to get 255 but what happens if I create a function called add that sets big number equal to big number + 1 let's save that delete that old contract and deploy well right now big number is 255 what happens when we add one to big number when 255 is the max size a unint 8 can be well let's hit add now let's check what big number is big number gets reset to zero so what's going on well prior to version 0.8 of solidity unside integers and integers ran on this concept of being unchecked which means that if you passed the upper limit of a number it would just wrap around and start back from the lowest number it could be so if I call add a whole bunch more times and hit big number now it's eight if I were to hit this add button a ton more times and get it back to 255 it would then continue to wrap over to zero so one of the most popular libraries that was out there was this safe math Library which would basically check to make sure that you weren't wrapping around a un 256 or an in 256 basically it was a way to say hey you've reached the max this number can be and now your transaction is going to fail if we switch this to 0.8 of solidity delete the old contract go switch this to 0.8 we'll go ahead and compile it and now we deploy this to JavaScript VM if I hit big number we get 255 but if we hit add it actually fails and we still get 255 in version 0.8 of solidity they added this bit where it automatically checks to make sure if you're going to do what's called overflow or underflow on a variable we can actually revert back to the unchecked version by using an unchecked keyword so if we wrap this big number equals big number + one in this unchecked bracket let's delete our old contract we'll compile we'll redeploy we hit big numbers 255 now we hit add we hit big number again it reverted back to zero so that's a little bit more about safe math checked and unchecked so in version 0.76 and below this code that you see in front of you is going to be the exact same as this code in 0.8 and above with this unchecked keyword now you might be thinking in newer versions of solidity why would I use this unchecked keyword well you'll find out later that this unchecked keyword makes your code a little bit more gas efficient so if you're absolutely positive that your math is never going to reach the top or bottom limits of a number then it might make sense for you to use the unchecked keyword let's head back over to our fundme contract where we are now using the price converter library that we just created awesome we have a lot of the basics of the math that we need in our fundme contract so all right so this is great people can actually send us money and we're going to keep track of them as well which is fantastic so the next thing obviously that we're going to to want to do is we're going to want to be able to withdraw that money out so now let's go ahead and Implement our withdraw function when we withdraw the money we're probably going to want to reset all the mappings back down to zero to show that hey we've withdrawn all the money and there's nobody left to do this we're going to use something called a for Loop a for Loop is a way to Loop through a list of something or to do something in a repeated amount of time if you're familiar with other programming languages it's the exact same concept we wanted to get all the elements in this list for example which where one is at the zeroth index two is at the first index three is at the second index and four is at the third index which I know is a little bit confusing these are the different these are the indexes these are the elements we would Loop 0 through three to get all the elements out of this array to do this loop we're going to use the four keyword we're going to say four put some parentheses and in a for Loop we can add a couple things and by the way this is a way to do comments inside of a line and solidity you do a back SL star star back slash and now everything in here is a common so in a for Loop you first need to give it the starting index then you give it the ending index and then you can give it the step amount for example let's say we want to start on the zeroth index we want to go all the way up to the 10th index and we want to go by up each time we would do zero 1 2 3 4 Etc well let's say we want to start with the third index we want to go to the 12th index and we want it up by two every single time well we would do three 5 7 9 Etc so our starting index is going to be a unu 256 and we'll call it funer index and we're going to say we're going to start with zero and we're going to end once the funer index is less than the fun. length so I know I said up here it's the ending index but instead it's a Boolean once the funders index is greater than fund. length which is how you can get the length of an array then we're going to end and then finally we're going to say every single time we do a loop we're going to say funders index equals funders index plus one now there's a shortcut you can do to do some variable equals itself plus one and that's just Plus+ this plus plus means every time we go through the loop just add one and we actually don't need that here and then we put these curly braces to say okay execute everything inside of this Loop here for the duration that we specified here and this final piece means that every time we run through all the code inside of these brackets we're going to add one to this funders index that's how we go from 0 to 1 2 3 4 5 6 7 Etc to access the zero withth element of our funders array we're going to say funders of fun index and this is going to return an address since it's an array of addresses so we'll say address fun equals funders of funer index and we want to use this to reset our mapping address to amount funded so we can say address to amount funded at the funer address is now equal to zero so we're going to reset whatever we added when they funded us down to zero because we're withdrawing all the money out and additionally how there's a nice little shorthand like Plus+ down here up here in the fund another nice little shortcut whenever you want to add something to whenever you want to add something to something that already exists instead of doing something equals itself plus the new thing you can just do plus equals this means that we're going to set address to amount funded of message. sender equal to itself plus message. Val so let's walk through this for Loop a little bit we're going to start with the zerith index we're going to get the fun at the zerith index in our funer array we're going to take that address stick it into our mapping and reset the amount that they've sent us to zero then we're going to do funer Plus+ we're going to check to see that funer plus funer index Plus plus plus is less than funders do length obviously fund 0 + 1 is going to be one so we're going to check if one is less than the total amount of funders and then we're going to get the address of the fun at the first index reset them to zero get the address at the second index reset them to zero third index etc etc until we finally reach the index that is equal to or greater than the length so if we have 10 funders and we reach funer index 10 the for Loop will exit and be done but we still haven't done two things we need to reset the array still and then we also need to withdraw the funds since we've accumulated all this message. value in the fund function to reset the funders array we could do the same thing we did with the mapping and reset each single address at each index or we could just create a brand new funders array which is what we're going to do so to reset the array we're now going to say funders equals new address array and to start off at a length of zero previously we used the new keyword to deploy a different contract now we're using the new keyword to reset the funders array to a brand new blank address array this part is a little confusing don't let it hold you back and lat later in the course why we make the choices here that we do so great we've gone ahead and reset the array so now how do we actually withdraw the funds for this section I'm going to go ahead and again refer to a previous course that it did because the content is exactly the same just remember JavaScript VM is remix VM so great we've gone ahead and reset the array but how do we actually now withdraw funds from this contract how do we send the funds back to whomever is calling this now to actually send ether or send native blockchain currency there are actually three different ways to do this we're going to we going to look at all three and say what the differences between the three of them are the three different ways are going to be transfer send and call let's go ahead and start with transfer since transfer is the simplest and at surface level makes the most sense to use so if we want to transfer the funds to whomever is calling this withdrawal function we would do we would say message. sender. transfer and then get the balance of our contract here by saying address this the this keyword refers to this whole contract. balance and we can get the native blockchain currency or the ethereum currency balance of this address like this and we can just do that only thing that we need to do is we need to cast we need to typ cast message. sender from an address type to a payable address type so message. sender is of type address whereas payable message. sender is of type payable address and in solidity in order to send the native blockchain token like ethereum you can only work with payable addresses to do that so we just wrap it in this payable type Caster so this is the first way that we actually send ethereum or send tokens from different contract conts to each other we wrap the address that we want to send it in in this payable keyword we do transfer and then we say exactly how much we want to transfer but there are some issues with transfer here we are on solidity by example for sending ether which again is a fantastic resource to refer to if you get lost the method that we just looked at was this transfer method now we saw way earlier in the course that if i s ethereum from one address to another it cost about 2100 gas or 2,100 gas our transfer function is capped at 2300 gas and if more gas is used it throws an error the next one that we're using is going to be send which is also capped at 2300 gas and if it fails it'll return a Boolean so with transfer if this line fails it'll error and revert the transaction with send it won't error it'll return a Boolean of whether or not it was successful so using send will do payable message. sender. send address this balance but we don't want to finish our call Here If This Were to fail the contract wouldn't revert the transaction and we just wouldn't get our money sent so we want to do Boolean send success equals this whole bit here and then we want to require send success and if this send fails we'll throw an error saying send failed this way if this fails we will still revert by adding our require statement here transfer automatically reverts if the transfer fails send will only revert the transaction if we add this required statement here so great what's the third one way that we can actually send ethereum or native currency well it's with this call command Now call is going to be one of the first lower level commands that we actually use in our solidity code because this call function is actually incredibly powerful and we can use it to call virtually any function in all of ethereum without even having to have the AI we'll learn the advanced ways to use this call much later for now we're just going to learn how to use it to send ethereum or your native blockchain currency call is going to look very similar to send we're going to do payable message. sender. call and this is where we'll put any function information or any information about the function we want to call on some other contract we actually don't want to call a function so we're going to leave this blank we can show that we're leaving it blank by just putting in these two quotes here we instead want to use this like a transaction and as we saw in our deployment there's always this message. value bit so we're going to use this call function as if it's a regular transaction and we can add stuff like message. value so in here we're going to add these squiggly brackets and we're going to say value address this balance this call function returns actually two variables and when a function returns two variables we can show that by placing them into parentheses on the left hand side the two variables it returns are going to be a Boolean that we're going to call call success and also a bytes object called Data returned since call allows us to actually call different functions if that function returns some data or Returns value we're going to save that in the data returned variable it also returns call success where if the function was successfully called this will be true if not this will be false and since byes objects are arrays data returns needs to be in memory now for our code here we're actually not calling a function so we don't really care about data returned so similar to what we saw with the price contract we can just go ahead and delete that and leave the comma to tell solidity yeah we know this function returns two variables but but we only care about one and then similar to the send piece above we're going to do require call success call failed meaning that we're requiring call success is true otherwise we'll revert with an error that says call failed now if learning the difference between these three is a little complicated for you right now don't let that slow you down feel free to come back to this after you've learn more about how some of these lower level functions work and a little bit more about how Gas Works solidity by examp Le does a fantastic job though of saying what the differences between all three are transfer has a maximum of 2,300 gas and throws an error if it fails send has a maximum of 2300 gas returns a Boolean if it fails call forwards all gas so doesn't have a capped gas and similar to send returns a Boolean if it is successful or if it fails as of recording right now using call is the recommended way to actually send and receive ethereum or your blockchain native token for now if this part's a little bit confusing for you for now just look at this and see Ah that's how we send and transfer ethereum or native blockchain currency tokens and I'm going to delete this part for the video but but I'll keep those comments in the code repository associated with this course all right great and actually the exact same code from that video we're going to use for this as well so we're going to use this call call success to work with sending a balance however there's a bit of an issue here right now anybody can call this withdraw function and take all the money out of this contract we don't want that we want anyone to be able to fund the contract but we don't want anyone to be able to withdraw money from the contract we only want the owner of the contract to be able to withdraw so how do we set this contract up so that the withdrawal function can only be called by the owner of this contract well we want to set this cont contract up so that whenever we deploy it whenever we create this contract an owner gets assigned to this contract we assign some address to being the owner and then we add some parameters so that withdraw can only be called by that address so what we could do is we could set up some function called call me write away and when we deploy this contract we would just immediately call this call me RightWay function which will set us up as the owner however that would take two transactions and remember we're Engineers we want to work incredibly hard to be incredibly lazy so instead solidity has something called a Constructor and if you're familiar with other programming languages a Constructor is the exact same as really every other programming language and the Constructor is a keyword and a special function in solidity so we can create a Constructor function without the function keyword we just call it structor and we also don't even need the public keyword you'll see remix even highlights it pink this is going to be that function it's going to be a function that is immediately called whenever you deploy your contract this this function will be called in the exact same transaction that is used to deploy your contract for example if I were to take this minimum USD added in our Constructor and say minimum USD equals 2 this minimum USD would immediately get updated to two right after this contract is deployed in that exact same transaction since we want this withdrawal function to only to be able to be called by the owner of this contract in our Constructor we can set up an address right away to be the owner of this contract so let's create a global variable called address public owner and then right in our Constructor we'll say owner equals message. sender message. sender of course being the sender of the caller which in this example is going to be the deployer of the contract and don't worry we're going to demo all of this very soon to show you everything that's going on if you want to test all this right now absolutely go for it but just remember it's going to take you a little bit longer on a test net and I'm going to show you how it all works anyways now that we have our own setup we can actually modify our withdraw function so that only the owner can call this function easily enough we're already familiar with the require keyword we could add a require the message. sender of whoever calls this withdrawal function must be equal to and this is how you do equals in solidity with this double equal sign a single equal is set a double equals means equals so message. sender must equal the owner and if it's not the owner we could revert with something like must be owner awesome so now we have a quick way to require that whoever calls the withdrawal function is indeed the owner awesome but let's say we have a lot of admin functions or only owner functions or functions that should only be called by the owner would we have to put this line on every single function remember we want to work incredibly hard to be incredibly lazy we don't want to have to copy paste this line to every one of these functions and this is where something called modifiers come into play so we're going to go ahead and actually delete this line and at the bottom we're going to create our first modifier a modifier is going to allow us to create a keyword that we can put right in the function declaration to add some functionality very quickly and easily to any function to create a modifier you use the modifier keyword and then you set it up very similarly to a function so our modifier is going to be called only owner we don't give it a visibility like functions and in here we can put our code so again we'll say require the message. sender is equal to not set to is equal to the owner and if it's not the owner we're going to say sender is not owner like this and then underneath we're going to put this little underscore with a semicolon what we can do is we can take this only owner keyword and stick it in the function Declaration of our withdraw and what's going to happen now is it's going to execute what's in this modifier first it's going to execute this require and then this little underscore says and then add whatever else you want to do in the function so we're going to execute this require then whatever else is in the function and for our withdraw a function it's going to be everything else in here in our modifier if we had the underscore above the require this means that we would execute the code inside the function first and then the requir so the order of your underscore matters so now with this modifier keyword in the withdraw function whenever you call the withdraw function we first go up there's a modifier I got a drop down here we'll execute this oh here's an underscore time to go back to the function let's do what's else is in the rest of the code and then it'll come back down to the only owner modifier and say oh is there anything else to do oh there's nothing else so I guess we're good so let's see this all go through end to end and remember you don't actually have to deploy this to a test net if you don't want to but if you want to follow along feel free to do so of course as well get started let's of course compile fundme Doo looks good let's delete any contracts deployed previously let's make sure we're on injected provider metamask and let's make sure that we are on a test net we are indeed let's make sure we have a little bit of test net eth in our wallet and we sure do and let's go down to the contract cont and make sure we're on the right contract if you try to deploy something like an interface you'll get an alert like this this contract might be abstract blah blah blah so we're not going to do the interface we're going to do the fundme contract of course we'll hit deploy metamask will pop up we'll go ahead and hit confirm on the metamask and then we're going to have to wait a little bit for the contract to actually finish deploying if we pull up the terminal we can see the contract go through and we can also see it in remix here now we've got a number of buttons in here we've got our red fund button of course which is because we have our fund function which is payable and this allows us to send eth with this function we have our withdraw function which is just orange because it is not payable although it is going to be withdrawing money out of the contract and then we have our typical blue View and pure functions the owner of course is going to be our metamask since we are the ones who deployed this contract minimum USD is going to be five and these are of course going to be empty we can call our fund function only if we send some value with it if we try to call fund without any value we're going to get this gas estimation error failed and we'll even see didn't send enough eth in the arrow log so let's go ahead and cancel this again we could send this but that would be a huge waste of gas so we'll cancel it and let's get a value that's going to be enough so I believe 0.01 e should be enough let's say 0.01 eth it looks like that's about $18 so back in remix let's do 0.01 e in terms of way which is this value here paste that in and we'll scroll down now if we call fund it does indeed go through and we can go ahead and hit confirm on this as well and we see that transaction pop up on ether scan and we might have to wait a little bit for this transaction to finish finish going through finish indexing Etc so let's give it a couple minutes oh looks like it's gone through fantastic we can even see in the fundme contract the balance has gone up to 0.01 and we can see if we look at funders at index zero we can see our address and if we copy our address and paste it into the mapping address to amount funded we do indeed see an amount in here with this transaction fund being called of course on the test net ether scan we can see all the data and information associated with this and we can even scroll down and see the input data we can see that this was calling the fund function we'll learn more about the input data later so now what we could do is we could do the reverse we could go ahead and withdraw and that should reset the mapping and the array back down to zero for our modifier to work we have to use withdraw on this account if we switch to an account that isn't the owner of this contract and we go ahead and reconnect and we scroll down we make sure value is zero and we scroll down and try to hit withdraw we'll see we get gas estimate failed and we'll even say sender is not the owner so we'll go ahead and cancel that we'll switch back to account one we'll make sure we're working with account one now we'll call withdraw we'll see metamask does indeed pop up and we can go ahead and confirm and in just a minute we'll see the balance reset and if we call our funders and mapping they should also have been reset so let's wait a little bit now if I try to call address to amount funded with that same address we now get zero and now if I look at funders at index zero it actually airs and this is incorrect following our more advanced Lo Concepts if you don't understand them the first time don't let them stop you they are not required to know to continue the following is an excerpt from a slightly older edition of this course you'll see that I don't use named Imports like a noob and a few other pieces of the code look slightly different but this next section we're going to go over a lot of really Advanced solidity pieces here that are going to really Advanced solidity fundamentals these are going to be fantastic for saving gas making your code look a lot cleaner and just better coding practices overall for those of you who are looking to go super far with this definitely be sure to pay attention to this section because this will make you look like a badass when you code later on just remember when we say JavaScript VM we just mean remix VM additionally whenever we deploy to the rink B test net just know that you should be deploying to theoa test net or whatever the most up-to-date test net is or just don't deploy to the test net and just follow along we're going to modify this contract to make it a little bit more professional it's not going to be end to endend amazing but it's going to be a little bit better and you'll see why in a minute so the first thing that we're going to do is we're looking we're going to look at some of these variables here in particular owner and minimum USD owner gets set one time in our contract here and then it never changes again minimum USD gets set one time even outside of the Constructor if we have variables that only get set one time we can actually use some tools and solidity to make them more gas efficient for now let's compile our fundme contract and then deploy it to a JavaScript virtual machine remember we can go ahead and deploy it right now however funding and withdrawing and doing any of the money stuff isn't going to work because again we don't have a chain Lake Network on our JavaScript VM so those aren't going to work so well but for what we're going to do right now we don't really care so much here's what we do care about we do care about how much gas this costs to actually send we do care about how much gas this costs to create right now creating this contract costs about $59,000 gas and we're going to add a couple of Tricks right now to bring this number down we're going to add some stuff back in in a bit which will bring it back up but for now we're going to learn some tricks to bring this number down the two tricks that we're going to learn are the constant keyword and the immutable keyword in their solidity there are two keywords that make it so that that your variables can't be changed and those keywords are constant and immutable you can learn more about them in the solidity documentation if you assign a variable once outside of a function and then never change it so if if it's assigned at compile time you can go ahead and add this constant keyword we'll learn later about storage but when you add a constant keyword this minimum USD no longer takes up a storage spot and is much easier to read to so now if we recompile this and we deploy this new contract let's see if we saved any gas we look in the transaction logs now we can grab the transaction cost of how much this cost to deploy and let's compare it to how much it was before wow we saved almost 19,000 gas that's almost as much gas as it cost to send ethereum typically constant variables have a different naming convention typically you'll want to do them all caps like Min _ USD so all caps with underscores so now let's just find minimum use D and replace that with all caps as well with this interaction we know that this variable is a constant variable and it's much cheaper to read from now if we go ahead compile this and redeploy in our fundme contract even though this is a view function remember view functions do have gas costs when when called by a contract as a constant variable we can see the execution cost of this variable 21,45 gas so let's put a little note right underneath it if we remove the constant variable we delete this contract we redeploy collect fundme and we hit minimum USD again we can now see how much gas this was cost if it wasn't a constant variable we can see the gas cost did indeed go up now on chains that are much cheaper this gas difference probably won't make it that much of a difference but on more expensive chains like ethereum this is going to make a big difference for example on ethereum we can actually see current gas prices on ethereum here we can see the current gas price of ethereum is about 141 gay so we'll go to our converter gay to way we'll copy the whe price times this we'll get the gas price of calling our minimum USD which is this number here which if we put back in our ethereum unit converter we can see cost this much gas and if we times that by the approximate current price of ethereum which is around $3,000 calling minimum USD as a constant is going to cost $9 calling this that is at a non-constant is going to cost almost an entire dollar more you you can see how all these little gas optimization tricks are going to make your life a lot better so let's keep this constant keyword in here we'll learn more about constant and storage in later sections of this course now as you're just getting started with this course and with solidity do not struggle and do not worry about making your contracts as gas efficient as possible in the beginning and especially right now just write your contracts as best as you can once you get really good at gas and once you get much later on in the course and much more advanced with solidity then you can start going back and working on gas optimizations but do not let gas optimizations hold you back or if you start stressing over it just let it go don't worry about it and just write your code as best you can so long story short do not stress about gas optimizations right now now another variable we only set one time is going to be our owner variable owner equals message. sender we set this one time in the Constructor variables that we set one time but outside of the same line that they're declared and we set them for example in the Constructor we can Mark as a mutable typically a good convention for marking immutable variables is going to be doing I underscore so that we know that these are imut variables they have very similar gas savings to the constant keyword owner of course is a variable that we can't set on the line here because inside the global scope there's no function going on however inside functions because inside the global scope there's going to be no message. sender there's only going to be a message. sender when we're inside of a function so inside here we might say I owner equals message. sender and then of course we'll scroll down and we'll change this require only owner now equals I owner now if we compile that and deploy it we can see how much gas we can see how much gas calling ioner is going to be by with the immutable we get 2158 which we'll go ahead and copy for now and we'll put right here we'll say immutable now if we remove the immutable keyword let's close this redeploy now if we scroll down to I owner scroll up the logs we go down to the call scroll down we see the execution cost was much more so we'll do double back slash paste that in here gas or non immutable so you want to keep some of these tricks in mind when it comes to storing variables the reason that these two save gas is because instead of storing these variables inside of a storage slot we actually store them directly into the bite code of the contract and like I said don't worry too much about that for now later on in the course we'll teach you more about storage and a lot of this lowlevel stuff that comes with these contracts but for now just know that these exist and they're nice gas Savers if you're only setting your variables once all right great so we've just made our contract a little bit more gas efficient little gas efficiency improvements are going to be Concepts I sprinkle throughout this course and when we get to the more advanced section I'm going to break down exactly what's going on and why all the these gas efficiencies exist and what's going on behind the scenes for these gas efficiencies to occur it's a little bit in the weeds which is why I'm going to gloss over it right now so if it's confusing don't worry I wouldn't let these gas efficiencies be the thing that slow you down awesome so we have these two gas optimizations how else can we make this contract a little bit more gas efficient well one of the ways we can make this more gas efficient is by updating our requires right now with our require statement we actually have to store this sender is not an owner as a string array every single one of these characters in this error log needs to get stored individually this the string may not seem very big but it's a lot bigger than the alternative with what we can do as of 0.8.4 of solidity you can now actually do custom errors for our reverts we declare them at the top and then use ifs instead of require and then just add our revert statements this ends up saving a lot of gas since we just call the error code as opposed to calling the entire string associated with the error so for example with our require down here and with actually with all of our requires what we could do is instead of having this require we could create a custom error so at the top what we could do is we could say error not owner and you'll notice that this is actually outside of the contract here now what we can do is we can take this aor not owner scroll down into our only owner instead of doing a require we'll do an if statement we'll say if message. sender is not I owner then we're going to go ahead and revert with a not owner error this ends up saving us a lot of gas since we don't have to store and emit this long string here now in a lot of code today you'll still see require a lot of places because these these custom errors are pretty new ins solidity so you'll want to get used to writing it both ways I wouldn't be surprised if in the future the Syntax for some of these errors looks like this so that it's more readable but for now if you want to do a more gas efficient way than requires you can use something like this we could update all of our requires here for these custom errors but for now I'm going to leave both in just to show you the differences this revert keyword does the exact same thing that require does without the conditional beforehand so you can actually go ahead and and revert any transaction or any function call in the middle of the function call now let's look at one more way to improve this contract sometimes people will try to interact with a contract that takes ethereum or the native blockchain token without actually going through the required function calls that that are needed for example on a JavaScript evm here I could actually try to send this contract money without calling the fund function however if I were to do that what would happen would our fund function get triggered no no it wouldn't get triggered we wouldn't keep track of that fun we wouldn't have that person's information updated in this contract so if later on we want to give rewards or something we wouldn't know about those funders and this wouldn't be great cuz people would send our contract money without us ever knowing and we wouldn't be able to give them any credit or anything additionally maybe they called the wrong function by accident and they they weren't using metam mask and they weren't using a tool to tell them hey this transaction is likely going to fail so what can we do in this case what happens if someone sends this contract eth without calling the fund function right now if we were to send this fundme contract eth it would just go to the contract right and this contract just wouldn't keep track of those people but there's actually a way for when people send money to this contract or people call a function that doesn't exist for us to still trigger some code and now there are two special functions in solidity one is called receive and one is called the fallback now in solidity there are actually a number of special functions and two of these special functions are the receive special function and the fallback special function a contract can have at most one receive function declared using the receive external payable without the function keyword this function cannot have arguments cannot return anything and must have external visibility and a payable State mutability what does that actually mean and or look like well let's create a separate contract to go ahead and play with this so in here we're going to create a new file called fallback example. soul and in here we're going to add our basic pieces SPX license identifier MIT pragma solidity 0.8.7 and we'll do contract fallback example like so feel free to pause the video to catch up to this point once we create our fallback contract let's create a variable to go ahead and try to test this function we'll create a un 256 public result variable and let's create this receive function so we'll say receive it's going to be an external payable function we don't add the function keyword for receive since solidity knows that receive is a special function whenever we send ethereum or make a transaction to this contract now as long as there's no data associated with the transaction this receive function will get triggered what we can do in here now is we can say result equals 1 so let's go ahead and test this out on the JavaScript virtual machine we compile this so we're going to go ahead and compile this we'll go deploy it on the JavaScript virtual machine we're going to deploy our fallback example and we're going to see what result is initialized to since we haven't set anything for result result of course is initialized to zero but what if we were to send this contract some ethereum well receive would go ahead and be triggered here we can actually send this contract some ethereum directly by working with this low-level interactions bit here don't worry about what call data means for now just know that this area down here is a way we can send and work with different functions and we can add parameters to this transaction by going up here and adjusting the variables up here if we keep call data blank it'll be the same as if we were in met mask and just hitting send and then choosing this contract address again we can't actually use metamask since this is a virtual machine and not one of the networks that we're working with so if I do for example I change this value to one way and I keep everything blank and I go ahead and hit this transaction button which again is going to be the same as hitting this send button but only sending one way what do you think will happen well let's try it we can see in the log area that we did indeed send a transaction and if you look at the description here you can even see it says from so and so to fallback example. receive it looks like it called our receive function which should have updated our result to one so if we hit result now we can indeed see that result has been updated to the value of one well let's go ahead and delete this let's deploy this contract again and this time let's have value be zero does receive get trigger this time so let's pull this down let's hit transact let's leave the call data blank we'll leave value at zero so this will be the same as if we had sent zero ethereum to this contract let's sayit transact looks like that one through do you think result is going to be one or zero you thought one you were correct a receive function gets triggered anytime we send a transaction to this contract now and we don't specify a function and we keep the call data blank when working with any other contract like fundme for example when we call one of these functions we're actually just in this call data bit with certain data that points to one of these functions up here if we send a transaction and we add data to it we could actually call one of these functions now let's try this again let's delete the contract again we'll redeploy open this up result is currently zero receive like I said only is triggered if our call data to it is blank now this time if if I add some call data to this transaction you think receive will be triggered this time if we hit transact and remix we actually get a popup saying fallback function is not defined this is because whenever data is sent with a transaction solidity says oh well since you're sending data you're not looking for receive you're looking for some function so let me look for that function for you hm I don't see any function that matches the 0x0 so I'm going to look for your fallback function remix is smart enough to know that we don't have a fallback function the second special function in solidity is called the fallback function this is very similar to the receive function except for the fact that it can work even when data is sent along with transaction so our fallback will look something like this fallback external payable result equals 2 fallback is another one of these functions where we're not going to put the function selector because solidity is expecting this actually you're already familiar with one other special function we go back to our fundme our Constructor for example is another type of special function there's no function keyword solidity knows that this Constructor is immediately called when we deploy this contract so now we have our fallback function let's go ahead and compile this let's delete our old contract let's go ahead and deploy this new contract let's click here we hit result we do indeed see it's set to zero now if I add this 0x00 and I send this and I hit transact this is equivalent to calling our contract here without a valid function so our contract goes hm I don't recognize what you're trying to tell me here I'm going to refer you to our fallback now if we hit result we see that it's been updated to two if we take this away solidity will go hm it looks like you're trying to send some ethereum or call this contract without specifying what you want to do well I have a receive function so I'm just going to go ahead and forward you to that so if we call transact we hit result we see it updates back to one add some data hit transact we see it updates to two no data updates to one solidity by example.org has a wonderful little chart that we can use to figure out whether or not receive is going to get triggered or fallback is going to get triggered if it is empty and there's a receive function it'll call the receive function if it is data and there's no receive function it'll just go to the fallback function and if there's no fallback function it might just it might error out so this is a lot of really fantastic information here how can we apply this to our fundme contract here well what we can do now in our fundme is we can add these fallback and receive functions just in case somebody actually sends this contract money instead of calling the fund function correctly so what we can do is let's add a receive function so if somebody asks accidentally sends it money we can still process the transaction we'll say receive is going to be external payable and we'll just have the receive function call fund and we'll do the same thing with our fallback function we'll have fallback external payable we'll just have it automatically call fund now if somebody accidentally sends this money without calling our fund function it'll still automatically route them over to the fund function this means too that if somebody doesn't send us enough funding it'll that transaction will still get reverted so let's go ahead now and let's switch to rink B to test this on a real test net I'm on rink B and my metamask let's switch over to injected web 3 and we'll scroll down we'll choose our fundme contract and we'll go ahead and deploy this menam mask pops up I'm going to go ahead and confirm the transaction and we see our fundme contract here right now we can see the own we can see I'm the owner we can see minimum USD and we can see of course that it's a blank contract and there's nothing funded in here if we copy the address and then go to Rinky ether scan paste the address in we can see that there's no ether in here and the only transaction associated with this has been the contract creation we saw what happened before when we hit the fund function our contract was updated with a new balance and that fun was added to our array let's see what happens now if we just directly send this contract money without calling the fund function here if we did this right our receive function should pick it up and kick the transaction over to fund so let's copy this address we'll go to our metamask we'll hit send paste the address in here we do 0.02 eth again because this should be more than the minimum amount in USD we'll hit next I'll go ahead and confirm this and after a slight delay if we did this right well we should see this transaction having called the fund function here now that our transaction has gone through and after a brief delay and waiting for ether scan to update we do indeed see that our balance has updated to 0.02 which of course this makes sense and we see in the transactions list here we see that this actually went through as a as a transfer instead of us calling the fund function let's go ahead and remix and see if our funders was updated it looks like it was at the zeroth position of funders we have our address and if we take our address and pop it into address to amount funded we can see exactly how much we had funded this means that since we added this receive function in here we automatically had to call our fund function up here so awesome work we were able to add a receive function to help people who accidentally call the wrong function or accidentally send this contract money instead of correctly calling the fund function now if they had directly called the fund function it would have cost them a little bit less gas but at least this time they're going to get credit and added to our funders array for having sent our funding contract money Okie doie as before with simple storage there is a small bug with the ZK sync plugin which I'm going to walk you through very quickly before I pass back over to Patrick who's going to walk you through step by step what the changes you need to do here are so I have made some small modifications for ZK sync to this fundme contract but Patrick is going to walk through that in a second I just want to note that if you were to compile the fundme contract after making all the modifications that Patrick suggested you would see in the deploy tab there are no contracts ready for deployment yet and that is because for the ZK sync plugin you need to make sure that your contracts are inside a contracts folder they're not just free floating here so if we just create a new folder called contracts and then we Chuck our contract inside the contracts folder and then we went back to ZK sync and hit compile fundme then you would see that the smart contract has compiled successfully and you can go ahead and deploy it so just make sure that all of your contracts are indeed inside of a contracts folder now I'll pass back to Patrick he's going to walk you through some of the changes need to be made to your smart contract before you do all of this so just remember put your smart contract inside of a contracts folder for the ZK sync plugin all right so now we're going to take this code base and we're actually going to deploy it to ZK sync similar to what we did with simple storage we're going to deploy it to the ZK sync sapoia test net now like I've always been saying deploying two test Nets can often be very fickle so if you do not want to follow along with me here feel free to not follow along with me but if you want to try to do this as well feel free to do so now the reason in particular I want to show you deploying this to the ZK sync sepolia test net is because I want to show you something in particular down here where we have the get version we're using this specific price feed address that we got from the chain link documentation this price feed address is specific for the sapoia chain and every single different chain including the different l2s are going to have a different address here so if we want to use ZK sync we have to use the ZK in sapoia test address so if we copy this address and we go back to the chain link documentation now the docs are probably going to look very different by the time you actually start looking at them because they change the docs pretty frequently so an easy way to get started here is maybe go to docs. chain. link and then over either on developer Hub or overview go to data feeds and this is where you can see most of what you need in the getting started section of the documentation so now that we're at the docs we're going to go ahead we're going to go back to the feeds addresses price feed addresses here and we're going to scroll down and once again we can see in sapoia testnet we can see the ethusd address down here on the sapoia test net since we want to deploy to ZK sync now what we're going to do is we're going to scroll up and this and in this networks section we're going to look for ZK sync which is right here we're going to scroll down we can see we have the ZK sync era main net list of addresses we're going to scroll right on past that and we're going to go to the ZK sync sapoia test net where we see ethusd right here and we're going to go ahead and copy that if we want we can even open this up in a new tab we can go to the contract we can select read and we can scroll down maybe to latest answer we'll hit query and we'll be able to see the latest price of ethereum on the sapoia test net remember this is just a test net so it's not updated very often so now what we want to do then is right in get version we're actually going to change this address paste in that new ZK sync sapoia address once we have the new address in here there's a couple other tweaks that we need to make and I have an issue associated with the ZK sync plugin here so that this becomes easier in the future but right now if we were to go ahead and try to go to the ZK sync compiler here and compile this you're going to get this long error saying solidity compilation failed right and one of the reasons is first we need to have we need to update our contract to the ZK silk latest version which is going to be 0.824 and we have to do that with our price converter we need to update that to 0.824 as well but additionally right now the zkn compiler has a hard time working with libraries so what we can do instead is we can just copy all of this Library code come over to fundme delete this import paste the library code in and we can first check it works with solidity then we can come back to the ZK sync compiler and compile it here and then it should update accordingly so I'm going to go ahead and I'm going to deploy this and I'm going to verify this as well just to show you what it looks like on the ZK sync test net like I said you don't have to actually do this you can just go ahead and follow along although my mistake we both need to update the version here and we need to update it in our library as well if we didn't do this it would be pointing to an address that doesn't necessarily exist on the ZK sync testet and this would fail we wouldn't get the correct price conversions so let's go ahead let's deploy and verify this and if you want to go ahead and do this as well feel free to do so so first we're going to need to update our environment to work with a wallet if you haven't already going to go select wallet down here normally a connect button will come up I've already connected so mine looks like this if you're not already connected you go ahead you'll hit connect wallet you'll select metamask here and then your metamask will pop up or if not if it's already connected it'll look something like this so what we'll want to do now is switch from Price converter to fundme remember not to do price converter you will get an error pull up the terminal here and then we'll select deploy and verify or just deploy per usual metamask will pop up now you notice a a little bit different from seoa We're actually just signing as opposed to signing and sending here that's because with ZK sync we actually have a slightly different deployment process but we'll learn about that in the future we'll go ahead and we'll sign this so it looks like our verification failed that's not a big deal what's important is that the contract has been deployed so what we can do now is scroll on down and we can check to see the blue buttons to see if this at least deployed correctly we select minimum USD we get that if we get select get version we do indeed get four which means this contract has been deployed to the correct chain so it didn't verify correctly but that's not a big deal because we can still interact with it as such and if you did go ahead and deploy this to zika sync you should be incredibly proud of yourself because that's incredibly exciting and feel free to play around with this as you see fit you'll notice the amount of eth I have actually did go down even though in my activity it doesn't show that I sent a transaction huh that's really odd for now just ignore that and we'll learn in the future why that happened and how that happened but for now if you did if you did this congratulations on deploying this to ZK sync that's incredibly exciting we've even learned some Advanced sections of solidity and this is going to be the last time that we start our projects in remix we're going to be moving over to a code editor now where we can get even more advanced with our solidity and our setup for the most part you've gone over the vast majority of solidity Basics there are a number of things that we still haven't learned yet and the reason we haven't gone into them is because they get more advanced and understanding the real use doesn't really make too much sense until a little bit later some of the things that we're going to go over are enums events try catch function selectors ABI encoding hashing and then Ule SL and then u/ assembly however if you've gotten this far you probably can read most solidity code and understand what's going on which is absolutely fantastic so you should give yourself a huge round of applause for getting this far and doing this let's do a quick summary of this more advanced section and make sure we understand what we learned in solidity there are a couple special functions some of them are receive fallback and Constructor these functions don't need to have the function keyword and instead can just be called like so receive and fallback are two very special functions if data is sent with a transaction and no function was specified the transaction will default to the fallback function if that fallback function exists if data is empty and there's a receive function it'll call the receive function there are a couple of keywords that can help us save gas in the long run some of those keywords are going to be constant and immutable constant and immutable are for variables that can only be declared and updated once once we say minimum USD is 50 * 1 E18 this minimum USD can never be changed again and this helps us save gas immutable can also save gas similar to constant however immutable variables can be declared one time in the Constructor once an immutable variable is declared it can't be changed later on in fact if we even tried to update an immutable variable or a constant variable and we compiled our compiler would give us an error saying can't write to immutable here or if we tried to change a constant variable our compiler would say hey you can't assigned to a constant variable sorry in remix if we want to send ether to a contract that's on the JavaScript virtual machine we can deploy that contract and then in the contract we can just hit the transact button without any call data and update the value that we send with the transaction if call data is blank it'll trigger a receive function if it exists but if there's data that doesn't specify any of the other functions it'll trigger the fallback function all right my codee's done time to ship it free box you dog water zero earn Z PR in the age of AI debugging and getting into software engineering has never been easier here are the exact six steps you need to take to unblock yourself from any software engineering era you'll ever get number one Tinker try to pinpoint your error you can usually use an AI buddy to help you out here pinpointing your error will potentially solve your problem before even going to an AI and allow you to craft a better question to an AI once you pinpointed the issue you can move to step two which is ask your AI you can use chat gbt find Bing's AI or if you want to give wrong answers Google's barred there's six principles to prompt engineering so that you can get the best out of your AI write clear and Specific Instructions give as much context as possible use delimiters to clearly indicate distinct parts of the input and especially look out for something called hallucinations hallucinations are when your AI gives you an output that it thinks is right but it's completely wrong for example if I write about writing solidity and variant tests in Foundry disgraces Us by saying we have to mpm install it from open Zeppelin these can be tough to spot but once you try it out you'll see it doesn't work and finally you want to understand the limitations of the AI you're working with and iterate constantly large learning language models are trained on human conversations so you can interact with them as if you're having a conversation but it's important to know the limitations of these AIS as most AIS have a limit on how many tokens or words they can keep in context at one time AI is trained off human language so if you're good at asking other humans questions you'll probably be good at asking robots questions too asking questions is a skill so keep practicing I've got a link in the description to learn. deeplearning.ai which is a free course to help software Engineers be better prompt Engineers now when the AIS can't help you you'll have to go back to the old standbys actually doing work yourself and one of the first pieces of work is reading the documentation you probably should have done this already however we can still still use chat gbt cuz a strategy that I constantly use is I'll copy paste sections of the documentation add chat gbts context and say some like the above are the docs for Tool X based on those docs how do I do y so Google might be crying because chat GPT is eating its lunch but Google still has what AI doesn't have the entire internet previously anytime I ran into an issue I prayed someone else to run into it before I made a post on it so I could Google search that exact issue there's a new tool called fine that combines web search with AI as it does a web search and it crawls through all the data of the sites reads them all and then gives you an answer based off of what it reads five asking a forum sometimes the information just isn't out there and we need to ask human beings we always want to ask our question on a webbed index Forum like stack exchange stack Overflow pirana or Reddit this way webcrawlers and more likely AIS can scrape the data from these sites and learn from us that way the next time we have this question we can get our answers quickly asking on Discord and Twitter are because your knowledge will get lost to the unsearchable hell hole of conversations that Discord is and webcrawlers don't index them super secret alpha is to ask a question on stack exchange and then post your stack exchange link to Discord you should 100% always ask your questions informat them with markdown and if you're not sure how to do markdown you can ask CHT to help you format your questions in markdown ask on the support GitHub or forum is the tool you're working on open source awesome ask a well formatted question on their git page not open source never use that tool again this is how we improve our tools by creating issues engaging with each other and even taking on issues and contributing to the open source code and then finally iterate do all these same steps over again and as always keep hopping through the code and until next time stay riveting my fellow block [Music] chainers all right fantastic so now we know a little bit more about the different tools and techniques we can use when we do in fact get stuck we can use something like chat TBT forums to ask questions we obviously want a Google Search and especially for this course you definitely want to make sure you use the discussions Channel but I wanted to give you some very specific tips about working with this course number one limit your self triaging to 15 or 20 minutes for example if we're trying to compile our price converter doou and maybe we forgot to add the address in here right and we're going ahead and compile and we're getting this error this is exactly one argument expected for explicit type conversion now this should be pretty obvious what the error is hey it's expecting one argument and we obviously just remove that argument but maybe you're having a really hard time and you're trying all this different stuff and you can't seem to figure it out limit yourself to 15 or 20 minutes we do not want to be messing around for so long that we can't figure something out right something like this would be very easy for us to compile copy this error go to chat gbt and say something like hey I'm getting an error compiling my solidity here is the error do three back ticks paste it in here like that three back ticks is markdown and like we said in the video we want to use delimiters to clearly identify what is Code versus what is not oops and I hit and I hit enter whoops the daisy we're actually going to stop generating and we're going to copy paste the question again now we're going to say here is my solidity it's wrong then we'll copy the solidity line once again three back ticks we'll say solidity here we'll paste it in three back tis to end it hit enter and it'll probably give us the answer here and turn off the error message suggests that you need to provide an address when using explicit type conversion so we go ah okay whoops we need to actually add an address in here it gives us an example and we can go back to our code and you know paste that address in here and be good to go so limit self triage to 15 20 minutes that's going to be the first tip number two don't be afraid to ask AI but don't SK skip learning the purpose of this course is for you to be able to learn everything here AI is going to get things wrong and it's only the people who actually have learned what's going on under the hood who are going to be able to call out when AI gets something wrong when AI gets something wrong it does something called hallucinate and we talked a little bit about that in that AI video we just watched so hallucinations are when the AI makes something up that it thinks is right but it's completely wrong and that's something we absolutely need to watch out for when we're coding and when we're learning a perfect example of this is with Foundry which is a tool we're about to learn very soon in order for us to install Foundry we actually need to run this Command right get founder. sh it's the first thing that it tells us to do at the time of recording chat gbt has not been trained on The Foundry tool so if I ask it a question like I'd like to initialize a Foundry project with solidity can you show me how to do that and we'll let enter so the first sentence out the gate is wrong it's not aware of Foundry so it tried to guess what Foundry was and it got it wrong it is not a rust paced framework for building blockchains at all and it is directly related to solidity so it's really important that we use AI to augment our learning but we don't skip over the learning with AI it's really good to bounce questions good ideas off of but in order for us to be even able to recognize when Foundry is hallucinating and making stuff up we need to have that knowledge oursel step three of course use the forms web3 education. deev will have a place for you to ask questions but in the meantime definitely be sure to use The Foundry full course discussions use this to your advantage and use this to help other people out who have questions this is a community project we're all going to be helping each other out learning number three Google the exact error if AI doesn't know the forums aren't know Google the exact error Maybe somebody else has come across this eror previously asked the question online and you can just Google it and then of course post your question in stack exchange or piranha and like we said in that AI video you want to use markdown and format your questions as best as possible so if you're unfamiliar with how to use markdown if you're unfamiliar with how to format your questions again please be sure to ask chat GPT or some other AI how to best format your question you can even simply say ask chat PT could you give me an example of a well formatted stack overflow question with Cod or code and it'll actually give us a really good formatted question so it gives us the question it formats the code for us it's using this with the three back ticks that I showed you in order to get this code block here it's using three back ticks and it's being very verbose in giving all the details of the question so be sure to ask questions like chbt awesome again let's say we're in here compile get this error exactly one argument expected for explicit type conversion if we copy this error go to Google we paste just the error in we'll remove this our specific code looks like the first thing we get in Google is actually contract inheritance and we can see that this is actually exactly the error that we're getting looks like this does actually explain the answer but it's a little bit confusing to understand here so maybe you would copy paste this into chat gpts context right there's a lot of creative ways you can approach debugging some of your issues obviously when you're out in the wild and you're actually building things yourself obviously the education site and the discussions channel of the giup repo the people in these aren't going to have context for the new creative thing that you're working on so I want you to get used to doing that methodology that we're teaching here right asking your AI buddy if your AI buddy doesn't know Googling asking questions on stack exchange ethereum asking questions on piranha piran is arguably better because you're asking your questions in a decentralized location as opposed to a centralized server but I definitely want you to practice asking questions and go to piran go to stack exchange make accounts for these so that when you do run into an issue because you will you'll know where to post them highly encourage you to pause and post a question on one of these forms right now just so that you get used to it just so that you get out of your shell and you're going to suck at asking questions in the beginning and that's okay you will get better at asking questions as you continue with this course asking good questions is a skill in itself and if you learn how to ask very good questions that's the secret sauce to being amazing at AI prompting as well now the final step in all of this is actually going to be posting an issue on GitHub sgit a surprisingly incredibly important part of being a software engineer and being a developer in web3 is interacting with the community the vast majority of these tools that we're working with are going to be something called open source meaning that the code associated with them is actually available for anybody to view this tool Foundry that we're going to be working with is one such example and if you see it has this issues tab where there's just a ton of issues people are posting while using this tool this is how code is able to be improved and moved forward all this code is public for people to use and work with and if there's a question that isn't answered you can post here and tell the developers of this tool hey I'm running into an issue maybe we should make a project Improvement I would say be very respectful with the way that you make issues you definitely want to do some searching on issues to make sure that nobody else has asked the question that you're working with and be to sure to use these other resources first like panha like stack exchange but in the future once you leave this SC it's going to be incredibly important for you to participate in the ecosystem by making issues by making poll requests and actually improving some of the tools that we're going to be working with yourself even ethereum has a GitHub and if there's any improvements that you want to make you can add an EIP to actually improve ethereum we'll talk about EIP some more later you can improve some of the clients that ethereum runs so interacting with each other is incredibly important and in fact if you don't have a GitHub we are going to get you set up with a GitHub right now because GitHub is a platform that most developers use to share code and write code and interact with code in between each other so if you don't have a GitHub let's sign up right now and we're going to use the GitHub to create our own portfolios of all the different cool coding projects that we've created this way when you go to apply for a job you can say hey go look at my GitHub I've got all these really cool projects so we're going to make you a GitHub right now if you don't have an email you're going to need an email I made a burner account just for this video and I'm also going to walk you through formatting a question and I know I'm belaboring the point here but I really really want to stress the importance of formatting these questions really well so we're actually going to show a clip from my past video so we're going to be using the full blockchain cility course JS but again for this video just be sure to use the GitHub repo associated with this course and not that other old GitHub repo all right let's watch this video in fact if you haven't already let's sign up for GitHub right now and let me walk you through formatting one of these questions because the better you format your questions the better chance you have of actually getting the answer and remember when asking questions on these forums when asking questions in these discussion communities people answer these questions out of the goodness of their heart right so if you don't get a response there's a chance that maybe nobody knows maybe it's your question isn't formatted very well and Etc so we're going to learn how to ask really good questions here and if you're new to blockchain do not skip this section okay this is going to be that piece that's going to give you the superpower to unblock yourself from any coding issue you run into so don't skip this part be sure to follow along okay so if you don't have a GitHub already you do need an email to get started so I'm going to go ahead and sign in I made a burner account just for this video so what we're going to do we're going to go ahead and sign up up GitHub enter your email and we hit create account they're going to send us an email so we're going to come back to our email going to get our launch code here paste it in answer a little bit of information we're going to choose the free version and fantastic we've now created a GitHub profile awesome so now we've created a GitHub so I'm actually using a GitHub that I used in my last course so that's why I have all these repositories over here now in order to create a new discussion over The Foundry full course f23 let's go over to the discussions tab we'll hit new discussion and we'll hit General and I'll say something like test discussion be like feel free to say hello here start discussion now I'm going to show you a question that's formatted poorly and I want you to never ever ever ask a question like this and if you see somebody ask a question like this please help them format their question correctly hey why my code not be good and then let's just have it be issue like this right what's wrong wrong with this okay well why my code not be good obviously isn't clear what's going on the code isn't formatted well and even an AI would have a hard time answering this so let's fix this to be a little bit better as we know we want to copy the exact ER we're getting so we'll say We'll copy the error we'll go back we'll say I am receiving this error we'll do the three little back ticks paste our error right in here like that actually let's be even more Expos I'm receiving this error while compiling here's my code three betics we'll put solidity here copy the whole line that is erroring paste it in here and someone help me figure out what the issue is right and you see how this is much much better right we have these two blocks that pop up because we did the back ticks and the secret is that this is going to get you a much better answer from an AI as well right if we edit this we can copy the whole thing of markdown go over to chat jbt paste it in zoom out a little bit and we're going to get it actually an answer hey you're receiving this air because you're trying to create instance of aggregator V in Phase without providing the necessary argument blah blah blah oh and it actually gives an enough version of that but it helps us out here so ask format your questions correctly you will get better answers from both AIS and humans and I know I'm spending a long time on this but I really really need you to understand that the secret to prompt engineering is actually just being able to ask better formatted questions with human beings and it's better for interacting with human beings as well now the other thing that I did really well here was I only posted the relevant code to the error that I was getting what we see a lot of people do is they just copy paste their entire code base into here this is not very helpful as it's going to make somebody who wants to help you their job a lot harder if they have to read your entire code base right we reply here this is so much more reading for them to do it's going to take them a lot longer and they might not actually read it and we didn't actually highlight this with the btics and it goes the same thing with AI if you give your AI too much text it can't read all of the text because again some of these AIS have limitations in how much text they can read so it's the exact same thing with working with human beings so feel free to take some time to either in chat BT or whatever AI you're using or in this test discussion forum to post some well-formatted questions and remember you can use AI to help you get those formatted questions in markdown be sure to ask chat WBT to give you the output in markdown so if you haven't worked with markdown before that's okay you'll learn as you go along but one of the biggest differences especially when working with markdown that's going to make your code so much more readable and I 100% need you to always do this whenever you ask questions is you see how this got like some syntax highlighting in this above question well if we go click edit again we can actually see why up here we did those three back ticks and then we type the word solidity when you do these three back ticks in your questions if you type the word or you type the language next to the first three back ticks it'll actually add some formatting to make it more readable so if we scroll down to this poorly formatted question you can see that this is just all white and like impossible to read it would be at least slightly better if we hit edit and next to these three back ticks we wrote solidity if this was like Java code or python code we could write python or Java or whatever but since this is solidity we'll write solidity I'll hit update and you can see that it is substantially nicer and it is much more readable now so even though this is still a bad question obviously because we just copy pasted all of our code it's at least much more readable so anytime you do a code block like this of any of your code absolutely 100% be sure to do the three back ticks and then the language of the block of code so just remember this there are no bad questions but there are poorly formatted questions make your questions well formatted for both human beings and for AI and then most importantly be sure to join these forums and like I've said 100 times interact with these people interact and help and give back the more people that use and are good at the tool that you're working with the more likely that they're going to help you sometime in the future and this is how I've met so many people in the industry is just giving back and interacting with other people so whenever you ask a question especially in the beginning because in the beginning you're going to have more questions than not be sure to at least try to go back and answer a question think of it as question and answer debt every time you answer a question make a little mental note and say ah in the future I need to at least try to answer one of somebody else's questions this is how we grow and move so much faster now this next piece that I'm going to show you is actually outside of this course but it's a resource that I wanted to show you in case after this course is done you want more resources to learn about ethereum and learn about the EVN it's with my good friend Austin who's going to show you speedrun ethereum and definitely something you might want to check out after taking this course what's up I'm Austin Griffith happy bow tie Friday I show you the best way to get started building on ethereum is speedrun [Music] ethereum.org and you'll learn about Randomness on chain and where it works and where it doesn't and what you can do about that you learn about a DEX and what a hyper structure is and how people can use liquidity to swap you'll learn about State Channel and scalability and sign messages and multisig wallets and account abstraction and SVG nfts lots of fun stuff along the way like I said not just the how but the why go to speedrun ethereum.org and get started today uh it'll have you do a quick video uh and then it says to use scaffold e to start tinkering I want to show you how to do that first of all all this stuff is open source uh it's all ungated and open source just get in and get get in get learning okay but the scaffold e thing uh scaffold e is a great way to Tinker uh with solidity and kind of get your your your bearings right so let me show scaffold 2 just for a second if we zoom in uh I've already kind of uh gone through the whole read me and installed everything I want to show this right here here's a smart contract and I have my front end that's uh adapting to the smart contract and so uh when in speedrun ethereum it tells you to Tinker with each one of these Concepts let's just go look at mappings or strs or modifiers let's just go look at a mapping and let's grab a mapping right and let's copy and paste it right into our smart contract so something called my map I don't even know what it is right and then we yarn deploy and we'll see that my map show up over here and this is kind of the feedback loop I want you to get into where you can grab grab some stuff from solidity by example paste it into your smart contract deploy it locally and then Tinker with it there's my my map let's see what vitalic bance is in my map it's zero oh okay so check out speedrun ethereum check out scaffold eth get started building cool things on ethereum today happy bow tie Friday hearts hearts hearts see you you've now completed the solidity fundamentals this is incredibly exciting you know a lot of the basics of solidity how to deploy smart contracts how to work with smart contracts and a lot of the fundamental skills it takes to become a smart contract developer or security researcher but we've really just scratched the surface next up is the introduction to Foundry course which is a smart contract framework that's going to accelerate our development prowess allow us to make much safer much better tests for our smart contracts allow us to deploy them programmatically and do a lot of really powerful things for us developers so huge congratulations on finishing sity Basics as always now is a great time to get some ice cream go for a walk or maybe go to the gym take that break and I'm looking forward to seeing you at the start of Foundry welcome to the foundaries fundamental course where you are going to learn about Foundry the smart contract framework once again my my name is Patrick Collins and I will be the lead instructor for you here let's get froggy now the reason I especially wanted to show you all of these debugging things right now is because we are about to move off of remix remix has been this phenomenal IDE or this phenomenal integrated development environment that allows us to quickly try things and quickly deploy things but we're actually going to move off of remix to a more professional setup and we're going to be using a modern set of tools that most of the rest of the development Community also works with and I'm going to tell you this right now often installing these new tools and often just getting your local development environment set up not using remix or not using what's called a cloud IDE can often be the actually most difficult step in this whole process so I want you to be absolutely Vigilant in using all of the resources that I just showed you using the chat using chat GPT using piran using stack exchange eth using web3 education Dev once we get this up and live be sure to use these tools and don't let installing these slow you down because in my mind installing these can be the hardest part of this whole course and it's okay things might not work the first time and that's okay just be sure to ask questions and be very specific with the errors that you're seeing and installing these things that's what we're going to learn how to do right now so remix is a phenomenal tool but now we're going to move over to this more professional setup called Foundry Foundry is one of the most popular smart contract development Frameworks similar to hardhead or brownie if you're familiar with those and it's known specifically for its speed Foundry is easily the fastest to work with smart contract development framework one of the unique aspects about Foundry is that whereas hard hat is Javascript based brownie is python based Foundry is completely solidity based so we don't have to learn any other programming languages other than solidity to work with Foundry and similar to everything that we've been doing so far all all of the code for all of our Foundry products are going to be in the GitHub repo associated with this course however the documentation for Foundry I think is also phenomenal so be sure to use this as you code along and something very interesting that I really love to do most of these pages are pretty small so even if your AI isn't trained off of Foundry which as a recording it's not what we can do is something called context injection when we have issues so we can copy the entire page of documentation we you can say I'd like to start I'd like to install Foundry here are the documentations for installation how can I do it do the three back ticks paste the whole thing in there and by giving our AIS the documentation for working with Foundry it's actually going to give us outputs to install Foundry so this is a methodology you'll see me use from time to time this context injection you can find more information in the GitHub repo once again associated with this course on installation and setup Mac OS and this should be Linux and then we have some Windows setup stuff down here we're going to go over how to set up all the important things for this course so be sure to use this as a reference now a great question you might be asking is well what's even the purpose of Foundry why do we need to use this other tool remix is working great well in remix you notice that we did a lot of stuff manually like I came in here I had to go to compile maybe I wanted to test something out I would go deploy it uh I got to put a price feed in here price feed in here deploy okay does the get version work Uh something's wrong with my get version okay my o i owner works okay minimum USD works oh crap I got to go make some little change here you know maybe I want get version to actually return you know 7 + 2 or 7 + 1 now I got to go you know delete this I got to go redeploy I got to go click this I got to go down I got to click ever and then if I have a 100 things that I change testing all of this is going to take a really long time and anytime you do something anytime us as human beings changes our code in some way there's a chance that we break something and remember these smart contracts are immutable so if we break something if we mess something up that's really bad because that mess up will be permanent on the blockchain so we want a framework that helps us deploy our smart contracts test our smart contracts and interact with them in a much more programmatic way rather than we having to manually click around right if I changed 10 functions and I wanted to test they all work I would have to go click 10 buttons that's ridiculous in Foundry we can do all of that in one command or one button so that's why we're going to be using Foundry here and I'm so excited for you to be using this Foundry tool because like I said it's the fastest smart contract development framework out there right now but additionally it's also the framework of choice for smart contract security engineers and Auditors and I expect more and more projects in the future to be built in Foundry so incredibly excited for you here now for the rest of the course I'm going to be using a code editor called Visual Studio code this is one of the most powerful code editors on the planet and if you've already got it set up feel free to go ahead and skip this part you'll often hear people refer to this as VSS code or Visual Studio code or just Visual Studio however it's important to not that that Visual Studio code this is different than Visual Studio which you might see look like this so visual studio code is what you want not Visual Studio Visual Studio is a different application makes sure you're on Visual Studio code now if you choose so and you're a total Hardo you can absolutely work just with your terminal or just with Powershell or just with whatever coding environment that you want like atom or Sublime however for us we're going to be working with Visual Studio code and I'm going to be going through setting up visual studio code the way that I like to set it up you can absolutely set it up whatever way that you feel comfortable now we're going to go through three different installation processes and pick the one that's most appropriate for you the first one is going to be for mac and Linux users the second one is going to be for Windows users and then our third one is going to be a last ditch effort if for whatever reason you can't get Windows or Linux or the Mac instructions to work we're going to use a gitpod installation now I highly highly recommend that you try to get everything working locally without using gitpod however if for whatever reason you can't get those installation pieces to work we will have get instructions for all of the repos that we work with here but to get started we'll start with the mac and Linux installation instructions the first thing you're going to want to do is download the Mac or if you're working with Linux download the Linux installation of Visual Studio code once you have it installed it'll look a little something like this and if it's a fresh installation it'll even give you some tips and tools to actually get started if you've never worked with Visual Studio code before I highly recommend going through any get started or getting instructions tips that come with opening Visual Studio code additionally we have a visual studio code crash course in the GitHub repo associated with this course now one of the awesome things about Visual Studio code is it has this thing called terminals which are commandline prompts that allow us to run scripts basically it's where we're going to be running all of our code the way we can open up the terminal is we can go ahead and hit terminal and select new terminal and you'll get something like this now you might have bash or zch or some other type of shell the type that you have doesn't really matter because on Mac and Linux it's going to be linux-based and like I said sometimes installing this can be the hardest part of this entire course so so don't get discouraged and please use stack overflow stack exchange ethereum and the GitHub repo to move past any issues run into now if you're on Mac or Linux you can actually hit control back tick to actually toggle your terminal mode this will pull the terminal up and down for you getting familiar with keyboard shortcuts will actually make your life a lot easier cuz you'll be able to move around Visual Studio code much more effectively we have a link to a list of keyboard shortcuts additionally in the GitHub repository associated with this section as we move along I'll give tip on different keyboard shortcuts that you can optionally use otherwise you can just go ahead and click as well you can click the trash can to delete the terminal go back up terminal new terminal to pop it back up now the next thing that we're going to need a little bit later we're not going to need it for this section but it's good to install it now is going to be git we will have links to the installation instructions in the GitHub repository installing git on Linux you're going to use one of these two commands and on Mac OS if you just type git on the command line it should go ahead and prompt you to install it so if we're back in our command line and we just type get it should prompt you to go ahead and install it and if you do get- Dash version you should get something that looks like this you can also use a Mac OS G installer by clicking this link here and running through the installation process all right now that you have git and visual studio code installed we can continue on to the next section awesome if you're not planning on using Windows or git pod feel free to skip the next two sections and for this Windows setup we're going to be learning about a tool called WSL and to introduce that to us we have my friend basili who has done amazing work helping me on some of my past courses and he's going to be helping us here today so take it away this tutorial is going to be useful for any Windows version from Windows 10 and above let's get started by installing or code editor in this case Visual Studio code so let's type BS code on the browser and hit enter select or version for Windows select the destination and click save and installation process is going to be the same as any other proc program so let's select an accept the agreement click next add code to the P create a desktop icon next and install this shouldn't take a lot and this is how the editor is going to look like the first time we install it we can customize the theme create shortcuts and sync with another devices and if you want to go deep into Visual Studio code well I suggest you to pause the video for a moment and go through all these steps one by one now we could 100% go forward and install the rest of our Tools in a Windows environment but basili is actually going to explain to us that the windows environment isn't really actually the best way and the best place to do our installations Microsoft has definitely increased their support for developers in the recent years but when it comes to Smart contract development there is a better option to consider using WSL the windows subsystem for Linux trust me is a Game Changer you see a smart contract development often involves working with tools and utilities that are commonly found on Unix based environments while Windows has come a long way in accommodating developers there can still be some challenges when it comes to ruing certain command line tools and setting up the right development environment not mentioning that if you want your code to run on any machine using a units based system Mac and Linux is better for your developer needs here is where WSL shines by installing a Linux distribution through WSL you can access to a full-fledged Unix light console right on your Windows machine and don't worry you don't need to be a hacker or wear a hoodie to make it happen is actually quite simple so let's do it for that let's open the windows terminal this is a pre-installed application on Windows 11 and something you can easily install through the Microsoft store on Windows 10 just type terminal and here you're are going to have the windows one so let's install WSL by typing WSL minus Min install hit enter is going to trigger us a admin operation and installation is going to start and here we just have to wait until the process finishes once the process is done this will require you to reboot your operating system so I see you on a second once rebooted this is going to automatically open this terminal and the installation process is going to proceed now you have to input a new Unix username for me is going to be chare and then you have to set up your password don't worry the password is always hidden on Linux operating systems and as this as that we already have a operating Linux terminal inside or Windows machine so we can now close this now if we open a new instance on the Windows terminal we click here on this drop- down arrow we can have now this auntu shell on which we are going to inst all the development requirements we are going to use to R the course so the next step is to make Visual Studio code compatible with WSL so let's do that let's go to the extensions tab let's search for remote development and install all these extensions this is going to automatically install the compatibility to connect or Visual Studio code with WSL and as you can see over here I have a new econ called open a remote window if I click here I can directly connect to WSL however there is a easy way to do this let's close Visual Studio code and on the Linux terminal let's just create a new folder for example Mader solidity course let's move to the that folder and now let's open Visual Studio code inside this folder just type code dot hit enter this is going to install the latest server for w cell on Visual Studio code and once this is done we are going to have a new instance of Visual Studio code but using WSL let's just trust the outs and as you can see here I'm getting this WSL Ubuntu Banner over here and it's because I already connected this with the Linux instance so you have two options from now on you can start using just the windows terminal to execute all the things we are going to need or you can use the integrated terminal which comes with Visual Studio code just go to terminal new terminal and now we are going to have a terminal using the exact same W cell instance so we can start using pseudo commands for example pseudo AP the update and this is going to work properly now just take something in consideration maybe you are going to develop all your projects on a folder called development inside your documents on Windows and you can do so however if you take a look to the Linux terminal with ls command as you can see here you are going to have just access to the local files and folders inside of the WSL instance and I highly recommend you to do that because of course you can do something like typing the address of your local development folders and use the projects from here but the communication from the WSL console and the local Windows files are actually quite slow so I prefer just to keep Simple and use all the folders inside W cell remember that you have to just manage simple commands such as LS to know all the folders on the current directory and CD to navigate through them now if you go back to your vs code and you hit terminal new terminal and open up a terminal we're going to want to then install git we're not going to use git for this lesson however we will definitely be using it in the future to see if git is installed type g-- version sometimes Linux will automatically come with get installed and you'll see something output like this however if you are the ones who decided to keep using po shell and just Windows instead of WSL don't forget to go to the official git page and install it for Windows the process is as same as we did before pretty standard just the common sequence of clicking next and of course please do read the license agreement and now if you've made it this far you should be able to follow along with the mac and Linux instructions as if you're running on a Mac and a Linux even though you're running on a Windows just be sure that whenever you're in your vs code you take a look at the bottom left and make sure you're on WSL yuntu like I said before if you want to run in Powershell or in a Windows environment you're more than free to do so but like I said if you've made it this far huge congratulations awesome work and then finally our last setup is going to be using a tool called git pod starting from lesson 5 the lesson that we're on right now ether's JS simple storage all of our code repos are going to come with a button in the repo scroll down they'll come with this open in git pod button now git pod is a cloud development environment where you can actually run your code on a remote server it's kind of similar to remix IDE but it allows you to run Visual Studio code in the browser or connected to another server this is good because then you don't have to do any installation on anything since all the tools that you want to use are just going to be running on this remote server this has its downsides though obviously since you'll only be able to code if git pod is up and working for you additionally when it comes to private Keys you absolutely do not want to run any code with a private key that has real money in it on gitpod why well once again since you're running your scripts on a remote server those servers have access to your private keys but since you've pinky promised that for this course you're not going to be using a metamask or a private key with actual money in it it should be fine the other downside is that these often cost money to use and G pod isn't free but it's an option if you absolutely cannot get any of the installation working so if you go ahead and you hit this opening git pod button you'll get a welcome to git pod showing up uh we're going to go ahead and continue with GitHub since you've signed up for GitHub here you want to go ahead and authorize GitHub and it'll go ahead and start creating this workspace for you and you'll notice it looks exactly like Visual Studio code since I opened the repo up in git pod it came with all the code and you can even open this workspace up in vs code desktop so this is might be a little bit confusing but basically you can run off of git pod using your local Visual Studio code and if you see gitpod here that's that's how you know that you're running off of git pod if you see this popup do you want to open this workspace in vs code desktop you can hit open and it'll ask you if you want to open up visual studio code which I'm going to go ahead and hit yes and you'll get something that looks like this on your Visual Studio code it'll tell you that it wants to install the gitpod extension and then open that git pod URL so you can go ahead and install it reload window and open and it's going to go ahead and start connecting to our the git pod workspace and this is going to be the same as running git pod in the browser here or you can also do it manually by hitting the git pod in the bottom left and then type in open in vs code and then you should be able to run it in your Visual Studio code for now I'm going to recommend that if you're using gitpod just stay in the browser just so that you know okay I am running this on a remote server and just as a reminder for you that you're not actually locally developing and hopefully this will be a trigger to not actually put any special private keys or anything like that but you can make workspaces you can make new folders and you should be able to run all the commands on here as if you were running locally with Visual Studio code to open up the terminal you can hit this little bar in the top left go to terminal new terminal or use control Tilda exact same as Mac OS and Linux keyboard shortcuts to create create a new folder we can change directory CD do dot mkdir new folder mkd makes make directory called new folder and then we're going to change our directory into new folder and hit enter and now we're in that new folder for each section you can either open up the entire source code right into gitpod or you can create a new folder for each section yourself and start from blank and then you would just type code period and you'd be in a brand new folder and if you're using Windows this should say WSL or yuntu or something like that and if you have all that that means we're ready to go now a quick note something that you'll see me do a lot and you can do this as well often times when my terminal gets really really big or there's a ton of commands in here gets a little bit overwhelming for me so one thing that you can do is you can type clear and hit enter to clear it or what you can do is you can hit command K if you're on a Mac or control K if you're on a Linux or a Windows and it's one of my favorite keyboard shortcuts that I use all the time Additionally the trash can and the X here are very different if I go do a couple of enters here and we're down here if I hit the X here and then pull my terminal back up by doing the toggle or by doing terminal new terminal you'll see all those lines are still here but if if I hit the trash can and then pull the terminal back up you'll see it actually refreshes M has a special command that prints stuff out trashing your terminal is basically deleting whatever is running in it and the x is just hiding it and it's hitting control Tilda or toggling our terminal or whatever command it is on your environment that's equivalent to hitting the hide not the trash so if we want to remove and start a terminal over we hit the trash can and then we pull it back up so after we have that set up the next thing that we're going to want to install is actually Foundry itself in The Foundry book you can find this in the installation tab or you can go to get foundary Dosh and it'll have this command that you can actually just go ahead and copy Windows users we're going to teach you how to do it the Linux or Mac OS way so just stay tuned so we're going to go ahead and copy this and run this command again we can go terminal new terminal and there are also some shortcuts to do this I'm just going to go ahead and paste this in here and hit enter you will need internet access for this to work because it's actually downloading Foundry from this website and let me just move this up zoom in a little bit here and you'll see me do this a lot in the terminal I'll type clear a lot to remove anything that's been coded or output in our terminal here or you'll also see me do command K like that which clears the screen when I'm typing in the terminal you'll see me hit control w a lot which actually removes the most recent block of code you've written you'll also see me do control U which deletes the entire line so I'm going to use command C for copy and command V for paste a lot for those of you on Windows and Linux it might be contrl C and control V and if you're unfamiliar you can Google the keyboard shortcuts for for copying and pasting for Windows or Linux if you're on a Windows these keyboard shortcuts might be a little bit different we've got a list of keyboard shortcuts in the git repo associated with this course but if you've just run that curl command you'll see an output at the bottom down here that says something like detected your preferred shell is whatever your shell is here and added Foundry up to path run Source or simply start a new terminal session to use Foundry up and once you run that we can go ahead and run Foundry up and this will actually install an update Foundry to the latest version now whenever we want to install an update Foundry we can just run Foundry up like this it'll automatically install everything and Foundry comes with four components Forge cast Anvil and chisel we'll know we've installed these right if we run Forge D- version and we'll see an output that looks something like this now something important to note if you hit this trash can in the top right this actually kills the terminal it's different from the X which is just close the panel we close the panel and then we reopen our terminal by hitting terminal new terminal like this this actually creates a new terminal which we can kill like this but our old terminal is still up in order to actually delete this terminal we have to hit the trash can now you want to try this out now delete your terminal like we just did open up a new terminal and run Foundry up if this doesn't run we might have an issue with your path and you might need to add Foundry to your path if this is an issue that you have please make a discussion on the GitHub repo associated with this course or check please first check this lesson six of the GitHub repost associated with this course and we'll add some debugging tips to make sure that that does indeed happen or if there is no debugging tips here make a discussion on the course but first be sure to check to see if that discussion already exists and you should be able to do Forge dasd version however what can happen is if you trash can the terminal and open up a new terminal if you run Forge D- version now it might say Forge command not found this means means that you have to rerun this command this Source command that Foundry told us to do if you're working with bash most of the time this bash RC file automatically gets loaded but sometimes it actually won't depending on what your setup is if this happens for you another thing that you can do is you can type CD and go to your home directory and type this line Echo source and then whatever Foundry up told you to do double carrot. bash profile and hit enter for example when we just ran Foundry up right here it gave us this command here this Source users patrick. bashrc that's what we would want to Echo however this will change depending on your terminal setup so look to the GitHub repository for the command that you should be using for your setup please make a discussions thread if one does not already exist what this will do is it'll add this command to the end of your bash profile make sure you do double like this otherwise you could over ride whatever's currently in your bash profile now I'm going to give you a command that if you screw up you could accidentally override some stuff if you've never used bash profile before you kind of don't have to worry about it though the other command you can run is something like this if you do get an issue we can just ask an AI something like how do I get my do bash RC to load by default and there's a couple of different ways for this depending on what system using and what you're working with all I'm going to say though is if this happens to you if you run Forge d version and instead of getting an output you get something like command not found ask an AI or come to the discussions of the channel and as people run into this we'll build and start a discussion and if enough people have issues we'll create a new file here to help people to bug that issue so but it looks like chat gbt does give a pretty good output of what we can do we can edit our bash RC our bash profile our profile Etc and work with it like that so if you run into that issue there's plenty of things we can do to fix it don't worry but if you're a little nervous feel free to use the discussions channel of the course got it okay great if you see an output like this you've done it right if you see an output like we don't know what you're doing you've done it wrong all right great and again installing these can be some of the hardest parts of this course so don't get discouraged if this doesn't work right away if it worked right away for you that's actually amazing now also the control back tick shortcut toggles the terminal visibility between up and down I also have command J as a toggle for panel visibility as well this is a key binding that you'll see me use pretty often because we often will flip back and forth between the terminal and our code which is going to be up here in fact if we click this explore button on the left we can select this area select new file do something like hello.txt or better yet hello. so we going to add some code in here what's important to note is if you see this white dot in the top section here this means that this file isn't saved command s or controls depending on if you're on a Windows or Mac or Linux will save it and make that white dot go away unsaved saved unsaved saved it's important to recognize if a file is saved or not because if it's not saved it might not do what you think it should do so I kind of by default will always automatically save by hitting command s and it's a good practice to get into just always autosave everything you do we can also delete this file we just created by right clicking it and selecting delete move to trash final thing that we want to install and we'll install a lot of these as we go along is actually an AI extension something in vs code to help us actually have ai inside of our Visual Studio code if you select this little box looking thing that says extensions you get a search box which allows you to search for extensions the AI that I work with the most is GitHub co-pilot but you can use whatever AI you want or you could just not even use an AI get a co-pilot does cost money to use so feel free to also not use it there's some other free vs code extensions that use AI so feel free to browse around and choose which one you like for me I'm going to go ahead and install GitHub co-pilot you'll get a little guy in the bottom right for your vs code that will let you know that you've done it correctly you'll need to sign into GitHub which is something that we've recently made in order for it to work now you'll see me using GitHub co-pilot pretty often when I write my code because I have this little doad on down here I can start writing some code and GitHub co-pilot will start giving me suggestions as to what I should write for example if I were to add spdx by sense identifier get up co-pilot actually automatically starts to gray out and give me a suggestion if I hit tab I can autocomplete my code with GI up copilot suggestion alternatively what I could do then for example I could keep coding and I can see it's already giving me a suggestion here and if I hit upkey enter I'll actually open up this bit on the side where get up co-pilot will give me a ton of different solutions on what it thinks I'm trying to write and I can just pick one of these Solutions obviously some of these aren't doing anything we'll learn about the command pallet soon and we can also use any of the GitHub co-pilot commands that come with the command pallet an alternate to vs code is a tool called vs codium so vs code is a tool that's owned by Microsoft and it sends up Telemetry data up to Microsoft so basically it can send data about ways to make your experience better with vs code for people who have a more security mindset this is an open- sourced version of vs code that I highly recommend you check it out another extension that you might want to add is GitHub co-pilot lab get up co-pilot Labs has AI features that are experimental so it might be worth installing as well all right fantastic at this point you should be 100% set up with Visual Studio code and git if you're using git pod that's great as well and if you're using Windows you should be 100% using WSL because the rest of the commands are only going to work if you're using WSL and we're only going to be working with Linux bash or zsh commands moving forward if you want to be a Hardo like I was saying do everything in Powershell that's great too moving forward what I want you guys all to do is open up your terminal the different ways I showed you and create a folder by typing in mkd foundary hyphen f23 and then you do CD foundary f23 you'll notice something else I do a lot is I'll type the first couple letters of the folder I want to go into and then I'll hit tab which will autocomplete a lot of stuff for you in the terminal sometimes it doesn't work you'll get better at figuring out what Auto completes and what doesn't I hit enter this means I'm now inside of my Foundry f23 folder and I can run commands inside of this folder moving forward I want you to put all of your repositories inside this folder this way moving forward in the future when you start actually working on projects in real life you can refer back to this folder and refer back to code that you wrote and refer back to your notes to make sure that you understand stuff moving forward originally I had set up this f23 to stand for this is The Foundry 2023 edition how we've gone back and we've updated everything and we decided to just keep the f23 so that we don't have to change all the links so so now the f23 just kind of doesn't mean anything so you can you can ignore that f23 moving forward we've got g-- version Forge D- version we have cast D- version which cast came with Forge and Foundry we have Anvil D- version and we also have chisel D- version I'm going to type clear or hit hit command K to clear everything in the terminal and all right now that we have everything set up let's go ahead and start creating our simple storage project in a professional environment this is going to be the exact same environment that the big protocols use these are the environments that Unis swap a curve Etc these billion dooll groups use you are learning the exact same tools as them additionally for those of you who are interested in security and auditing Foundry is the most popular tool amongst Auditors so for those of you who want to become security researchers you're going to learn the exact same tools that the best of the best use you ready I sure am so let's go ahead and create a new folder inside of this folder here to do this we're going to type mkdir foundary simple storage f23 and then we're going to CD into Foundry simple storage F2 23 and you'll notice I hit tab there to autocomplete again now everyone's terminals are going to look a little bit differently mine tells me the exact path of the folder that I'm in but I have a Alias called video shell which just shows me the current folder that I'm in and I'm going to use that for the rest of the video so if you see my terminal look like this it means I'm at this location now if you're inside of this folder you can actually type in code and then hit a period and then you should get a new Visual Studio code which is now defaulted to that folder if you don't you can also hit file open folder and select the folder that you want to open which will also open up a new Visual Studio code inside of that folder if you open up your terminal now you'll see that we are indeed in the folder for this project and now on the left hand side over here this Explorer piece we create a file you'll see it pop up in the left hand side of our Explorer touch is a command to create or touch a file and we go ahead and click it and type stuff in this file now all these CD and mkdir and all these commands are known as bash or zsh or like Linux terminal commands and we're going to be using them a lot throughout this course if you want it's a great lesson on working with bash and CCH and Linux commands on the free Cod Camp YouTube but at the same time most of the time chat gbt and most AIS are actually very well-versed in bash and Linux commands so anytime you have a problem doing something you can often just ask one of these AIS and it can help you out as of recording this one just came out a couple weeks ago so it's incredibly up to date so if you want to get the basics down it's only about 45 minutes long I definitely recommend watching this so you can at least be familiar with some of the power that bash has you can absolutely continue on with the course as is and just use AI to augment you but for those of you who want to get more knowledge definitely check that out and again the reason I have this- f23 is to let everyone know that this is associated with The Foundry 2023 course but awesome we can actually begin getting set up with our own local environments similar to that remix VM that we saw when we were working with remix we can work with our own local blockchain and do a bunch of stuff locally as you can tell by the name of this project and from what I was saying earlier this is going to be our simple storage project but coded with Foundry which again is a smart contract development framework that's going to make our deployments in interactions with a code much more professional to get started with Foundry what we can do is we can open up our Explorer to see what's in here let's go ahead and delete high. txt move to trash I'm going to do my video shell command here which won't work for you but it works for me what we're going to do is we're going to run a command to create a new Foundry basic project for us and if you go through The Foundry documentation this is going to be basically this creating a new project section of the documentation and if you want to follow along with the documentation you can do that as well but to do this we're just going to run Forge and knit like this and we'll see it created a ton of folders over on the left hand side for us and if you run into an error because you accidentally have some files in here for example if I run Forge in it right now it's going to say oh it's not an empty directory we can do is type Forge init D- Force period to say let's do it in this directory hit enter and it's actually going to give us an error because it's going to go hey it already has everything that I was going to do so it just it's just not going to do anything but if you have have files in here already you just add this D- Force piece now if you get a different error about git Bas is actually going to help us triage that so take it away and we are getting this error and this is pretty common don't worry reason is because even though git comes preinstall it on our WSL install we still have to configure our username and our email so we can just use this commands change this one my actual email and now let's also configure the username after we have these configurations we can run that command again P init hello fundry and if we check this out we have our first phone re project ready to be used with all the things we are going to need and let's walk through what we have over on the left hand side here so we have this GitHub slork flows file which we're going to ignore for now but we'll explain this later we have lib which we're also going to ignore for now but we'll explain later we have script with a file in here which for now we're going to go ahead and delete we have SRC which is where we're going to put all of our smart contracts that we want to deploy right now it comes packed with this counter. Soul which we're also going to delete move to trash and then we also have tests which we haven't learned about yet but we will and for now once again you guessed it we're going to go ahead and right click and delete source is going to be the main section that we're going to be working with SRC stands for source and you'll see in a lot of projects this is where they put all of their main contracts test is where we're going to put code to test what's in SRC and script is where we're going to put code to interact with our contracts that are in SRC get ignore is going to be files that we're not going to push up to GitHub if we push our code to GitHub which is going to be really important get modules we can ignore for Now teach you about that later and founder. toml is a file that is going to give us configuration parameters about working with Foundry and as we go along in this course we're going to update this folder because we're going to update how we're going to work with Foundry now for us to get started here we're going to add our simple storage code into the SRC or Source folder if you close your remix we can just come on back to the repo associated with this course we'll scroll down to the remix simple storage select the code base and we'll Co here and just copy all the code in here come back over to vs code and then SRC we'll right click new folder simple storage. s paste it in here and hit save hello my name is basili and I'm going to be your instructor for everything related to development on Windows we are going to see each other a lot because each time a new tool is introduced to any of the courses you're going to see me there teaching you how to install run and configure that specific tool on Windows installing developer dependencies on Windows is a little bit tricky and sometimes really messy that's why we are going to install a tool called WSL or the windows subsystem for Linux on the upcoming videos I'm going to be really straightforward on how to install the tools we are going to use for the rest of the lessons however if you want to actually understand what WSL is how it works the basic command line tools and a lot more please be sure to check or 100% free crash course about a self for smart contract developers we published on YouTube with that said let's get that Windows environment ready for development Microsoft has definitely increased their support for developers in the recent years but when it comes to Smart contract development there is a better option to consider using WSL the windows subsystem for Linux trust me is a game changer you see a smart contract development often involves working with tools and utilities that are commonly found on Unix based environments well Windows has a long way in accommodating developers there can still be some challenges when it comes to Runing certain command line tools and sitting up the right development environment not mentioning that if you want your code to run on any machine using a units based system Mac and Linux is better for your developer needs here is where WL shines by installing a Linux distribution through WSL you can access to a full-fledged Unix light console right on your Windows machine and don't worry you don't need to be a hacker or wear a hoodie to make it happen is actually quite simple so let's do it let's get started with the installation process first we need to install WSL using the windows terminal in Windows 11 you can just hit the Windows key and type terminal hit enter and this will open the windows terminal for you which defaults to poers Shell however if you are using Windows 10 you are going to need to install the windows terminal through the Microsoft store so you can open the Microsoft store look for Windows terminal and please be sure to select the one from Microsoft Corporation once you have it please open it and installing W cell is going to be a really straightforward process and on the terminal we are just going to type WSL D- install this is going going to trigger some admin level operations as you are going to see on the screen right now you just select yes hit enter and once the installation process is finished it this will require you to restart your computer once you reboot your computer this is going to automatically trigger this window to continue the installation so let me actually make this big for you to see and the first thing we need to do here is to select or Unix username I'm going to select chare hit enter and then we are going to be required to set up a new password something interesting on most of Linux operating systems SL distros is that when you're are using the terminal if you type anything over here the password is going to remain hidden that doesn't mean that you're not typing anything but the terminal is not going to show anything over here unless you use another Linux Dr for example Linux minan otherwise most of the Linux operating systems are going to keep this always hidden I'm going to type my password though and then hit enter and as you can see here the terminal recognizes that password and ask me to type it again for confirmation and once we finish this that's it we have W cell installed on our machine as you can see here the installation finished it properly and we can continue I'm going to actually close this for now there are plenty of ways to install Visual Studio code and I'm going to show you three of those ways on this video the first one is going to be using the terminal as we are going to spend a lot of time using the windows terminal anyways we can install it with the hacker SL programmer way for that we are going to use winget which is a package manager pre-install it on Windows 11 for installing software you can also get winget on Windows going directly to the documentation so for example if I want to install Visual Studio code using winget I just use winget search vs code this is going to show me all the available packages to install Visual Studio code so installing Visual Studio code using this is going to be really easy I'm just going to copy this and say Wing get install and the package name I just selected if I hit enter this is going to start the installation of Visual Studio code on my machine as you can see this is opening the installation for me and that's it this is how you install or code editor from the terminal and if I go to the main menu I already have Vis stud here installed the second way to install Vis Studio code is open your favorite web browser on the search bar look for visual studio code select the one from code. studio.com this is the official Microsoft one you can click on download for Windows this is going to automatically trigger the download and open it this is going to start the installation process and of course we have the user and license agreement mostly no one cares about this stuff and no one read it but I highly recommend you to spend a little bit doing so as a good practice I'm going to accept the agreement hit next this is going to give us the path and the installation is almost the same as we did on the terminal way but in this case is going to allow us to have more things like this add open with code action to Windows Explorer File context menu this will allow us to do a right click here and have the ability to open any folder using visual studio code I'm going to also create a desktop icon hit next and install on the meantime this is installing I'm going to mention that if you are concerned about Microsoft having that much control over the data because they own Visual Studio code they own GitHub they own a lot more of tools and you want a open-source version of Visual Studio code that will lead us to the Third Way which is vscodium vscodium is an alternative to visual studio code which is exactly the same but without Microsoft Telemetry Gallery logo and Etc so basically they take the basic Visual Studio code built remove all the Microsoft Stu from it and change the license to the MIT license so basically if you are concerned about your privacy or Microsoft having access ACC to your data BS codium is a really nice alternative the installation is exactly the same you hit on install you download the latest release this is going to lead you to GitHub and select the one for Windows in this case is going to be the one marked as BS codium user setup. XA you hit this this is going to trigger the download and you're going to have the package to be inst it over here if you open it this is going to allow you to install vscodium but as this is not signed by Microsoft Microsoft is going to prevent to run this you click on more info and run anyway this is going to open the installation and the process is going to be almost the same because at the core they are the same code editor and this is how you can install Visual Studio code in three different ways select the one you like for this tutorial and for the rest of the course I'm going to keep from the one coming directly from Microsoft Visual Studio code now one of the first things that you'll notice is this is formatted horribly it's just all white text this cute little eth logo comes up which is really nice but we want a way to actually format this code correctly so there are a lot of different vs code extensions that actually will format our solidity code for us one of them is the solidity if we if we simp simply type solidity in the extensions bar we'll get a whole bunch of options that we can use I'm a big fan of the hard hat solidity extension even though hard hat is another framework it also can format our code in Foundry another one that a lot of people like is the solidity visual developer so that's another option if you want to use that one and this one by Juan Blanco is probably the most used on the planet but we're going to go ahead and hit install to install this nomic Foundation solidity vs code extension and if we go back to our simple storage. you'll see it is now formatted with syntax highlighting similar to what we saw in remix if it doesn't automatically highlight for you here what we can do is hit command shift p or control shift p which opens up our Command bar here and we can type in settings and we want to open our user settings in Json you can also hit code and then settings as well in here and a lot of you might have nothing in here so what you can do is you create these little brackets to say hey whatever is in here is going to be our new settings and we want to type these little quotes little brackets and say solidity like this little set little colon here some more brackets and since I'm using GitHub co-pilot it's even starting to give me suggestions which I'll explain much later but we could do editor dot you could paste in this editor. default formatter NCH foundation. hardhead solity I'll have this code in the repo associated with this course so you can just copy paste this if you want to I've got a whole bunch of other stuff in here so I'm going to go ahead and delete this though but that way your solidity code will default format using that hardhead extension that we just installed great additionally this Foundry dotl file also isn't formatted very well so we'll go to extensions we'll type in toml and we'll install this better toml here close this now if we go to founder. toml we'll see this is now highlighted very nicely too great now just remember whenever you see this little dot here this means that it's not saved so hit command s or file save and do that a lot the other thing that's really good about us adding that default formatter is in our code here you know maybe this isn't formatted very nicely right maybe we we've got this over here and and this over here and it's kind of not looking very nice here if I go ahead and save without formatting it'll save here but what we can do is if we add that auto formatter now if we do command shift p again that brings this up this command pallet up you can also get it by hitting view command pallet and we type format document it'll format our code automatically depending on what formatter we're defaulting to since we opened our Json and we defaulted to the solidity hard hat it'll automatically format with that if your code isn't autof formatting that's okay okay don't worry about this too much be sure to use AI a web search and the forums to get your formatting good the other thing that I like to do is we'll go over to settings again we're not going to go to the Json we're going to open the user settings and we're going to type in format on Save and we'll check this box on this way every time we save it'll automatically format so if I have this and I hit save it'll automatically format my solidity code for me if I don't want it to format again we open the command pallet with command shift p or view command pallet and we can say save without formatting and it'll save it see the white dot is gone and it will not be formatted but I'm going to save and reformat it because I like it formatted and just to note we pretty much never want to open these default settings Jason so avoid that one all right great and just with this little pieces of code and Foundry installed we can go ahead and compile our simple store for.ou right in our terminal so what we can do is we pull up our terminal and we can type in Forge build or Forge compile and this will compile our code like so once we compile we see a couple new folders show up one of them is out and this file in out has all the different information that the remix compiler would have for example it has the ABI we go back to remix we go to the compiler tab we go to one of our contracts we scroll down we can see we have the ABI section or it's also in the compilation details in vs code we can even click this little drop down thing next to it and it'll minimize the ABI and we can see the rest of this stuff like B code method identifiers and all this other stuff which we'll learn about later we also get this cache folder this is a folder that you could basically ignore now anytime in our terminal we hit up we can actually cycle through commands that we've recently run so if I run some crazy long command like this Echo here which is a bash command don't worry about it and I want to run it again I can just hit up all right great so one of the things that we did in remix quite a lot was we deployed our code to a remix VM or a JavaScript virtual environment we want to be able to do the exact same thing in Foundry in order to test and interact with our contracts Foundry actually comes buil in with a virtual environment in the shell and if you run Anvil you get an output that looks and we pull this to the top you'll get an output that looks something like this Anvil and we get some fake available account with some fake private Keys you'll also get a wallet pneumonic the derivation path which you can ignore some details about the blockchain and then this endpoint or RPC URL which we're going to learn about soon for now if you want to close this hit contrl C or just delete your terminal to end running the Anvil blockchain now moving forward we're going to work with Anvil but I do want to give you an intermediary step that's going to be with the ganach eth chain and we'll have a link to this in the GitHub repo associated with this lesson now and I want to give you a heads up so ganos is part of this Suite of tools called the Truffle Suite tool set and the Truffle Suite is actually being Sunset it's being deprecated so in this video I'm still going to be showing you some ganache stuff however you do not need to download it you do not need to do any of the ganache stuff that I'm going to show you here I'm going to go ahead and show you ganache however pretty soon we're just going to do everything with Anvil anyways so feel free to just watch follow along and then we'll actually replicate the exact same things using Anvil so this is one of those times where you can just sit back and enjoy the ride don't do any of the ganache stuff here just go ahead and watch me but when we get to the Anvil section we definitely want you to do the Anvil stuff so great ganach is a oneclick blockchain and it gives us a user interface or an app for us to look at our transactions in an easier way so if you go ahead and download it for your system we can get started there now a note for Windows users if you're using WSL the setup here is a little funky we ran into some issues with it in our previous course and we'll have some troubleshooting tips for those of you who are using Windows and WSL if you want to work with ganache everything that we're going to be doing moving forward though does work with Anvil ganache just allows us to see transactions a little bit better than viewing all this stuff in the terminal so if you're having a hard time with ganache don't worry we can do everything that we're doing with Anvil which should work for you no problem once you have ganache installed and you open it up it'll look something like this and if we hit quick start for ethereum we'll actually create a brand new locally running blockchain with a nice little UI to view things same as Anvil and same as remix we get some addresses we get each of them has balances they come with some dummy private keys and dummy addresses and the likes what's nice about this is that we can see the blocks we can see different transaction and if we're working with truffle we can see contracts we're not going to work with truffle though but these are going to be very helpful for us to view stuff additionally we're not going to use ganache again in the future so if you have trouble setting up with it don't worry just use Anvil I'm going to use it to show you what's going on remember though don't use these private keys on a public blockchain it's for development purposes only because everyone knows these private Keys cuz they're dummy private Keys now in order for us to learn how to actually deploy to this blockchain or how to deploy to Anvil if we're working with Anvil we need to understand how even remix was able to deploy to a public blockchain when in remix when we switched to injected provider of metamask we know that metamask popped up it asked us to add our password and we went ahead and got connected and if we looked in metamask we saw our account is indeed connected to saoo when we hit deploy our metamask popped up again and it was able to deploy our contract to a real test Network well how did it know where to send our transaction how did it know where to send our contract well let's go ahead and open up our metamask here if we click the three little dots and hit expand view we hit the little button now and we go to settings and we go to networks you'll actually see in here that each one of these networks ethereum main G SEO Linea or whatever you have comes with a whole bunch of information let's go to eth mainnet and check that out for a second it has a name an RPC URL a chain ID currency symbol and block Explorer this RPC URL is the actual https endpoint that we actually send API calls to when we're sending transactions so whenever you interact with metamask and you send a transaction or you deploy a contract you're actually making an API call to whatever is in here you'll see this is an infura endpoint and infura is known as a node as a service project that allows you to send transactions to a blockchain node without having to run one yourself if you wanted to send transactions to your own blockchain node you would just Swap this out with your own blockchain node address we can't actually change the ones that come built into mamass but we can add new networks which is what we're going to do now in here if we scroll to the bottom we can hit add Network manually and we can add information about our own custom Network so for us we're going to make this new network called local host or local chain or whatever you want to call it for RPC URL if you're working with ganach it's going to be this RPC server right here if you're working with Anvil at the bottom we have this listening here so what we would do is we would copy this or we would copy this from ganach and paste it in here just note that you always need the HTTP or https colon slash most of our local applications aren't going to be https they're just going to be HTTP so if you're working with ganach let's go ahead and copy the ganach mpoint paste it in here like so every single blockchain gets their own chain ID it's an easy way for us to know which blockchain that we're interacting with gach has 1337 and Anvil doesn't say it but it's 31 337 so Anvil is 31337 since I'm using the ganach endpoint here I'm going to type in 1337 if you're using Anvil it would be 31337 but what's kind of nice is metamask can actually identify what you're using and identify the chain ID and basically tell you what chain ID to use just a note it looks like the newer versions of ganach are using a different RPC server and a different network ID and make sure you're on this hard for the merge here as well although in practice I've found that even when you have 5777 it still is expecting 1377 so be sure to use the correct chain ID when you're working with this currency symbol we're going to do eth and since this is a local blockchain we don't actually have a block Explorer ether scan has no way to connect to our own local blockchain so we don't get a block Explorer for this one but if I go ahead and hit save now it says Network added successfully and I can go ahead and switch to my local host chain boom and now we can see it in my list of networks of a local host I've got no assets no nfts and no activity now if your local Anvil or ganache chain isn't running after you've put it in your metamask if you actually try to swap to your Anvil or to your local host or to your ganache you'll just get this spinning wheel of death here right and eventually you'll get this little a that'll show up and you'll have to switch to a different network so if you ever want to switch to one of these that isn't running it won't work you'll have to either run it or you can hit X here and then in your metamask you could just delete one of these right here while we're not running our ganache or our Anvil we're just not going to have one of these selected great and so this is where on both Anvil and ganache they have these available accounts and these private keys since I'm using ganache what I can do is I can select this show Keys copy this private key and import it into my my metamask so I can go up hit this little button I can hit import account paste my private key in here and hit import now you'll see in my menas I have a couple different accounts account three the one I just imported has 100 eth why does it have 100 eth well because I'm using one of these dummy accounts from ganach and again if you're using Anvil they have they start with th000 eth this process that we just did to add our new ganache local chain is also how we're going to add any evm compatible chain on the planet we'll just hit add Network and metamask actually comes built in with a lot of these and for example if we wanted to work with arbitrum 1 we could just hit add and it would add all this information in for us approv Network adding successfully but if metam Mass doesn't have those built in that's the process now if we go back to settings network Local Host this endpoint is the most important thing you need to send a transaction to a blockchain you need a connection to a node in order to send transactions to if you wanted to send transactions to your own node you would run something like G which is an execution client and then something maybe like teu a prism which is a consensus client and send transactions there I'm not going to go over this right now but I highly recommend that those of you who are curious maybe you take some time and you try to run your own ethereum node I run many ethereum nodes and it's a lot of fun it's kind of a weird thing to say it's fun to run nodes whatever it is fun to run nodes each one of these blockchains has different methods you could send to them to do things if you're familiar with apis and HTTP endpoints and you go to this ethereum jsonrpc specification site you can actually see all the different methods that ethereum blockchain nodes can make and most evm blockchain nodes can make and when we actually sign and send transactions it's these calls that we're actually making like e sign sign transaction send transaction send raw transaction Etc we're actually not going to be going over interacting with these because Forge actually handles a lot of sending these transactions itself if you want to learn how to send a raw transaction making raw API calls to your own ethereum node or an ethereum node as a service like in fura or Alchemy you would do that in a different programming language like bash python or JavaScript all right awesome now that we have our endpoint and our private key we pretty much have everything that need to deploy to our own local blockchain be it ganache or Anvil same as working with a real blockchain we need an actual balance to spend gas to deploy our contract now there's actually two ways that we're going to learn to deploy contracts and the first way is actually with just working with the command line if we're in our command line if we're in our terminal here and we do Forge d-el you can actually see all the different commands that Forge comes built in with the one we're going to be working with right now is this create command and if you read it it says it deploys a smart contract which is perfect that's exactly what we want to do and if we're in our Command here let's hit clear and we do Forge create d-el we can see a ton of different options for deploying our contract click show Keys copy the private key again if you're using Anvil use the private keys there if we do Forge create simple storage which is the name of our contract it'll compile and then it'll throw an error actually or it might might actually work but because I'm working with this RPC server but this RPC server is different from the one that Forge actually defaults to so instead what I can do is Forge create simple storage-- rc- URL copy this paste it in here it might be upset with the uppercase so let's just make that lowercase and I'll hit enter and this won't work either well of course we forgot to add a private key so if I hit up I can hit-- interactive as well and now it'll prompt me for a private key now and a really important note that I want to tell you never use a real private key in your vs code if you're using an application that potentially will send your information a much better option is to use your own terminal as opposed to something like vs code which might send data or get pod since we are just developing and we're just practicing it's fine to paste our private Keys here because because this is a private key that's not going to have any real money right it's a fake private key so for now we can go ahead we can go back to our ganache or back to our envil hit show Keys copy this private key paste it in here it won't show up if you hit paste but I'll hit enter and we'll go ahead and see information about our transaction now if you're working with ganach we can now hit done here we go to blocks we see we created a new block we go to transactions we can see see that we sent a transaction and we created a contract and then you can see logs about working with this as well fantastic if you're working with Anvil and you send a transaction you're not going to see any of those details for those of you who want to continue to see these blocks and these transactions and want to keep working with ganache feel free to do so moving forward we're going to work with Anvil so I'm actually going to close ganach now I'm going to hit clear in the terminal and I'm going to run Anvil here and what I'm going to do is I'm going to create a new terminal by hitting the plus button here and we're going to run that command again but we're going to run it with a private key from Anvil so if we go to here we do Forge create this time we don't have to put an RPC because Forge defaults to the envil one but I can say simple storage interactive it'll do enter the private key I will paste it and we'll go ahead and deploy go to Anvil we don't get any logs like this but we can see we went ahead and actually deployed it to our Anvil blockchain awesome work another way we can do this Forge create is by running Forge create simple storage if we wanted to be incredibly explicit we would do-- RPC D URL copy this HTTP colon slash paste it in there D- private key and back in Anvil copy the private key paste it in like this and we will get the same thing now here's what I'm going to tell you and this is incredibly important pasting in your private key like this is no bueno very bad we pretty much never want to have our private key in PL text especially our production or our private keys with actual money putting this private key in plain Tex is not a big deal because this is a fake dummy one it's also bad to have our private keys in our shell or bash history if I hit up once on my terminal I can see the private key in here which is why the interactive is a little bit better because it at least offis scates the private key to remove your private key from your history in bash you can do history- c now if I hit up I can't see any commands and if I do history I can see my entire history which is just the history keyword now if I type clear I'll do history now I see history clear history great and we don't have the private key in our Command history anymore we will learn more about proper private Key Safety in the future but I want you to do something for me right now in a new file I want you to right click and I want you to write promise. MD we're going to hide the terminal and in here we're going to say I promise to never use my private key associated with real money in plain text in fact take this and tweet this I promise to never use my private ke associated with real money in plain text and I can't spell and that's fine and then if you want to add me or you want to add cyer audits or whatever go ahead and send that we are going to have more of these promises that you're going to do but this is the first one that I need you to understand right now it's cool because these are dummy keys but in the future it will definitely not be cool and I'm stressing this because I've seen a lot of multi-million dollar companies not follow this and get their private Keys hacked great now of course though the basic way to deploy to any blockchain would be Forge create the name of your contract add the RPC URL and then add your private key we're going to learn how to get RPC URLs for free using Alchemy for any blockchain that we want and like I said more safe private key methodologies in the future but now you've just learn how to deploy your contracts to any chain from the command line this is great so this was a while ago that I made this with this EMV but now what you can do is you can just have nov at all and you can now use the power of cast built into Foundry to use private keys without ever having them in plain text which is what we want your private keys will always be encrypted using the methodology that I'm about to show you and therefore you should never have to use a EnV again if you come to cyphon looking for a security review or a security audit and you have aemv example in your git repo I will fail you so recently we just showed you how to use aemv or use a. example to get a private key RPC orl and ether scan API key as environment variables which is great however the issue is that we have these in plain text and that's bad for 100 reasons we might accidentally push this to GitHub we might accidentally show this in our terminal you always want to do your best to make sure private keys are never left in plain text so what we can do instead is we can encrypt them using ERC 233 5 which is just a way to encrypt our private Keys into a Json format so in our cbase let's pretend our private key is the default key that comes with Anvil so if I run Anvil I get this output like this we scroll to the top and let's say this is the private key that I want to encrypt I'll copy this address and then we'll do cast wallet import default key-- interactive I would also highly recommend you not doing it in vs code and instead do it directly in your terminal or your shell just in case you're using a buggy vs code for whatever reason and this will bring us into an interactive shell for us to post our information I think this is also really helpful because we do have to paste our private key and this will be the only time you have to paste your private key or have it in plain text but when we hit paste so I'm going to go ahead talk our screencast mode I'm going to go ahead and paste it in and you'll see that nothing actually showed up because it does that intentionally so now I'm going to un toogle screencast mode and then you enter a password and this will be the thing you need to remember moving forward to work with this private key so I'm going to do a crappy password great and it'll say default key key store was saved successfully and it'll give you this address here now before what we were doing was we were passing our private key directly into our terminal and you we were using a make file to make it look a little bit easier but in our terminal it would be something like Forge script blah blah blah some script-- private private key and then our private key which is bat so instead what we can do now now that we have it in our cast and we can even do cast wall list to see our default key in Here and Now what we can do is we can run Forge script script deploy excuse me script deploy fund me. s.o colon deploy fundme right this is going to be our basic script that we're running D- RPC URL HTTP Local Host 8545 this is if I'm running Anvil right which I am running Anvil right now of course this can be sepolia this can be main this be whatever else you want and now importantly instead of doing D Das private key and then in plain text pasting some private key we now instead do D- account default key-- sender and this is where this is a little bit annoying but we do have to copy paste the address of the sender so the sender associated with this private key so this is our private key and this is the address associated with that private key and then we can do D- broadcast and then Dash you know vvvv and of course if we were actually deploying to sooa we could do zoom out a little bit we could do verify ether skan API key Etc but I'm going to go ahead and run this now and what it's going to do it's going to compile it's going to run through the traces and now it's going to say Enter key Store password and it won't let you actually run this without the password so which I'm just going to say okay going to type in my crappy password here and boom it's going to deploy so there are some other ways to do this to make it even quicker there's also a D- password file where you can pass it a password file so maybe in your files here you'll do like a password or something like that where you put your password in here you'd of course want to put that in yourg ignore but even if you push your password up to GitHub that is still substantially better than if you push your private key up to GitHub just absolutely make sure you're not reusing passwords and once you have this in here you can do cast wallet list you can see your wallet in here and if you go to your home directory and you go to Foundry key stores do an LS in here you can now see this default key in here we can also look at this file I'm going to use cat but you can really use any command you want and you can see this it's this giant blarble of nothing it's basically this encrypted version of this private key which again follows this ERC 2335 and then in your shell if you type history you should be able to see a history of the different commands you ran and if you put your private key in any of these commands do history- c now if you type history it'll be gone you can also remove yourt bash history boom and now the private key is no longer in your bash history and if you're using a different shell like zsh check out where the zsh history is shown so should you still take the EnV pledge absolutely any time you feel yourself starting to think hm I kind of want to reveal my private key you should have a feeling come over you where you go maybe I don't want to do that again I know that you are using a development private key for this course because you promised you would be but when you move to working with a real private key with real money this is what I want you to do I want you to encrypt it once and then try to never look at it again anytime you see your private key in playing text alarm Bells should go off in your mind and you should say I shouldn't be doing this how do I reveal this private key as least often as possible and everyone should go on Twitter and thank this guy for being being the one to finally set this up and merge this Foundry Improvement so to recap you no longer need to have your private key in aemv ever you shouldn't be doing that anyways because I showed you other ways to not do that but now you doubly do not need to do that and especially if you have a private key with real money in it if you must send a transaction with that private key this is how I want you to do it number one use cast wallet import number two at least use a password or a password file instead of using your private key and number three if you do type your private key make sure to delete it from your history after you write it thank you and stay safe all right great so now we've learned how to actually deploy a contract to any blockchain that we want using the command line now I'm going to teach you the second way we're going to deploy our contracts and this is the way we're actually going to do it for the rest of the course when we're deploying our code we want to make sure we have a continuous reproducible way to deploy our smart contracts and when we test our code in the future we want the tests to test the deployment processes as well as the code so instead of just doing the command line we're actually going to write a script for us to deploy our code and because Foundry has everything written in solidity this script that we're going to write to deploy our code is also going to be written in solidity and this is where solidity as a contract language versus solidity as a scripting language is a little bit different Foundry has a whole bunch of built-in stuff to give our solidity even more functionality outside of just smart contracts and you'll learn about how later in the course but for now we're going to learn how to create a script to deploy our simple storage contract and the way we create a script to do it is first we come to our script folder we'll rightclick new file we'll create deploy simple storage. s.o this s.o is just a Foundry convention most of the time script have a s doou instead of just being doou and in here we're actually going to write a contract in solidity to deploy our smart contract which sounds a little bit weird but don't worry too much about that this deploy script is going to be written in solidity but it it shouldn't be considered a contract that we actually ever want to deploy it's just for deploying our code but it is written in solidity so since it's written in solidity we'll do the same thing as usual spdx license identifier MIT and if you're using GitHub co-pilot it might even Auto suggest like this and I'm just going to go ahead and hit tab I'll do pragma solidity 0.818 and then I'll create contract deploy simple storage like so and I'll hit save if you go to The Foundry docs we can actually scroll down to this solidity scripting section in the tutorials and you can learn how to actually write scripts and work with scripts the first thing that we need to do in order to tell that Foundry that this is a script is we need to actually import some additional code now one of the things that we saw in here was this lib folder and this lib folder actually starts with another folder called Forge STD this Forge STD stands for Forge standard library in here there's a ton of helpful tools and scripts for working with Foundry and to tell Foundry that this contract deploy simple storage is actually a script we need to import from Forge STD so we're going to do import Forge dstd /script doso and we'll have our contract deploy simple storage inherit all the functionality of this script by saying is script and I know we learned about inheritance before so you should know what that means is script and then additionally our deploy simple storage is going to need to know about our simple storage contract so we'll go ahead and import that import we'll go down a directory since we're in the script folder and we need to go to the Sr C folder these two dots is how you go down a directory we'll do slash SRC vs code even might help prompt you here Dash and it again Auto prompted for me and I hit Tab and now we've imported simple storage now since we know that this is the noob way to do Imports we're going to do the cool way by using named Imports instead of nameless Imports okay great now inside every deploy or script contract we need our main function which is going to be called run and this is going to be the command that gets called when we go to deploy our contract so we'll create a function called run we'll make it external and we can have a return a simple storage contract and in here we're going to use a new keyword that we haven't used before we're going to say vm. start broadcast VM is a special keyword in the Forge standard Library the VM keyword is a special keyword that we can only use in Foundry it's related to something called cheat codes we're not going to go over that too deep right now you can see a whole list of Foundry cheat codes in the documentation and Forge standard Library references which have even more cheat codes as well this VM stuff is only going to work in Foundry if you actually were to try to deploy this in remix or some other framework it wouldn't work these VM cheat codes only work in Foundry it's not valid in regular solidity but if we're inheriting Forge STD code this VM keyword exists if you're using the hard hat solidity extension we can actually control or command click into VM and we can actually see where it's defined but if that's confusing ignore that for now this vm. start broadcast says hey everything after this line inside of this function you should actually send to the RPC and then when we're done broadcasting we're going to do vm. stop Brad so everything inside of these is what we actually want to send and deploy the reason we have this is because maybe we have some stuff like we want to set some boilerplate code before we actually send transactions and we don't want to spend any gas to like set starting value to one right so any transaction that we want to actually send we need to put in between these vm. start broadcast and vm. stop broadcast and for us to deploy our simple storage contract we just do simple storage lowercase simple storage right these are different simple storage the variable simple storage the contract equals new simple storage like this and remember what does this new keyword do well the new keyword creates a new contract in solidity it's also going to create a new contract in between our vm. star broadcast this being in between these vm. star broadcast is going to send a transaction to create a new simple storage contract if this is a little bit confusing for you right now that's okay it's going to make more sense as we go on later in the course but for now just do this and follow along with me and then of course we can say turn simple storage okay great now if we pull our terminal back up we can see we have Anvil running right now we can actually kill it with contrl C we clear to the top and what we can do now is run Forge script script deploy simple storage. s.o hit enter and look oops looks like I got some different solidity versions so let's change this to a carrot in here let's change this to a carrot in here this being an 18 so that they're both on the same version let's type clear close these or minimize these out we'll hit up twice and we'll run this again and now what you'll see is it's compiling it compiles both the script to deploy and our simple storage contract using 0.8.9 because we did the carot compiler successful script successful tells us the gas and then we went ahead we returned our simple storage contract which was deployed here now you might be asking wait wait wait wait Patrick we we don't have Anvil running we don't have a local blockchain running where did this deploy to well in Foundry if you don't specify an RPC URL it'll just automatically deploy your contract or run your script on a temporary Anvil chain so once I ran Forge script it saw there was no RPC URL so it spun up a temporary Anvil blockchain deployed our simple storage and then tore it back down at the end you can see at the bottom if you wish to simulate on Trin transaction pass an RPC URL so if we do clear we run Anvil and then create a new terminal we could run Forge script script deploy simple storage s.o and I'm hitting tab to autocomplete that-- RPC URL go back to Anvil copy this go back to bash HTTP do do slash we actually almost deployed this to the blockchain we actually did a simulation of deploying to our Anvil chain here it gives us one more piece of information to broadcast these transactions add-- broadcast and wallet configurations to the previous command and now we get a new folder which gives us information about our previous deployments in case we forget for example if we deploy a contract we can flip back here and see where we actually deployed code so let's pull up our terminal once more and actually deploy this to the blockchain so we'll hit clear I'll hit up we have our RPC URL so now let's do dh- broadcast and we'll do D- private key and we'll grab a private key from Anvil and paste that in here and hit enter boom and we see at the bottom onchain execution complete and successful we see we get some transactions here we waited for receipts Etc so fantastic so we learned how to actually deploy our smart contracts through the scripting command now awesome job now let's learn a little bit more about what actually just happened right because because right now sending transactions is still kind of this magic thing right so let's hide our terminal and let's go up to our Explorer let's pull this out a little bit and let's go into here now what's important to note is that there's actually a couple different folders in here dry run is the folder whenever we don't have a blockchain running otherwise this gets separated by Chain ID and we'll talk about this a little bit later but if we go into one of these either dry run or or even just run latest we'll see details about the transaction we'll see a hash trans action type contract name address blah blah blah this right here this transaction section is actually what is getting sent on the Chain when we do Forge script or Forge create this is the transaction that we send to that RPC URL right this is the API data if you're familiar with htps post this is the data that we actually send we send the type which for now just everything is type two because we're in the merge don't worry about type one for now we have a from which is of course the from address that we want to have we have a gas here and this is the hex value of gas now if we pull our terminal back up we'll clear this out I'm about to show you an amazing trick that's going to make your life a lot easier Down the Line cast actually can convert between hex and numbers really easily and cast comes built in with Foundry we do cast d-2 base paste our hex in here and write DEC for decimal it'll convert this hex value to its decimal value 0x 714 C2 whatever is just this number and I use this cast to base all the time you can put some value in here and then what you want to convert it to and it's a very easy way to see what some value is there's some other stuff in cast as well if you do cast d-el there's some other ways to convert different units to each other like from way spites 32 and some other stuff but two base is going to be one that we're going to use a lot so we have the gas we have the value with the transaction yes since deploying a contract is just a transaction we can add a value to it if we want in our deploy script right in here we would just do some brackets we would say like value and like one ether if we wanted to deploy this with one ether you can't send a value here because in solidity you can't set the option value if the Constructor is not payable we'd have to make the Constructor payable but we could send value just like any other transaction there's this huge data piece here this is actually the contract deployment code and the contract code in here we have the nuns which is going to be that number that's only used once and then don't worry about access list for now but this is all the transaction information and then of course we have our RPC now what's not stored in here is is a couple other pieces of the transaction now additionally there are these v r and s values that account for the transaction signature it's not getting saved here because it's technically part of this from anyways they public values and these RS andv allow our private key to sign the transaction so what's really happening when we send this the reason we need our private key is we need the private key to actually sign the transaction that we built and that's happening a little bit under the hood so whenever we send a transaction there is a signature happening we are signing a transaction and then we are sending it and that's important for later in the course they don't save it here but signing the transaction does happen when you sign a transaction it's very similar to doing that hex thing we showed you way way at the beginning of the course with the blockchain only the private key can sign the transaction this is how when we send our data to a node it knows that it's able to execute it because it's signed by our private key I'm not going to go too deep into that right now this nuns piece is a little bit important every single wallet has a counter of transactions which is basically the nuts whenever you send a transaction you give it a nuns or this value this number only used once to basically count your transactions this is really good because if you want to replay transactions you would just send the same transaction data with the same nuns for example if we have a transaction that didn't go through you'll see that this is in this run latest with the dry if we run this again if we hit up you'll see that if we run our transaction again with our Anvil deployed here we'll actually deploy another transaction if we go back to our broadcast folder we see there's actually two runs and a new run latest if we go to our run latest now you'll see that the most the latest run now has 0x1 so this increments every single time we send a transaction your nuns increments every time you send a transaction and again contract deployments are transactions now we went over a lot of stuff in here but the most important takeaway I want you to have from this is anytime you change State on the blockchain it does it in a transaction and the differentiator is going to be what's ever in this data field this data field contains the op codes to tell the blockchain hey I'd like to create a new new contract we're not really going to go too deep into what these op codes are or this evm bite code we'll briefly talk about op codes later in this course but if you want to really learn about op codes and assembly we have another course on security coming out that we'll go over that but this is the most important thing to take away when we're in remix and we're sending transactions with these buttons we're doing the exact same thing we're populating the data field of a transaction but instead of the data being associated with creating a contract the data is associated with sending a transaction right great now that we've actually deployed our contracts though we should learn how to interact with them in the same way that remix allows us to interact with them with our buttons here now there's two ways to actually interact with our contracts one is going to be doing what we did before with scripts but the other way is actually going to be doing directly from the command line so we're actually going to learn the command line Parts in this project and then we're going to learn how to do scripts in a later project so let's pull up our terminal here and just to make sure that we have this deployed let's hit up couple times and we'll rerun this deploy script now in just a second we're going to learn how to actually interact with our contracts from the command line as well similar to how remix has all these buttons that we can press however first we're going to make this a little bit better and we're going to take a couple of different approaches to not having this in the command line as you saw before we could use Forge create interactive paste our private key in and it wouldn't be in our command line we actually can't use interactive for when we're sending scripts at the moment I'm sure in the future they'll make it a little bit easier for us to do this but right now we really don't want to have to do-- private key and paste our private key in PL Tex so what else can we do what alternatives can do we have now what I'm about to show you once again only do this for your development environment do not put a real private key in here the reason I'm showing you this is because it is much quicker to test however it's terrible to use in production so this is cool for development purposes this is not cool for actual production purposes what we're going to do is we're going to create a new file called EnV and whenever you create a EnV the first thing you should do is go to a g ignore file make sure that a EnV is in this get ignore I'll explain what the dog ignore does in the future but for now just have that be the first thing you do in ourv file we can put in what's called environment variables these are variables that might be a little bit sensitive that we don't want to actually write in the command line or accidentally expose to the public one of those of course is going to be our private key so let's go to Anvil scroll up grab that private key copy and paste it in here and we have this private key equals this typically you'll also see RPC URL equals what's our Anvil RP see relance this right here so we'll do HTTP SL SL paste that in there and great now that we have those in there what we can do is now run source. EMV which will add these environment variables into our shell here and we can do Echo private key like that and we'll see our private key actually show up like so we can also do Echo dollar sign RPC URL and we'll see our RPC URL actually show up like this and then what we could do is we we go back to our Forge script and instead of typing in our private key we would just do dollar sign private key and dollar sign RPC URL so now our RPC URL and our private key at least aren't being run in our command line so that it's not stored in our Shell's history the issue of course is that okay well now we have it stored in this EnV anytime you have your key stored in plain Tex you should be afraid you should be a little bit nervous so we can actually take one more step to make this even more secure and this is going to be one of the steps that I recommend that you take when you're actually working with production code you definitely do not want to launch production code with aemv file and I'm going to summarize all this very soon just stick with me I promise this is a little bit boring but it's incredibly incredibly important that you get this right and I'm going to try to prevent you from getting wrecked now Foundry is a tool that is constantly being improved and updated and there's an issue in The Foundry repo right now called improve wallet management us using key store I would love a way for you to actually encrypt your private keys so that none of you accidentally push a private key up to GitHub or expose a private key that it's in plain text if you run Forge script d-el and you scroll up you get this wallet options section where you can actually pass the path to an encrypted key store file and a password a key store is a file that has your private key but encrypted by a password instead of having your private key in PL Tex you would have it encrypted and you just need the password to decrypt it that is a much safer way to deploy your contracts I've added some context in another issue on Foundry as well and if you all could come in here and give this a thumbs up that would be fantastic a way to encrypt your private key into a key store file natively doesn't exist in Foundry yet but I've put out a bounty for someone to actually implement this so be sure to just check the G up repo associated with this course to check to see whether this feature is implemented so what I'm really trying to get at is for the moment a private key in ourv file is cool so long as we don't expose the EMV file but for real money you're not going to do that we're not going to do that okay for real money we're going to use the dashes interactive to paste our private key or we're going to use a key store file with a password once Foundry adds that there are some tools like dap tools eign that you could optionally download if you want to deploy and interact with wallets that have real money in them and it does have this import keyword where you can import your private key into to a key store file and then you would just obviously encrypt that with a password so for the moment this is your setup but in the future this is going to be your setup okay this is cool now but not in the future and additionally if you go to The Foundry full course f23 you go to discussions and this will also be in and this will also be somewhere on this side at some point you'll see this the EnV pledge which has a whole bunch of information about working withv files and keeping your private key safer for the rest of this course we are going to be working with this syntax because it is easier however I'm really hoping that Foundry in the future adds this key store encryption by default so that we don't accidentally expose our private keys and I'm not doing this to scare you but I'm doing this to impress upon you the importance of making sure you keep that private key and that num monic safe the other reason that we're okay to put our private key in ourv file is that you have already promised me that you're only going to work with a development private key or a private key that you're not going to add any real money into so if you expose it it'll be fine but you still want to practice not exposing it so please say take some time to read this and then if you do agree to everything just say I will be safe as a comment on this.v pledge so I'm going to read it out and it's important for you to understand this moving forward so it's going to be a little dry here but I am just going to read it I solemnly swear that I will never place a private key or secret phrase or pneumonic in a EnV file that is associated with real funds I will only place private keys in a DMV file that have only test at eth link or other cryptocurrencies when I'm testing and developing I will use a different wallet than the one associated with my real funds I am aware that if I forget a DOT get ignore and push my keyphrase to GitHub even for a split second or show my keyphrase to the internet for a split second it should be considered compromised and I should move all my funds immediately this is a really important line even if you show your private key to anywhere on the internet for even a split second it is considered compromised and you should move all of your funds immediately if I'm unsure if my account has real funds in it I will assume it has real funds in it if I assume it has real funds in it I will not use it for developing purposes I aware that even in my metamask if I hit create account or add account on my metamask or other eth wallet I will get a new private key but it will share the same secret phrase slne monic of the other accounts generated in that metamask these are some additions that I made from the last course for this course I will only use funds associated with my brand new never-before used metamask or other wallet and again most browsers you can choose a different profile and install a metamask on a different profile and use that metamask for this development purpose if I must use a private key associated with real funds of the future until I'm 100% sure what I am doing I will always either use encryption methods like the DAP tools keystore file I'm not going to show you how to work with this because some of the installs might be a little bit tricky but they have a way to actually import and encrypt private keys to a key store file use the foundaries built-in keystore Creator which isn't implemented yet anybody here who is a rust developer or knows some rust or wants to participate definitely be sure to check out this issue which is on Foundry and I would love somebody to take a crack at this or if you must use the command line as a way to pass your private keys and then delete the command line history immediately afterwards if I never actually deploy anything to main out myself or work with a private key with real funds I do not need to be concerned for any of you who are getting a little bit nervous about this just remember if you don't work with any real money you don't have to worry about this okay so a lot of you people who are who are newer here who are going to be going through this course we're not going to use any real funds so you won't have to be worried about this for those of you who are doing the extra credit which is with real funds you will need to keep this in mind moving forward and I would try to load your real metamask with real money with small amounts so that if it all gets stolen you won't lose sleep at night okay great and I'm telling you all this to arm you with this knowledge that you can be more secure moving forward take a look at this read this internalize it and if you want to copy paste this on Twitter in a huge tweet thread shout this from the rooftops put this in an article make a Tik Tok with this EnV pledge have an absolute blast the more people who know about this and the more people who understand this the better thank you for coming to my TED Talk all right so I know that was a lot of private key information and there's going to be more soon too so but the reason I'm harping on this is because I really really really really really want to make sure that all of you don't actually mess us up since you you are the developers you are going to be the ones responsible for dealing with all this and I want to make sure that you get it right so this was a while ago that I made this with this DMV but now what you can do is you can just have nov at all and you can now use the power of cast built into Foundry to use private keys without ever having them in plain text which is what we want your private keys will always be encrypted using the methodology that I'm about to show you and therefore you should never have to use a EnV again if you come to cipon looking for a security review or a security audit and you have aemv example in your git repo I will fail you so recently we just showed you how to use aemv or use a.v. example to get a private key RPC URL and ether scan scan API key as environment variables which is great however the issue is that we have these in plain text and that's bad for 100 reasons we might accidentally push this to GitHub we might accidentally show this in our terminal you always want to do your best to make sure private keys are never left in plain text so what we can do instead is we can encrypt them using ERC 2335 which is just a way to encrypt our private Keys into a Json format so in our coase let's pretend our private key is the default key that comes with Anvil so if I run Anvil I get this output like this we scroll to the top and let's say this is the private key that I want to encrypt I'll copy this address and then we'll do cast wallet import default key-- interactive I would also highly recommend you not doing it in vs code and instead do it directly in your terminal or your shell just in case you're using a buggy VSS code for whatever reason and this will bring us into an interactive shell for us to post our information I think this is also really helpful because we do have to paste our private key and this will be the only time you have to paste your private key or have it in plain text but when we hit paste so I'm going to go ahead talk our screencast mode I'm going to go ahead and paste it in and you'll see that nothing actually showed up because it does that intentionally so now I'm going to un toogle screencast mode and then you enter a password and this will be the thing you need to remember moving forward to work with this private key so I'm going to do a crappy password great and it'll say default key key store was saved successfully and it'll give you this address here now before what we were doing was we were passing our private key directly into our terminal and you we were using a make file to make it look a little bit easier but in our terminal it would be something like Forge script blah blah blah some script-- private private key and then our private key which is bat so instead what we can do now now that we have it in our cast and we can even do cast wall list to see our default key in Here and Now what we can do is we can run Forge script script deploy excuse me script deploy fundme dos. Soul colon deploy fundme right this is going to be our basic script that we're running-- RPC URL HTTP Local Host 8545 this is if I'm running Anvil right which I am running Anvil right now of course this can be spolia this can be mainnet this can be whatever else you want and now importantly instead of doing-- private key and then in plain text pasting some private key we now instead do D- account default key-- sender and this is where this is a little bit annoying but we do have to copy paste the address of the sender so the sender associated with this private key so this is our private key and this is the address associated with that private key and then we can do D- broadcast and then Dash you know vvvv and of course if we were actually deploying to sooa we could do zoom out a little bit we can do verify ether skan API key Etc but I'm going to go ahead and run this now and what it's going to do it's going to compile it's going to run through the traces and now it's going to say Enter key Store password and it won't let you actually run this without the password so which I'm just going to say okay and to type in my crappy password here and boom it's going to deploy so there are some other ways to do this to make it even quicker there's also a D- password file where you can pass it a password file so maybe in your files here you'll do like a password or something like that where you put your password in here you'd of course want to put that in yourg ignore but even if you push your password up to GitHub that is still substantially better than if you push your private key up to GitHub just absolutely make sure you're not reusing passwords and once you have this in here you can do cast wallet list you can see your wallet in here and if you go to your home directory and you go to foundary key stores do an LS in here you can now see this default key in here we can also look at this file I'm going to use cat but you can really use any command you want and you can see this it's this giant blarble of nothing it's basically this encrypted version of this private key which again follows this ERC 2335 and then in your shell if you type history you should be able to see a history of the different commands you ran and if you put your private key in any of these commands do history- c now if you type history it'll be gone you can also remove yourt Bash history boom and now the private key is no longer in your B history and if you're using a different shell like zsh check out where the zsh history is shown so should you still take the DMV pledge absolutely anytime you feel yourself starting to think hm I kind of want to reveal my private key you should have a feeling come over you where you go maybe I don't want to do that again I know that you are using a development private key for this course because you promised you would be but when you move to working with a real private key with real money this is what I want you to do I want you to encrypt it once and then try to never look at it again anytime you see your private key in plain text alarm Bells should go off in your mind and you should say I shouldn't be doing this how do I reveal this private key as least often as possible and everyone should go on Twitter and thank this guy for being the one to finally set this up and merge this Foundry Improvement so to recap you no longer need to have your private key in aemv ever you shouldn't be doing that anyways because I showed you other ways to not do that but now you doubly do not need to do that and especially if you have a private key with real money in it if you must send a transaction with that private key this is how I want you to do it number one use cash wallet import number two at least use a password or a password file instead of using your private key and number three if you do type your private key make sure to delete it from your history after you write it thank you and stay safe in any case let's go ahead and let's learn how to interact with these contracts from the command line first and in later courses we'll learn how to do it from scripts so we have our Anvil running and we've deployed our contract using our deploy using at least something marginally better using private key as an environment variable as opposed to just pasting it right in here so what we can do now is we can take this contract address and we can actually start to interact with it Foundry has another tool built in called cast and if you type cast d-el you'll see we get a whole bunch of commands to work with cast one of the commands that we can work with is going to be send which is to sign and publish a transaction so what we can do is we can do cast send d-el we can see the help of send and we can see the arguments it takes is going to be two the signature and the arguments so on remix for example we have our simple storage contract and we deployed it if we wanted to call our store function and send the transaction we would just add some numbers in here and then click store like this right if we want to call store from the command line we can do cast send the address we want to do the signature which for now just know is the is the function and the input types it needs so we could call store with a parentheses U 256 because we're calling the function store which takes a u 256 six is input parameter and then the arguments or the values we want to pass to our store function and we'll go ahead and hit enter of course this fails because we need to add our private key and RPC URL so we'll hit up we'll do RPC URL we'll do dollar sign RPC URL and then we'll do D- private key and then private key like that and now you'll see we'll get all of this data about our transaction back we get the block hash block number contract address is blank probably because it's a local chain logs we can learn we'll learn about logs later the transaction hash Etc now in order to read this we're going to use cast call which is going to read off the blockchain and if we do cast call d-el and we scroll up a little bit we'll see call takes two signature and arguments exact same as send but the difference is it's like call is like doing one of these blue buttons it's calling as opposed to sending a transaction it's just doing a view function not actually sending a transaction so we'll do cast call we'll paste the contract address we'll call retrieve r t r i r e t r IE V did I spell retrieve wrong I don't know I guess we'll find out no input parameters here and no arguments we can just hit enter and we'll see we get the hex value back this is where I said you're going to be converting stuff from hex back and forth a lot then we do cast D- to base paste the Hax and say decimal and we can see we get back one two three which is exactly what we've stored on chain so if we hit up a couple times back to our cast send transaction our cast send command and we change 1 2 3 to 777 we hit enter we'll send that transaction now if we hit up three time two or three times we'll call cast call retrieve now and we should see the new number which we get back as a hex and then we'll do cast d-2 base paste in deck and we do indeed see 777 Return To Us awesome so now we know how to actually interact with our contracts from the command line and this is going to be the same way we can actually interact with our contracts on an actual test net or on an actual main net all right so now you might be asking okay Patrick what does this look like on a test net or a live Network so let's go ahead let's go to ourv file and let's update this so that it's aemv file for an actual test net so the first thing is we're going to need an RPC URL for an actual test net for an actual Network and this is where in our metamasks actually have inferior connections built in remember before we went to our settings networks theum main net we saw oh we saw we have this inferior connection we can't use this one because this one's designed specifically for our metamask so we're going to have to get our own RPC URL for an actual test net well one of the things we could do is we could run our own blockchain node but a lot of people don't want to do that so what a lot of people do is use something called a node as a service to do this what I'm going to recommend you do is actually come over to The Foundry full course repo scroll down and there's going to be a section called deploying to a test net or main net if we click this link we'll actually go ahead and we'll get sent to the Alchemy platform where we're going to sign up for a free notice of service that we can actually send transactions to and we're going to go ahead and sign up for their platform you can sign up with Google sign up with SSO whatever you want to do I'm going to go ahead sign in with Google I indeed human and we're going to come to their user interface that looks something like this we're going to deploy this to sapoia but remember go to the recommended testet section of this course so what we're going to do now that we're in here is we're going to go ahead and create a new app and you can name it whatever you want I'm going to call it seoa testing I'm just going to copy this for a description this is on the ethereum Chain but on ethereum seoa we're not going to do any advanced features we'll go ahead to create app and now we have this ethereum sapoia app where we can view details we can see how often we're calling this and we can see different details about our node and if we hit view key we see we have this htps endpoint and this is going to be the exact same thing as that Anvil or ganache or metamask endpoint that we saw and we're going to go ahead and copy this and back in our b v what we could do is we we can create a new RPC URL called sepolia RPC URL equals and we'll paste that in here now we have an RPC that points to an actual test n with our private key we can't use this as our private key because this is an anvil private key it doesn't have any real money in it and it doesn't have any test net eth in it but what we can do is instead we can use our one of our private keys in our metamask so if we switch back to sapoia in our metamask we can pick one of our accounts that actually has some money in it I'm going to pick account number one we'll hit the three little dots Account Details export private key and remember it's okay for me to show the private key here because this is just a dummy private key but I'll add my password in and remember I'm never going to actually do any real money with this and I'll copy this done and paste this in here and maybe I'll maybe I'll comment this line out in EMV file this hashtag or this pound sign is what the comment is but maybe we'll do a new private key equals and I'll paste this in here and now I have the private key for metamask I have the RPC RL and those are all I need to actually deploy a transaction so what I can do now pull my terminal back up so we're going to run this command to actually deploy this to a real test net from our Foundry using Alchemy as our node as a service and you'll see in the user interface of alchemy you'll see a transaction actually come through our node This Is Us sending a transaction to a real node and we'll be able to see the stats here on our Alchemy dashboard so let's go ahead let's do this again so first we're going to need to run Source AMV to make sure all of our AMV stuff is loaded then we're going to run Forge script script deploy simple storage. s.o and I'm hitting tab to autocomplete here- Das RPC URL sepolia RPC URL with the little dollar sign D- private key dollar sign private key-- broadcast if you don't add the-- broadcast it won't actually send it it'll simulate sending it now if I hit enter we'll see a compile and now we're running this script deploy simple storage. s.o which actually deploys it and we'll see we went ahead and deployed our contract simp storage on the seoa Chain we see all these details about it it's sending the transaction right now it's storing the latest run under the broadcast folder under its chain ID in here in this run latest. Json and after a brief delay we'll see it went through and what we can do is we can grab this hash go over to cia. etherscan.io paste that hash in here and we'll see we actually successfully sent a transaction and if we click on our contract address we just created we'll see we actually just created this contract on a real test we go back to our Alchemy dashboard and we hit refresh we'll see we actually sent we sent some requests we scroll down we can see some of the different requests we sent eth send raw transaction was the request that we sent to actually send our transaction to the blockchain but we also got some stuff about the chain ID fee history Etc one thing that you'll notice though when looking at this on ether scan is that the contract o it's just a whole bunch of bite code here right this isn't very readable what we can do is we can actually verify this contract and now I'm going to show you the hard way first and I'm going to teach you the easier way later but you can manually verify a contract on ether scan or other block explorers by selecting verify going to solidity this is a single file contract so we're going to do single file I know that we were on 0.8.9 and our open source license is MIT we'll hit continue we'll go back to our simple storage. soul and we'll copy the whole contract scroll down we'll hit paste optimization is going to be yes there's no Constructor args no contract Library addresses no Miss settings I'm not a robot and we hit verify and public sometimes this can be a little bit tricky to get right and we're going to going to work with programmatic verification pretty soon that makes it a lot easier but if we did it correctly what'll happen then is if we click on our contract address here and we go to contract and we scroll down we can actually see our contract right in ether scan this will also give access to these read and write contract buttons which we can see it now looks really similar to what's on remix and we can actually interact with our contract right from ethers scan or another block Explorer like I said that's the manual way to verify your contracts and you can run into a lot of issues doing that so I don't recommend doing it I recommend doing the programmatic way which I'm going to teach you very soon all right so now we're just about done with our very basic project here which is fantastic we've learned a ton already but there's a couple things we want to keep in mind here moving forward and one of those things is when it comes to formatting so we are using the vs code autof formatter to autof formatter code but if somebody else comes and I'm going to actually save without formatting if somebody else comes to our code base we're going to want to have them format it the exact same way that we format it so what we can do is we can use the forge format command which if we run it you see favorite number actually went ahead and formatt it so I'm going to save without formatting again run Forge format and it's going to autof format our code here so this is a command that will automatically format all of our solidity code awesome and additionally for every single repo you ever work with you always want to make a readme.md file so right click new fil readme.md I actually already made one over here and this is where you're going to put information about your project here I put some notes about the private key usage which I'm just going to delete for now readme files are generally where you put information about your project instructions to work with it places to contact you really any information that another open source developer should know when they want to interact with your project because we are going to push this up to GitHub as well we're not going to push this up to our GitHub because it's kind of easy but in the next project we're actually going to push the code up to GitHub and I'm going to teach you how to do that read me. MDS are this markdown syntax remember how we were talking about answering questions or asking questions using markdown syntax well this is going to be the exact same if I do a hashtag or pound sign like this and I say hello and then some text down here and if I hit save what I can do is I can actually preview this markdown so in my extensions over here we're going look for a markdown extension I actually already have one markdown all-in-one or markdown preview or whatever you want to install and we can do open up our Command pallet with command shift p or view command pallet we can do markdown preview open preview like this and we can see what this looks like as if it was on a GitHub repo we can see Hello is Big we can see our text down here is small and if I were to do like some back text like this I could say like code here save that look at our preview again we can see this is formatted now as code you can also do command shift V to automatically go to preview mode or it might be control shift V for Windows and Linux users there's a lot of different ways to go preview your markdown and remember if formatting your your read me is difficult usually AIS do a pretty good job at formatting your markdown for you if you just ask them politely so now we just learned a lot about deploying smart contracts private keys and more now we're actually going to teach you a slightly new process for working with a layer two for deploying to ZK sync we actually have to go through a slightly different compilation process this is because ZK sync compiles down to slightly different op codes than ethereum we'll learn more about the differences between ZK sync and ethereum in a future section but for now just know that at a high level solidity will work pretty much exactly the same on ZK sync as it will in ethereum but the low-level stuff the stuff that comes out in this out folder with Foundry is actually going to be different from ZK sync so right now instead we're actually going to do three things so first we're going to install this tool called Foundry zik sync then we're going to compile our solidity our simple storage contract with this D- Z syn flag and then we're actually going to revert back to vanilla Foundry and you'll see what I mean in just a second by that now if you go to the GitHub resources associated with this course The Foundry full course giab repo and we scroll on down we'll go to Foundry simple storage and we go into the code base and we scroll down in here there will be a section towards the bottom that says ZK sync instructions with a link to Foundry ZK sync you can also find this link in the main repo if you scroll down a little bit farther there is a Foundry ZK sync there is a Foundry ZK sync Link down here as well compiling to ZK sync in Foundry ZK sync that you can go ahead and click and that will bring you to this matter laabs Foundry ZK sync GitHub repo and in this repo what this is It's a what's called a fork of Foundry tailored for the ZK sync environment so it's basically all The Foundry code with a couple tweaks a couple of additions to make it work a little bit easier with ZK sync and if we scroll down in here there's actually some instructions to installing this project installing this repo there's this quick install instructions now I'm going to go through the quick install here however the instructions might be a little bit differently depending on when you watch this so just just follow along with the instructions here we will show you what the expected outcome should look like and the important bit is that this installation overrides any existing Forge and cast binaries in Foundry so right now in our terminal if I type Forge D- version we get this output like this and this is what I'm going to refer to as vanilla Foundry or base Foundry The Foundry that we installed from The Foundry documentation this Foundry here is going to be Foundry ZK sync and it's going to use the same keywords it's still going to use Forge but it's going to be this Foundry ZK Inc addition first thing we're going to want to do is we're going to want to clone this repository so I'm going to copy this get clone line here either with the copy button and in here what I want to do is I actually don't want to install it in my Foundry simple storage repo maybe I'm going to CD down a directory into my Foundry f23 or I guess I should say f24 now because I'm recording this in 2024 and I'm going to paste that in here hit enter if you're having issues cloning it with this you can of course just copy the URL up here and do get clone paste the URL and then delete a bunch of this stuff just to this part github.com slatter laab Foundry ZK sync or whatever the URL is at the moment and you can do that as well this will create a new Foundry ZK sync repo that we can CD into CD Foundry ZK sync like so I'll do a little clear here and oh the instructions said change the directory Great we've already done that next we're going to run this command line here now if you're on a Windows machine this command as such won't work so you'll need to be on WSL like what we showed you or use a Mac or a Linux environment but we're going to go ahead and we're going to copy this and we're going to paste this into our terminal in this Foundry ZK sync folder remember we can do a little PWD to make sure we're in the correct Foundry zync folder and we're going to go ahead and hit enter and this is going to run what looks like to be The Foundry installation piece huh interesting if we scroll up in here we can see a similar output to what we with Foundry but we get something like this detected your preferred shell is Bash or this might be Z zsh or whatever shell that you're using but it says run Source this right here or start a new terminal session to use Foundry up ZK sync well okay I'm going to go ahead and delete and open up a new terminal here now if I type Forge D- version I actually get a slightly different version than what Foundry gave me it might be 0.0.2 it might be some other version depending on what version of Foundry ZK sync you actually update now I can also run this new command Foundry up- ZK sync go ahead and run that and what this will do is it'll install the latest edition of Foundry ZK sync into our terminal which is really exciting and what's cool if I do Forge compile or build d-el and I scroll up a little bit we'll see in here we have some new ZK sync era Flags such as the-- ZK sync flag which we're going to use pretty often and some compiler options and all this other good stuff now here's what's cool if we want to switch back to what I'm going to call vanilla Foundry we can just run Foundry up and this will override Forge and cast to be back to vanilla Foundry so now if I run Forge build-- help and we scroll up I won't see those ZK sync Flags anywhere I don't see them in here but now if I go ahead and clear this and I run Foundry up- ZK sync now I'm going to get those ZK sync commands back and we can see we're back to 0.0.2 if I run Forge build d-el I scroll up we can see oh there's some ZK sync stuff ZK sync compiler zync Arrow VM and we're back on The Foundry Z sync compiler very exciting so for you I'm going to recommend for the most most of the time you should be on the vanilla Foundry and you can make sure you're on vanilla Foundry by just running Foundry up then whenever we want to switch back to Foundry ZK sync we're going to run the this Foundry up- ZK sync to switch back to the ZK sync edition of Foundry so if you haven't already run that Foundry up ZK sync to be on the ZK sync edition of Foundry and then what we're going to do now is finally we're going to build this simple storage. soul with Foundry zync remember when we ran build before we got this out folder here created okay and this contains all the Compilation All the compile all the build details of sort of associated with vanilla Foundry if we run Forge build Das Dash actually let me keep this open and I'll zoom out just a little bit Forge build-- ZK sync what you'll see happen now you'll get some warning outputs like this you can ignore these but what you'll see now is you'll see this new folder called ZK out and this ZK out folder contains all the compilation details for you guessed it ZK sync right so we have out which is the evm or the base ethereum compiled code and then we have ZK out which is the ZK sync or the arrow VM compiled code now like I said if I want to just switch back to vanill Foundry I can just run Foundry up we'll switch back to vanilla Foundry maybe I'll clear my terminal if I do Forge build now I just build a normal Foundry project like so so now with just running Forge build- dzk sync on that Foundry ZK sync Edition we can compile all of our smart contracts to the ZK sync output so we can deploy our smart contracts in a much cheaper more effective manner to the L2 or the layer 2 the rollup ZK sync awesome like I said for continuing this journey stay on The Foundry up the base the vanilla Foundry command line unless I tell you specifically hey now we're going to be using Foundry ZK sync so cool all right so now that we've learned a lot about deploying our smart contracts with Forge crate and with Forge script to our local and chain we're going to now learn how to do it for ZK sync now typically the process is going to be exactly the same you're just going to have your Forge create script with all your little commands in it- RP crl this would be like your ZK sync RPC and then you would add that-- ZK sync at the end as of recording you also have to add a-- Legacy but we'll explain why you need that another time so typically the process is going to look exactly the same just with the dash D- ZK sync and a-- Legacy flag however I'm going to show you how to deploy to a locally running ZK sync node and this process is a little bit more involved than working with Anvil so I'm going to tell you that this is 100% an optional section to do and the main takeaway is that deploying to ZK sync with Forge create is going to be pretty much exactly the same as what we did with Anvil you're just going to add that --zk sync flag and a -- Legacy flag at the end of your Forge crate command now we're not going to be showing you how to deploy to ZK sync with scripting because as of recording scripting with ZK sync doesn't work very well so in a production environment you actually would want to use that Forge create syntax and do some clever bash scripts to test your deployment process we're not going to go super deep down that path but just know for deploying you're going to use Forge create and we're going to walk you through how to actually do this right now but sometimes we want to make absolutely sure that our smart contracts work properly on ZK sync instead of raw ethereum so to make absolutely sure we can also deploy our smart contracts to a locally running ZK sync chain now to do this you're going to need a couple additional pieces so like I said this is going to be optional if you want just go ahead and kick back and relax and watch me do this just so that you're familiar with some of these processes or if you're feeling sufficiently motivated feel free to jump in but again this this is not required this is 100% optional so what we're going to do is same thing go to your GitHub resources we're going to scroll down Foundry simple storage we're going to open up our code base here and we're going to scroll down to this section in here called zky sync instructions so we've already got set up with Foundry ZK sync we can make sure we're on Foundry ZK sync by running Foundry up - ZK sync getting an output like this and it looks like cool that installed successfully then what you're going to need to do is you're going to need to install now if you're unfamiliar with Docker this could be a whole new world and that's why I'm saying this is optional Docker can be very tricky for new developers to install if you already got installed great if you want to give yourself a challenge here great go for it the docker docks have a lot of documentation on how to install Docker so feel free to do so I'm not going to walk you through installing this because like I said this is going to be an optional section for you I will say that once it's installed at least for Max you get this new Docker application for Linux you don't I don't think you get one for Windows either and if you open the application you'll see something like Docker engine starting and then maybe you see something like this so this is specifically for Mac OS Linux users will see something different and what this will do is it'll kick off it'll start the docker Damon or the docker background Pro progress so if we kind of just move this off to the side we keep it running though we go back to our terminal do a little clear if I do a Docker D- version I'll get a little output that looks something like this once I do that I can kill my terminal reopen it I can run Docker PS and I'll get an output that looks like this now if I stop this on a Linux you might be doing something like pseudo system CTL uh pseudo Sy CTL start Docker to start it and then stop Docker to stop it but if it's running and I go ahead and quit it quit Docker desktop or pseudo system CTL stop Docker if I run Docker PS now I'll get cannot connect to the docker Damon but that's how we go ahead and get Docker installed like I said this is an optional section if you're struggling installing doc if you're struggling with installing Docker you can just move past this Anvil is going to be perfect for pretty much everything that we're going to do but once you have Docker installed the next thing we'll want to do is install nodejs and mpm once again we can come to the node.js documentation by clicking that link in the GitHub repo assed with this course and you can choose the version you can choose your operating system like Windows or Mac or Linux if you're using WSL definitely use Linux and you can choose the package manager to install with and you can run each one of these commands to make sure that it's actually installing correctly once you've installed it you can run MP m-- version get something like this MPX D- version get something like that and then node-- version and get something like this so not is a pretty common pretty popular package so it's probably good for you to have this installed anyways because a lot of projects and a lot of people work with npm so now that we have both of these installed we're going to work with this ZK sync CLI so this ZK sync CLI you can find more information on this in the ZK sync documentation this is a tool that makes developing and interacting with ZK sync a little bit easier and we're going to be using it to run a local ZK sync node like a minimized ZK sync node so to get started we're going to run MPX ZK sync CLI Dev config and going to go ahead and copy paste that in here MPX ZK sync CLI Dev config and this is going to prompt us to say hey uh what do you want to use and we're going to say we want to run run an inmemory node so this will be in Docker so I know there's this section section that says dockerized node but we're going to do the inmemory node here quick startup no persistent state only L2 node the name of this might be a little bit different depending on when you watch this and then we don't want either of these we don't need a portal we don't need a block Explorer if you want to fiddle with working with these yourself feel free to do so so I'm just going to go ahead and hit enter here as well the configuration has been saved successfully now to spin up our doer node and actually before we do this if you do like a little Docker PS you'll see again a blank output here now if we paste this in npx zyn CI Dev start and this is going to go ahead and spin up a ZK sync node running in the background for us so unlike Anvil which is kind of in a terminal and will always be in a terminal this is actually running in a darker cloud and we get a whole bunch of information here that is going to look pretty familiar with us but if I run Docker PS now now I get this kind of wild output here but essentially we this Docker PS command means hey there's a process running in the background in Docker now if I were to quit Docker so I just I just went ahead and actually quit Docker in the background now if I run Docker PS you're going to get this cannot connect to the docker Damon hey is the docker Damon running if if I also try to run MPX ck6 CI Dev start I'm going to get kind of an err that looks like this cannot connect to the doer Damon is the docker Damon running so if you see something like this you're having a hard time starting the docker Damon and I would honestly tell you it's probably not worth figuring that out right now so just move on keep working with Anvil Anvil is fantastic so so I'm going to start Docker back up in my background here in my little My Little Mac Docker application so anyways I just this back up and now I can go ahead and rerun this MPX ZK sync Dev start it's going to remember my config from before and we're going to go ahead and get this in memory node spun up right I can run Docker PS I can see that this is once once again running and fantastic you can see up here it'll give us a chain ID an RPC URL and instead of giving like an output with a list of private keys and accounts we can actually copy paste this link that it gives us and it'll give us this list of account addresses and private keys in the ZK sync docs that we can go ahead and use so now that this is running now that we have this RPC RL we can go ahead and deploy our contract to our local ZK sync chain the same way that we did with Anvil except for we're going to be doing to this ZK sync chain so first let's just check Forge D- version okay 0.0.2 cool that means I'm on The Foundry ZK sync edition of this so I'm going to go ahead I'm going to do Forge create simple storage now this probably won't work and I'll show you why in just a second though-- RPC URL we can just copy paste this RPC url-- private key and again this is terrible to do private Keys like this I'm going to show you a better way very soon paste that in here and then we have to do D- Legacy --zk sync enter and the reason I wanted to show you this is because we are going to run into an error let me zoom out just a hair libraries must specify a path this is a bug consider reporting basically The Foundry zync isn't clever enough to know where this simple storage contract is so I'm actually going to delete my terminal here or hit contrl C or get out of it however you want we're going to open the terminal back up we're going to run this command again and we're going to update it though so instead of just saying simple storage we're going to say srcs simple storage we're going to give it the whole path so it's SRC simple storage and then we're also going to do a colon with simple storage like this so we're saying at path srcs simple storage in this folder do excuse me simple storage. saw in this file grab the simple storage contract and deploy that and if we hit enter now we'll see first it compiles successfully and then it goes ahead and deploys fantastic and we can see has a deployer deploy to transaction hash Etc now if we didn't use this -- Legacy it'll also work but it might not work for more complicated smart contract that we're going to use in the future so for now I'll say just default to Legacy if you want to get more interesting you don't do with the --zk sync you will just get failed to serialize transaction address to to address is null and we'll learn why that happens in the future with CK sync so once you're done working with all this of course if you want to go ahead you can close down quit your Docker desktop and then we can just run Foundry up to convert back to vanilla Foundry as opposed to being on Foundry ZK sync and now you've deployed a smart contract to a locally running ZK sync node which is pretty phenomenal now I'm kind of fibbing to you scripting works for ZK sync the forge script script thing it works for zync in some scenarios however because it's not super clear where it's not going to work I'm just going to say for the duration of this course for now just assume it doesn't work however I did go ahead and deoy to a zync locally running node using forward script so I could show you something cool about Seri here so I'm going to introduce a lot of different concepts to you and it's not super important you understand everything right now later on in more advanced sections we'll go deeper into these transaction types and deeper into the concepts that we're going to express here again you don't have to to actually deploy to the zikas sync locally running node that is 100% optional but if you were to do it with a script you would get this broadcast folder with this train ID and I wanted to do that to actually show you something cool that I'm going to teach you now now I know this was an optional section but I went ahead and I did actually deploy these smart contracts to the ZK sync local node as well and if you did that if you look in your broadcast folder you'll probably see this 260 in here right now in here you'll see a 31 337 folder and a 260 folder these 31 there's a lot of them in here this 31337 represents all the scripts that we ran on our Anvil local chain and since I've been recording for a while and I wanted to do a couple of trial runs I've actually deployed a ton in here and then there's our 260 which is our locally running ZK sync chain if you went ahead and did that again you don't actually have to and these folders contain informations about when we ran those deploy scripts right again I did not teach you how to use the scripting functionality for ZK sync but we did actually go through that for Anvil and going into these runs we can actually learn something about transaction types so let's look into these transactions that we sent to the 31337 chain ID AKA that Anvil chain this can actually teach us something about different transaction types now if I look in the Run latest. Json and we scroll down in here we can see a whole bunch of transactions if we scroll down into this receipts section we can see this type 0x2 however if we flip on over to the 260 chain ID right this is going to be the chain ID of the ZK sync local node that we were running and we go to run latest we scroll around in here we scroll down we can see a bunch of stuff we can actually see in this transaction area we see a type 0x0 huh is there a receipts okay yep okay there's a receipts okay well maybe there's a type in here no we see logs status I don't see I don't see a type in here that's actually because The Foundry ZK sync and The Foundry report types A little bit differently but interesting so we see on The Foundry we see a type 0x2 and on the ZK sync we see a type somewhere in here type where is that type0 x0 well what if we were to deploy our smart contract again with regular vanilla Foundry but we use that-- Legacy Command right so remember deploying with vanilla Foundry to Anvil we had a type 02 transaction in our receipts so let's go ahead let's do Anvil copy this make a new one new terminal now let's to forge script script deploy simple storage. S.S soul-- RPC URL HTTP remember this is all in the GitHub repo so you can go ahead and copy paste if you want to follow along-- private key we can go back here we can scroll on up we can grab one of our private keys and remember putting your private key in plain text is terrible we'll teach you later how to actually fix that and then we do D- Legacy D- broadcast this is now going to deploy our smart contract to Anvil via a legacy transaction so if I go back to my 31337 which is my Anvil deployments and I go to the Run latest. Json whoa in receipts I now have type 0x0 right if we go to this one right above it we still have type is 0x0 because these two are going to be the same but if we go to one past that now we scroll down we can see type 0x2 now if I were to run this script again without this Legacy flag right I'm going to go ahead and press enter now we're going to get a new run latest and now the type two is back so this is showing that these transactions are actually different types so there's actually several different types of transactions in the evm and arvm ecosystem so there's actually several different types of transactions in the EV M or the ethereum and the ZK sync ecosystem we do a little bit of a walk through of these different transactions in a phenomenal blog that we have on the cipon blog site and the ZK sync docs also do a great job of walking through the different transaction types so on ethereum on ZK sync on all these chains the original type of transaction was didn't have a name it was just called like transactions there was only one type of transaction however the E ethereum and the evm ecosystem quickly decided oh having a single type of transaction isn't that helpful we probably need to support multiple different types of transactions so they created an ethereum improvement proposal called type transaction envelope and don't worry too much about eips or these numbers or anything like that for now but basically they improved ethereum they approved the evm to support multiple transactions and all the original transactions they just called Legacy or type zero transaction then they created a type one transaction which had this access lless thing we had this EIP 1559 or type 2 transaction which as of recording is the default transaction so that's why in Foundry when you don't specify that-- Legacy flag it automatically sends it as a type 2 transaction if you add the-- Legacy flag it'll send it as a type zero transaction now each one of these transactions have slightly different parameters and they look slightly different again you don't need to worry too much about this now I really just want to tell you there are several different types of transactions the other thing is back in our remix back when we were deploying to ZK sync when we hit the deploy button we had this weird signature thing come up we had another transaction type if you looked at the metamask it was a little bit weird because we signed something in our metamask but we didn't send a transaction and if you looked in your metamask we had another transaction type type 113 or 113 I'm going to go ahead and reject this if you go to the ZK sync docs they do a great job of explaining type 113 where this is one of ZK sync superpower where they have this account abstraction type transaction 113 or 0 x71 this is the hex of 113 this is a transaction type specific to the Z kync ecosystem and many different ecosystems have different types of transaction types however pretty much all evm ecosystems have at least type zero type 1 type two with type two or EIP 1559 being the default again if these eips and numbers are kind of feeling like I'm pulling magic words out of a hat we'll explain eips and erc's later on in the course now as I said you don't need to remember or understand everything that I'm saying right now just the takeaway that I want you to have is that I want you to know there are different transaction types in these e these evm and these zync ecosystems if you see the-- Legacy flag being passed you know that you're passing a type zero transaction if you don't have the-- Legacy you're probably going to be working with a type two and I say probably because there are scenarios where you're going to work with a type one or a type three or a type Etc so now you know there's different types of transactions under the hood all right so a little bit earlier in this course we deployed to sepolia and then we just taught you a lot about working with ZK sync one of these rollups one of these l2s and actually deploying to spolia deploying to that testet actually simulated something what we did actually simulated deploying to the ethereum chain itself deploying to a layer one deploying to one of these chains or really deploying to ethereum which is great how however there's something we want to keep in mind like I like I've said earlier in this course most projects nowadays they don't deploy directly to ethereum First they'll deploy to an L2 or a layer 2 or these rollups as Kira has gone through for us and if we go into our broadcast folder right into our 1155 again if you haven't actually deployed to spolia don't worry just kind of follow along with me if we scroll into this run latest we can see this Gast used section and we can also see this effective gas price but let's look at the gas used so we can convert that gas used HEX number back to a real number with cast to base paste it in deck like so and we'll see we used this much gas to deploy this smart contract cast to base is a tool that converts a hex number to its decimal equivalent or its numerical or integer equivalent often times in the blockchain world numbers are represented and their hexadecimal formats instead of the actual number formats so when we saw the gas here this 0x5 747a is the hex version of the number 357,96 so that's why we had to do that conversion here now we can actually estimate how much this would cost us to deploy this to the ethereum mainnet on the test net Explorer I can scroll down in here and I can see how much this would have cost me oh by the way you can see that transaction type here again we can see that we used this much gas okay that looks like it's exactly what we got in our Foundry project okay cool we can see we have some gas fees here and then we can see the final transaction fee how much it costs right here which going to be the gas price times gas used okay so this is the gas used this is the gas used and this was the gas price so what we can do then is we can take this gas used and we can go to Ether scan and we can go check kind of the most recent gas price of different transactions so we can just pick kind of the most recent block we'll go pick any transaction hash we'll scroll down to more details we can see okay gas fees okay gas price is right here so what we can do then we can pull up our little calculator and we can do the gas used of creating that simple storage contract times at 5.15 I mean we could put the rest of it but that's the approximate gas price and this is the final value that we get so this is how much gas it costs to deploy this we can take this output that we get go to maybe ethon converter.com one gas is going to be aay so we can just kind of paste it in here we could see the total eth amount and then if this site doesn't update we can just be like eth to USD converter and we can basically finally arrive at how much money this would cost if we were to deploy this to ethereum just deploying this contract would cost us $7 and this is a very tiny minimal minuscule little contract here this is it right this isn't a big contract and there's code bases with thousands and thousands of lines of code and this has like less than 30 and it cost us $7 so contracts deployed to the ethereum main chain as a recording cost thousands or tens of thousands of dollars and this is why a lot of people don't deploy to the ethereum main chain because of how expensive it is and this again goes back to why rollups are so important using the ethereum chain can be incredibly expensive which prohibits a lot of people from using it so a lot of applications a lot of people deploying smart contracts they don't want to deploy to ethereum because if it's expensive for them it's expensive for everybody else but they want the security of ethereum so they go ahead and they deploy to an L2 so now I'm not going to show you how to deploy this to zync sapoia but if you wanted to the process is going to be pretty much identical to deploying to that zync locally running node the only additional piece that you would need of course would be an RPC URL for ZK sync sapoia we can actually get one of those from our friends over at Alchemy if you've already gone and signed up with Alchemy and if you don't have an Alchemy subscription a number of other RPC or node providers also support ZK sync like quick node for example so to get a ZK sync sapoia RPC first we would go back over to Al Aly we're going to sign back into Alchemy and we're going to create a new API key on Alchemy so we're going to go ahead and apps create a new app we're going to switch now to ZK sync we're going to do ZK sync sepolia and maybe we'll call it like testing testing like this and same thing in here we're going to select the API key and we're going to grab this https API key for the Alchemy ZK sync we're going to come back to remix and EnV although you now know you're not going to do this private key in the EnV anymore uh but what we can do is we can say ZK sync sepolia RPC RPC URL equals and then paste that in there so now we have this new RPC URL that we can use so if we go to this site L2 fees. info this will give us a better understanding of how much doing different operations costs we can see on ZK sync era which is the chain that we've been working with a lot sending costs less than a penny a lot of these l2s are substantially cheaper versus something like ethereum which is going to be substantially more expensive which is why we want to deploy to these l2s in the first place and if you did follow along with us let's just do a little Foundry up just so that we're back on vanilla Foundry instead of Foundry ZK sync now Alchemy has a couple of other really cool features about it especially when it comes to learning more about what what's actually happening with our transactions whenever we send a transaction to a blockchain node it actually enters something called the mempool it's basically the place where transactions go before they get actually sent and the Alchemy dashboard is a great place to actually view those transactions and see their status so I'm going to go ahead and turn it over to veto from the Alchemy team who's going to explain more about what Alchemy has to offer some of the other cool parts of alchemy and more ZK Stark ZK n ZK proof z Oh W oh I'm I'm sorry I'm gam gam everyone and welcome to this brand new video I'm V and today I'm going to walk this is not my channel this is not even AR's Channel where the oh my God this is the latest Patrick Collins video about Foundry that everyone must watch oh well welcome everyone I am VTO and thank you Patrick for Austin this came I guess my job today is to tell you a bit more about what Alchemy is what we do how we do it and how you can get the most out of it well before getting started let me quickly quickly introduce myself I am BDO lead developer experience at Alchemy block hand developer and web free content creator on a mission to on board one million developers on the web freame of course today we're not here to talk about me but we're here to talk about how Alchemy can add pure decentralized applications scale to billions of users so to get started what is alchemy well Alchemy is a node provider and web free developer tooling platform bwing hundreds of thousands of web fre and web CH applications out there things like openc Nifty Gateway but also zerox Argent Dapper but as well as big massive web two companies such as Adobe Shopify and stripe the question here probably is why do this companies use us why Alchemy well that's the question we try to answer here briefly the thing is when you need to develop an application chances are you won't run the servers you'll code your code will run on and most likely you won't even develop the deployment and integration pipelines for it to do this you will use services such as AWS Azure Google Cloud well Alchemy does exactly this but for web free you can see it as the AWS of web free with apis sdks libraries that will simply make your developer experience better but how do we do that well we do it in mainly three ways the first one is the super node a blockchain propriatary engene that acts as a load balancer on top of your node and make sure you always got the latest available data from the blockchain on top of the super node we built the announced apis the announced apis are a set of apis that will allow you to pull data from the blockchain with ease here you can see how we envision this with the Alchemy supernode at the center as has the core infrastructure powering its ecosystem all around such as our enhanced apis but also our monitoring tools and of course supporting all the chains that we support to date and we get back to it in a few seconds but the question is of course how do you get started well the first thing that we're going to do is navigate in on alchemy.com and we're going to create a new account creating an account on alchemy.com is completely free and actually cool thing is that you'll be able to scale your application using our free plan because it's quite generous so don't be concerned about paying anything everything you'll see today and probably in Patrick's course is completely free to use let's go back at creating a new account in this case I would just sign in of course I already have an account so I will click on sign in and as soon as we'll open this window you will see all of your applications of course if this is the first time you log in in on Alchemy you will only see the demo application but no worries we're going to learn how to create a new application right now super important click on create app and let's give it a name so we're going to call it Patrick is cool and I'm going to use underscores just because of personal preference feel free to use spaces or name your application the way you want we're going to also give a description this is optional you don't have to but I really think that Patrick is cool and then we're going to select a chain as we said before we support the majority of evm compatible chains as you can see here we support ethereum polygon P also gkm as well as optimism and AAR and on top of that we support Solana and non evm chain here you can select your chain and here you can select your network in this case we will go for etherum main net but feel free to try out all the other networks and test Nets of course we have one for all of these U main Nets that we support so I will create the new app and once the app has been created I can just go and search for my name so so Patrick is cool and click on my application here we go once the application has opened you will be able to see the application specific dashboard and this is a big change big game Cher for all de centralized application developers because this gives you full visibility over your application and infrastructure Health you'll be able to see things such as latency compute units that that is how many RPC calls are eating your notes as well as the success rate of your calls the throughput and so on and so forth super useful when you need to debug so let's say that here you see 98% of success rate you'll be able to understand why your transactions are not going through well let's actually do an example let me go back and find an application that has actual codes so here we go I just navigated to this demo key application that as you can see has a ton of calls but also as you can see it has a success rate of 98.5% that means that 1.5% of our calls are failing to go through but how do you understand that how do you debug this well if you not using Alchemy chances are that to debug your RPC calls you will have to spin up your own nodes or be run a local node and in that case you'll be able to see the logs coming from the node otherwise there is no possibility to see the logs coming from the node this is not something you will see on E scan using Alchemy you'll be able to see all the issues related to your calls as well as the known issues related to your calls in this dashboard so let's say that we have 1.5% of calls not going through what we can do is go on the recent invalid request dub and here all the requests that didn't go through will be listed as well as the reason why they didn't go through for example here we have an e Sand Road transaction that didn't go through because there weren't sufficient gas funds well let's take another one here execution reverted for example means that probably there is a problem with the smart contract so as you can see the bugging as well as you can see other information on the left hand side but I will go back at this in a few seconds because I want to show you another tool that is even more precise to see the information about the acttion request here you'll be able to debug your RPC calls with super Ease on top of that as I was saying we have other tools to help you debug and get more visibility on your application so if you click on the menu and here what we can do is navigate on the M Pool and the manool is actually just like the manool that you might think about when you're thinking about ethereum so it's a place where all of your transactions are and you can see the status of the transaction the information about the transaction what if the transaction is going through if didn't go through if it's spending for hours if you got mind how much it cost and so on and so forth so let's say we we just navigated on our Mano Watcher and here we have all the transactions going through on our applications here I have a bunch of applications so that's why I'm seeing a lot of transactions here on the top you can see all the Mind transactions so the transactions that already went through that can be mined or validated the pending transactions um let me just select one application because of course otherwise it's going to take a long time here you have all depending transactions that mean all the transactions that are waiting to be mined or validated and here you have dropped and dropped and replaced so transactions that have been dropped cancelled or replaced by other transactions with the same non same call data and the same gas fees or dropped means there are transactions that have been cancelled and won't be validated or Min but on top of that you can get even more information on these calls on these transactions if I click here on the ash this won't bring me on eths Canal will bring me on the manool transaction summary page and here I can see all the information about the transaction I can see how much gas it costed uh which network it was on of course uh the transaction transaction hash as well as the from address so who send the transaction and who's sending the transaction to as well as the value inside transaction the time it took to get sent and the time it took to get um validated this is more clear on validated transactions where everything has already be filled out so I can go back in my mind page so here we go I can select one and as you can see here I have all the information so I have Max Fe per gas I have the transac type so this was using the EAP 1559 and a bunch of other information about the transaction itself super helpful to debug and get full visibility over it all right now that we have quickly gone through how Alchemy Works what it is and how it's features can help your developer experience become way better and develop faster I don't want to steal much more of your time while learning during this amazing course so what I'm going to do is leave you with a couple of resources that will make your developer experience with me even better the first one is our documentation so our documentation has everything you need to get started using our apis SDK libraries and also tools that we didn't have the time to go through today such as our generalized custom graphql web books that allow you to pull data real time from the blockchain through graft queries on top of that you will also have tutorials and guides to build your applications and complement the knowledge you're creating during this course of course follow us on Twitter Twi at Alchemy platform or Alchemy learn and if you want to shoot me a message telling me the amazing things that you're building while learning from the Patrick course please shoot it at vdock on Twitter thank you so much Patrick once again for hosting us and thank you everyone for sing with us for 12 minutes it's been a pleasure see you around and happy building but for this one you should be incredibly proud of yourself you just did an entire project in Foundry huge congratulations so let's do a quick recap of everything we learned and then we'll move to the next project and yes we are going to push our next project up to GitHub and do a lot more advanced Foundry and a lot more advanced tooling here so let's do a quick recap of what we learned so far well first we learned how to create new Foundry projects with Forge Das Dash and knit which will give us all of these folders on the left hand side here to actually start working with our projects in a more professional environment we learned about some of the basic Foundry commands such as cast Anvil and Forge Forge is used for compiling and interacting with our contracts cast is used for interacting with contracts that have already been deployed and Anvil is used to deploy a local blockchain similar to ganach which is another local blockchain that we worked with we learned that whenever we send a transaction on our metamask we're actually making an HTTP post request to this RPC URL and we can also take an RPC URL from a no as a service like Alchemy and use it to actually send transactions from our Foundry prodct projects we learned both how to actually compile our code in Foundry and then also write a script to deploy it directly in solidity we've learned some very basic information about keeping our private Keys safe for the rest of the course we're going to be working with aemv file but when we work with real money we might not want to actually have our private key in plain text ever so we learned how to deploy our contracts to a blockchain programmatically and then we learned how to interact with them using the cast keyword and send to send transactions and then cast call to read from those contracts we've learned how to autof format our contracts with Forge format and we learned the manual way to actually verify one of our contracts on the blockchain we learned a lot here so be absolutely sure to take a minute to go on a walk go get a cup of coffee go grab some ice cream go post on Twitter that you've taken an extra step in your web three developer Journey you should be incredibly proud of yourself for getting this far like I said earlier installing some of these tools like vs code and Foundry can be one of the hardest parts of this entire course so if you're in here if you're working with me you're doing fantastic we've got a lot more to go but just by getting this far you've done incredibly well so with that being said take that break remember breaks are good for your brain take that break and we'll see you in the next one all right now welcome to lesson 7 The Foundry fundme if you're on the GitHub repo assisted with this course you can of course scroll down to lesson 7 here and the code is all going to be right here this is going to be the first codebase that you actually push up to GitHub your yourself doing this is an incredibly important step in your smart contract Journey yes being on GitHub or gitlab or radical or some Version Control System like this is incredibly important for being a part of the web3 ecosystem we're going to be using GitHub because it's the most popular at the at this time so let's do a little walkr of what we're actually going to be building here we're going to be using the fundme contracts that we created before and if we go into the SRC of this folder you can see we have our fundme contract in here and you can see we're using the more advanced syntax here we've got all caps for our constants we're using icore for our immutables sore for storage or state variables and I know we talked a lot about storage and state and we didn't really explain what it was though and so additionally we're going to finally learn what this storage stuff really means and we have an example that we're going to go through called fun with storage we're going to learn how to in a professional way deploy this code using Foundry scripts we're also going to learn some really cool stuff about interacting with storage we're going to learn how to make it easier to deploy these contracts on different chains that require different addresses and we're going to learn how to use Foundry scripting to actually interact with our contracts in reproducible scripts instead of always from the command line we're going to learn how to make our contracts more gas efficient so that people spend less gas using our transactions we're going to learn a little bit more about Advanced debugging techniques and more on making a professional Foundry setup and additionally we're going to learn how to write really fantastic tests for our contracts writing tests is an essential piece of becoming a powerful and effective smart contract engineer so a lot of this lesson we're going to be writing awesome tests when you get to the end of this project you should 100% push this up to your personal on Twitter on LinkedIn on lens protocol whatever because this is going to be a huge huge step in your journey and and at the end of this you're going to understand what all of this code does and be able to use it and talk about it effectively and just a quick note to make this and just a quick note to make sure you absolutely smash this project out of the park we're not going to be deploying to ZK sync or worrying about deploying to an L2 let's just 100% get you to the end of this so that you can push this up to your GitHub get that portfolio going and be incredibly excited for this and then we'll learn how to deploy one of these more advanced smart contracts to ZK sync in the smart contract Lottery which is going to be outstanding so with all that being said let's go ahead let's jump into the code and let's start building our Foundry fundme all right so here we are in our vs code and we're in our Foundry f-23 folder which if we type LS right now we just have our Foundry simple storage this is the only folder that we've created so let's create a new one we'll do mkd which stands for make directory Foundry fundme f23 and hit enter now if we hit LS which stands for list we can see these two folders and we can type code foundary tab fnd tab and it'll autocomplete and we'll hit enter and this will open up a new vs code in that folder which of course is going to to be blank now if I pull our terminal back up we can run and we pull up the Explorer we can run our Command to initialize a blank Foundry project so we can do of course Forge init or Forge in it-- force and we get our basic project setup here fantastic so we have some tests SRC and scripts we know what SRC is we haven't worked with tests but we have worked with scripts most of the time Foundry will come default with this counter thing and if your Foundry doesn't come with these don't worry just watch for now but if it does you can play along with me if we look in SRC or Source we see this counter. so contract it's a very basic contract we have a set number which takes a un 256 new number as an input parameter and changes this storage variable to whatever that new number is we also have this function increment which just uses this plus plus syntax this Plus+ syntax is equivalent to saying number equals number + 1 so whenever we see Plus+ that's the same thing as number equals number plus one we have a script here which doesn't really do a whole lot of anything but we have this test which we haven't talked about testing our smart contracts and testing our code is absolutely essential to being a top blockchain engineer you'll see out throughout the rest of this course we're actually going to spend a decent time inside of this test folder inside of this test file testing our code testing our smart contracts and if you run Forge test in your terminal and you do have this counter. T.O what it will do is it'll compile all of our code and then it'll run these tests from this test file so we see two test pass for this test file and they're going to be test increment which is a function here and test set number what the test keyword does is it runs this function in our test file it runs all the code inside of here and it checks to see if some assert is accurate so what this test does is it first calls this setup function so it'll deploy a new counter contract sets the number to zero and then increments that number by one and then we check to see okay well is the new number of counter equivalent to one so this assert equals saying hey is this equal to this and since we increment the number bar one these do indeed this is indeed true these two are equal so that's kind of the basic rundown of this test file we're going to be going over it a lot more very soon so to keep going let's go ahead and get this set up the way we want we can delete these three counter files because we don't need them we're going to be using our own contracts now for this section we actually want to start from Lesson Four remix fundme we don't want to copy paste from our Foundry fundme this is because we're actually going to modify our Foundry fundme a little bit to make it a lot easier to write test and interact with so for now we want to go to the remix fundme and copy paste the contracts from here so we'd come copy this whole thing go to SRC let's create a new file we call this fund me.so paste it in here paste it into fundme and then go back we'll go over to price converter we're going to do the same thing we're going to copy this whole thing going to make our price converter doou paste it in here like that all right great now if we try to compile this right now though Forge build or Forge compile you'll see we get some errors get a few errors un we see compiling unable to resolve Imports at chain link contracts blah blah blah it's having a hard time with both of these Imports in remix when we do this at chain link contracts remix automatically reaches out to the mpm package repository however Foundry doesn't do this we need to be very explicit and tell Foundry exactly where we need to pull our dependencies from and we actually need to download this directly from GitHub there's a package out here called smart contract kit chain Le brownie contracts that has all of the contracts that we need and this is the GitHub repository that we're going to pull from I'm going to go ahead and use 1.1.1 because because as of recording that's the latest release however throughout this video you might see references to 0.6.1 when I originally made this course a year ago that was the most recent version so I've updated as of recently to this more recent version that's why sometimes in the codebase you'll see this shared folder here and sometimes you won't so if you see that discrepancy that's why you're seeing it so what we're going to do is we're going to copy this link and go back into our terminal and we're going to say we're going to install this dependency with Forge install and actually we don't need the whole link we just need the name of the org and the name of the repository so it's going to be smart contract kit Chain Lake brownie contracts Forge install paste that in here and most of the time you're also going to want to add this D- no commit and just to make sure that we're working on the exact same version you can also add this at sign here and shoot use a version in the releases tab I'm going to use 0.6.1 since that's the latest version 0.6.1 for now just Auto default to adding this-- no commit you'll learn about why we need to add that later but let's go ahead and hit enter and now it's going to say installing chain Le brownie contracts and it it give you the path to where we're actually installing them if you want to download a very specific version of the chain Le brownie contracts or any pack page you can just add the version number at the end of the install so we can do Forge install Smart contract kit SL chainlink brownie contracts or we can do the full GitHub name at 1.1.1 D- no commit D- no hyphen commit like this and that will install this exact version here you can also do it without the full GitHub link so we can do it just with smart contract kit chain Le Browning contracts like this and that will do the same thing so in a lot of this video we're using 0.6.1 however the GitHub repo as of today is 1.1.1 so just keep that in mind as we're going along so just keep that in mind as we go on here if we go to our Explorer now and we open the lib folder we can see we now have Forge STD which comes default with Foundry but we also have chain link brownie contracts and if we click into here and we click contracts we can see all the list of all these contracts that come with downloading that package so now we have all these contracts locally in our own environment and in here of course is going to be our aggregator V3 interface. soulle it's in contracts SRC v0.8 interfaces aggregator V3 interface. so we can go ahead and import from here but we need to do one other thing right now in our contract we're saying import aggregator V3 interface from at chainlink contracts we need to tell Foundry that at chainlink contracts should point to this lib folder so we need to create something called a remapping in our founder. under profile. default we can create a new section called remappings Equals we'll do this for now and if you want to see the entire list of possibilities I can go in here you can click this link that comes with the repo which brings you to this config section and it has all these different endpoints and all these different parameters we can use in our Foundry doc config yep there's a lot of them but in this remapping section we're going to put some text we're going to tell Foundry hey anytime you see at chainlink SLC contracts that should equal or you should redirect or you should point to the lib SL chain link brownie contracts SLC contracts fer so we're saying hey Foundry if you see this replace it with this so in fund me.so it's equivalent to US swapping this out with the path to chain L bring contracts in the library cool now of course if we try to compile clear Forge build or Forge compile we still get an error because can't find price converted. Soul so let's do the same thing let's go back to the GitHub repo associated with this course go to SRC price converter and let's copy this whole thing folders new file price converter Doo and we'll paste it in here now we'll hit clear we'll do Forge build and awesome compiler run successful we can see we've got our little out folder with all this stuff in here about all the compiled stuff fantastic all right great also so it's a best practice when you name your errors you name them with the contract name and then two underscores this way when you do get this error you can very easily tell what contract it came from in this case it came from the fundme contract so this is just a nice convention for error handling so now we have our contract actually compiling correctly next normally we'd go ahead and write our deploy script but let's actually get used to writing some tests and we're going to refactor these tests a couple of times so stay with me here you ready all right let's write our first test and like I said tests are absolutely critical for our smart contract development journey and if you try to deploy your smart contracts without test or go to a Smart contract auditor without test they're going to turn you away you absolutely are not writing mature code if you're not doing tests and writing badass tests separates a lot of the mediocre devs between the really good devs so let's write some badass tests for now we're just going to go ahead we'll create a new file we'll call fundme test. T.O thist doso is just a convention in solidity for saying hey this is a test file so fundme test. T.S soul and we're going to write our tests in here in solidity exactly as we would write any other solidity contract so we're going to get this started exact same way we get anything else started so we'll do spdx license identifier MIT my GitHub co-pilot automatically recommended that so I just went ahead and hit tab prag my solidity GitHub co-pilot again give me some decent recommendations and then we can say contract fund me test now the forge standard library has a couple of standard packages or standard contracts that we can import to make running our tests easier that assert command for example is something that Foundry automatically has built in so for now we'll do import test from C d/st test. and we'll say fundme test is test so we're we're going to inherit everything from this test contract and if you command click into here you'll see this abstract contract test is a whole bunch of other stuff and these are all different contracts that help us write our tests so what's the first thing that we should do when we write our test well we want to test that our fundme contract is doing what we wanted to do so one of the first things that we're going to have to do is actually deploy that contract now pretty soon we're going to learn how we can actually import our deploy scripts in here to make our deployment environment the exact same as our testing environment but for now we're going to just deploy our contracts right in this test folder so we're going to say function setup external like this and on all of our tests the first thing that happens is this setup function and in here is where we're going to actually deploy our contract now I do want to show you something though here's what one of our tests is going to look like we're going to say function test demo we'll make this public I'm doing this just to have a demo test if this is your entire test file and you pull up our terminal and we run Forge test you'll see it'll run this and everything will pass oh I should spell external right now we run this we'll see compiler run successful and we'll see test demo went ahead and passed here how however setup always runs first for example if we have VI 256 number equals 1 and then setup we say number equals 2 and then we run test demo where we say assert equals number and two there and run our test we'll see this indeed does past so we first run our setup function and then we run our tests another way to actually test this and actually do some debugging is using something called console.log so if you control click if you command or control click or just command P to test. Soul this test. sole is a huge file and another library that it comes packed with is this thing called the console you go to the forge documentation talks about this thing called console logging and we can actually do print statements that will print stuff out from our test and from our smart contracts so if I import this console into here and then I do function test demo public and I do console.log number I should get printed out to our terminal the number associated with number which should be two I can also do something like console.log hello an exclamation mark now if I pull up the terminal let's clear what we have so far and we run Forge test- VV this- VV specifies the visibility of logging in this test we can have 1 2 3 four or five we're just to go with two right now we should see those two logs output and we do indeed we see a new section of our output here where we have logs and we see two and hello we minimize our terminal we change this to hi Mom P the terminal run it again with the- VV we now indeed see two and hi Mom and this can be an easy way for us to start debugging but it's something I wanted to show you just to show you again hey this runs first and then this runs we're going to leave console in here for now because you're likely going to want to use it later when you run into issues and when you start debugging yourself all right great so now we know how to write a basic test and how the test actually gets set up and we know a little bit about console logging let's go ahead and let's deploy our contract in this setup function so in order to deploy it we're going to have to obviously have this contract know about it so we're going to say import fundme from we're going to go down a directory so we're going to we're going to go so the two dots stands for going down a directory because this is in fundme so we go down to to this overall file and then we're going to go slsrc slf fund me.so and GitHub co-pilot and vs code or actually even helping me out a little bit there now that we have our fundme we can actually deploy this in our setup and then actually let's get rid of these lines because we don't need them anymore so in our setup now we're going to say fund me fundme right and so this is a capital F this has a lowercase f these are slightly different equals new fundme fundme fundme equals new fundme right a little confusing but we're saying our fundme variable of type fundme is going to be a new fundme contract and if we go to our fundme we go to the Constructor here we can see that it doesn't take any input parameters so we can actually just go ahead and deploy this as we see fit those of you watching though know that this address here only works for sapoia and we'll see how we can work with this in a little bit but we've actually deployed our fundme contract like this now in our demo we can test this fundme contract and we could pick a function or a public variable to check to see if what we're working with is good so for example since minimum USD is a public variable we could check to see if the minimum USD is indeed five or 5 * 10 is the 18 or just you know 5 E18 so what we could do in our test demo we could see we could change the name of this to test minimum dollar is five I like to make my test names very verbose to explain exactly what they're going to be doing but in this function here we would then call this minimum USD function and make sure that it's equal to 5 or 5 E18 in order to call this we need access to this fundme and since it's scoped in the setup let's go ahead and make it a storage or state variable by putting it here and initializing it in the setup so now that we've scoped it in this entire contract we can now do fundme minimum USD and this test contract gives us access to this assert equal function and we can just wrap our whole test up like this so now that we have this we can pull our terminal back up and run Forge test and fantastic we see compiler run successful test minimum dollar is five is now passing great if we change this to six we should see that actually fail so running Forge test now we'll see that it indeed failed because the starting minimum USD is five and we're trying to check to see if it's six so let's change this back to five clear the terminal rerun the terminal and boom compiler runs successful awesome you just run your first basic test great job when you're working with systems where you don't have to work with any external contracts just continuing to write your test like this is a great practice and with the Advent of AI we can go even further with this so let's go ahead and write another test maybe let's check to see that the owner is actually the message. sender so what we'll do is we could say function test owner is message sender public and we can say assert equal and this is the another good thing about writing very verbose tests it gives GitHub co-pilot a better idea of what you want to do I'm actually going to go ahead and hit tab again here but assert equal message do excuse me assert equal fundme iore owner is equal to message. Sender what I can do now let's go ahead write Forge test compiler successful uhoh it looks like this actually failed how can we find out why this failed or what's going on well we can do a lot of different things here we learned recently about console. logs so we could console.log out the actual [Music] owner and console.log the message. sender as our starting point so let's go ahead and clear that Rerun Forge test with two v's so that we can see our console.log outputs huh we can see that indeed these are two different addresses the reason they are two different addresses is technically in our setup function the fundme test is the the contract that deployed our fundme address and would be the owner down here our message sender is whoever's calling the fundme test so it kind of looks like this us is calling fundme test which then deploys fundme up here this fundme bit is basically us calling to fundme test which then will deploy the fundme so the owner of fundme is actually fundme test and not us down here we shouldn't be checking to see if message. sender is the owner but we should be checking to see if fundme test is the owner so instead we could say address this and delete these let's see if that works aha that's exactly what the issue was great job so you'll see how using some of these console. logs can be helpful and like I said we're going to going to continue to find more and more helpful ways to write tests but let's take a pause on these tests for now because we're going to come back to them and refactor them pretty soon if you've written just these tests great job and if you want to even pause and try to write some more tests yourself feel free but we're actually going to run into an issue one of the issues is that we're hardcoding this contract address in here and this contract address only exists on saoo but we're testing on not aoia we're testing on our local chain so how are we going to deal with that keep that question in the back of your mind as we continue with this section let's go ahead and let's move on to writing our deploy scripts because we know that we're going to have to deploy this at some point anyways so let's go ahead let's Sate a new file called deploy fund me. s.o remember the S is a convention that we use to say something is a script and in here we're going to do the same thing spdx like since identifier MIT I went ahead and hit tab feel free to slow me down if I'm talking too fast or the tab are too fast co-pilot also gives me the pragma solidity now we're going to say contract deploy fund me like this and remember since we're using a script in Foundry we're going to need to import script from Forge STD script. Soul once again GitHub copilot thank you for letting me just hit Tab and of course since we're deploying fundme we're going to need to import fundme from do srcf fund me. Soul great as we know in order to run a script we're going to say function run and remember if this is confusing to you feel free to go back to our lesson six to remember how we did this before this is going to be an external function and in here we're going to say vm. start broadcast fundme lowercase fundme equals new fundme and then we're going to say vm. stop broadcast and we can go ahead try to make sure this runs by running Forge script script deploy fundme dos. Soul oops it's saying I can't find the VM keyword that's because we need to do is script it's clear let's redo unused local variable oh we actually don't even need this line we can just say new fundme we don't love warnings so let's just do this again hopefully we get no warnings and great compiler runs successfully script ran successfully if you wish to simulate onchain transactions pass an RPC URL so fantastic now what's one of the most important pieces of our fundme that we should absolutely get right well obviously the funding we want to make sure that this conversion rate is actually working and in order for this conversion rate to actually be working we need to make sure that we're actually able to get the version from our aggregator V3 interface we're able to interact with them correctly let's use this get version function to try testing if our price feed Integrations are working correctly we know from remix that this get version should return version 4 so what we can do is we can go back to our test now and write a new test we say function test price feed version is accurate this and we'll say now we'll say fundme dot get version like this this should return four and that's a u and 256 so we could say U and 256 version equals funme me.get version and then we could say assert equal version 4 what do you think will happen when we run this test do you think this will pass go ahead pause the video and write down what you think will happen well when we run Forge test we actually get an evm revert huh why did this revert we don't really have that much information now something that's really annoying is that we're still running these tests and we don't care about them so what we can do is we can double click this function copy it let's clear the terminal we can do Forge test- M paste this in here and now it we only run that single test awesome but we still don't have that much detail in here okay let's clear let's change the visibility using 2vs okay that didn't really do anything let's use prees oh now we got some more information here it looks like we get a what's called a stack trace of the error that we're getting and it looks like we're calling our fundme test we're calling this test price feed version is accurate we're calling get version and that get version is reverting doesn't tell us why it's reverting but we know that it's reverting because we're calling a contract address that doesn't exist remember when we run tests in Foundry when we don't specify a chain Foundry will automatically spin up an anvil chain and then delete it right after the test is done so when we run Forge test and we don't give it an RPC URL it's going to spin up a completely new blank Anvil chain and run our tests and we're making a call to a contract that doesn't exist so obviously we're going to get an error because nothing exists at that address so what can we do about this well we can do a couple of things and in this course we're going to talk about four different types of test unit integration forked and staging Fork can kind of be considered like a unit integration add-on but I think it's important to call out as something a little bit different here this is something known as a unit test a unit test is where we test a very specific piece or a specific part of our code for example here we're testing a single function we're testing Tes in get version we're testing to make sure that works correctly so that's going to be considered a unit test however one could argue that it's also an integration test because we're testing this function works and this function actually calls out to another contract so in this case we're testing actually multiple different contracts are working correctly together a fork test is when we test our code on a simulated real environment and we'll talk about this soon and staging test is actually when we deploy our code to something like a testet or even a main net and run all of our tests in that Real Environment to make sure things actually work correctly these are all important and they have different tradeoffs and they have different best times to use them for the purposes of this course we're going to focus on number one kind of number two and especially number three we're not going to do too much staging tests in this course however it is definitely something important definitely something to consider I've seen protocols skip this step and get screwed because their production environment was completely different than their testing environment and I'll explain what this actually looks like in a little bit but let's go back to the problem that we're working with here what can we do to work with these addresses outside of our system how do we test our test price feed version when we're working with Forge and Anvil well one thing that we can do is when we run our Command here we can pass what's called a D- Fork URL and we can go back to Alchemy we'll sign back in and go to our we'll grab our API key and just so that we'll have it we're going to create aemv say set polia RPC URL equals that and we're going to make sure the EMV is in ourg ignore okay great and then actually let's run source. EMV so now if we run Echo sepolia RPC URL we see that we're successfully using this as an environment variable but if we hit up a coule couple times we can now run this test price feed version is accurate with a D- Fork DL dollar sign sepolia RPC URL this is how we access our sepolia environment variable and what will happen is Anvil will actually get spun up but it'll take a copy of this seoa RPC RL it'll spin up in Anvil but it'll simulate all of our transactions as if they're actually running on the seoa chain so it'll pretend to deploy and read from the aoia chain as opposed to a completely blank chain so if I run this now what do you think will happen whoa we see we go ahead and we get an okay here we can see we're getting returned the hex value of four and we can see that in our test here we're actually getting four returned and if we go over to our Alchemy node we hit a little refresh here we can scroll down and we can see recently we made a whole bunch of calls to our Alchemy node when we use a for URL we're going to simulate what's on that actual chain and this is a great way for us to easily test our contracts on an actual Network now the downside of doing these Forks is that you're going to make a lot of API calls to your Alchemy node which can run up your bill which is why I still think I still think it's important to write as many tests as possible as you can without forking but there's going to be a lot of tests that you have to run that can only be done on a fork or using mocking to make sure that we get plenty of coverage to test all of our contracts and that's another interesting thing that you hear me talk about is coverage so if we delete all this we can also run this thing called Forge coverage and then if you do D- RPC URL or Fork URL those are the same thing and we can actually see how many lines of our code are actually tested so for I un Forge coverage with fork URL we'll run our entire test suite and then we'll actually see how much of our test Suite how much of our code is actually tested right now as you can see a lot of our code is red and not tested right fundme doou has barely any tests price converter doou has barely any tests we want to get this up as high as possible now sometimes it's infeasible or doesn't make sense to bring this up to 100% but 16% is incredibly low as we're continuing with this course I'm not always going to write tests that bring us up to 100% And the times that I don't it's on you to actually try to see if you can bring the number up higher or if it even makes sense to bring the number up higher but in any case we're going to set up our contracts here to write an elaborate set of tests so that we can maximize our test coverage we can write unit tests integration tests Fork tests and staging tests and all that good stuff and if this is a little bit confusing to right now this is one of these times when I am going to say don't worry the more we work with it the more that it'll make sense to you just continue to follow along with me for now and it'll become clear as we do more of it now the thing is we want to make this process even more robust right now our contracts are hardcoded so that this will only work for sapoia sooa is the only chain that we can deploy this contract to and it's the only chain that we can actually test our contracts on that's incredibly restrictive and if we were to go to change our minds and deploy to a different chain we'd have to refactor our entire codebase we'd have to consistently update all the addresses in here both in fundme and of course in our price converter and it could take a lot more work to get that done correctly so what we really want to do is we want to make it such that whenever we deploy our contracts we deploy them in a way that's modular with addresses or external systems if we deploy our code with without hardcoded addresses like this we can actually make our deployments more modular deploy to other chains much easier and actually test much easier no matter what chain we're working on so we're actually going to do a little bit of refactoring of our core code base so that it's not just hardcoded to suoo so let's go back to the fundme oh and we actually want to do looks like I copied this wrong this should be fundme not owner like this but let's come back to the funme and let's update this so that we're not hardcoding the address here what we we can do is we can actually pass a Constructor parameter so that whenever we deploy this contract we deploy it with the address that we want to use and this address will depend on the network we're actually deploying to when you go back through your code and you change the way it's architected but you don't really change the lot of the functionality that's something called refactoring your code refactoring is something that's really good for engineers because it helps keep your code maintainable moving forward so in our Constructor what we could do is we can pass an address price feed as a Constructor parameter and up here where we have our state and storage variables we can create a new one aggregator B3 interface private sore price feed now what we can do is in our Constructor say S price feed equals aggregator V3 interface price feed so now down here where we're hardcoding the address we can actually just go ahead and delete this whole thing and do S price feed version call the version function directly on our price feed variable that we're passing in and additionally in our price converter we can update this function to take in an input parameter for this price feed address so for get price we'll just say as an input parameter it's going to take aggregator V3 interface price feed we're going to actually just delete this line and then for get conversion rate we'll have it also take an aggregator V and B3 interface price feed and then for this get price here we'll just pass it the price feed as an input parameter now back in fundme doou when we call get conversion rate we will pass in this price feed here so I know we just did a lot of refactoring but let's recap when we deploy this contract now we're going to take as an input parameter this price feed object if we were back in remix and we were to copy paste this into a remix here let's go ahead and copy paste both of them both the price converter and the other one let's compile fundme looks good and we were going to go deploy fundme we now see in this deploy box we have this address price feed as an input parameter that's exactly what we're going to be doing when we deploy our fundme contract here we're going to pass it a price feed and this price feed is going to depend on the chain that we're on so if we go back to our deploy fundme doou we now actually have an error it's saying oops wrong argument given you need to pass a price feed in here what we could do is we just stick the price feed in here and now and it should work of course in fund me. test we're also going to have to go and stick the price feed in here and this is where you're seeing there's kind of a lot of work happening every time we update how we deploy this right if I update how I deploy in my script I'm also going to have to update how I deploy in my test that's too much work and remember we're Engineers we want to do as much work as possible possible to be as lazy as possible additionally if maybe we update something in our deploy script over here and we forget to do it over here that means we're not going to be testing our deploy environment so how do we set this up so that anytime I change the way I deploy my contract I don't have to also change the way I do my setup function well what we can do instead of deploying our fundme contract ourselves in here we can just call out to our deploy function over here so let's update this this a little bit let's instead in our fundme test let's just import our deploy fundme contract from script deploy fundme s.o and let's just use our deploy fundme so that we always deploy in our test setup the exact same way we deploy in our script so let's update our run function to instead return a fundme contract and now we'll say fundme fundme equals new fundme and we'll say return fundme I know there's a lot of uppers and lower cases in here make sure we have it right returns and what we can do is in here instead of doing this line we could say we first create a new deploy fundme contract deploy fundme equals new deploy fundme because remember deploy fundme is a solidity contract and then then we'll say fundme equals deploy fund me.run because run is now going to return a fundme contract so now that we have this set up all we have to do is update how we deploy in here and our test will deploy it the exact same way every single time this is us being much more intelligent with the way we approach the architecture of our code base awesome and once again I love saying this but by you learning this you're already better than half the solidity Dev velers out there so great job excited that you learned this and just to make sure everything's working let's go ahead and run Forge test-- Fork URL deola RPC URL let's make sure everything's working correctly here and it looks like we broke something in our refactoring so this is good broke test owner is message sender ah well the reason that failed is because now our deploy fundme contract over here is actually doing the deploying and when you do this vm. start broadcast this makes the funer actually message. sender again it's a little bit confusing this is one where you don't have to worry too much about it right now but just know that instead of doing address this now we can actually go back to message. sender and now if we run our test again great we can see everything passes fantastic now the next piece that we're going to do is going to also help it help us so we don't have to always be making calls to our Alchemy node here we don't want to have to run up the bill every single time we run a test Suite we want to be able to do everything locally for as long as possible and not even have to make any API calls to Alchemy we do want to absolutely test our Fork URL but maybe not all the time so let's go ahead and clear tie the terminal and let's keep going and this is why it's good to have some tests before you even start doing refactoring this way you can make sure you don't break anything in the process but all right great so how can we update this now we said before the whole purpose of this refactoring was so that we wouldn't have to hardcode an address in here and sure enough here we are we're hardcoding an address in here this still only works with sapoia if I try to run this test without a forked chain it's just going to fail right because this test price feed version is accurate needs to make a call to a contract that exists so what can we do we can do something called creating a mod contract on our local Anvil we can deploy our own fake price feed and interact with that for the duration of our local tests and that's what we're going to do right now so to work with these mocks we're actually going to go ahead and in our script folder we're going to create a new contract called helper config doou excuse me. s.o and in this contract we're going to do two things number one we're going to deploy mocks when we are on a local Anvil chain and number two we're going to keep track of contract addresses across different chains for example spolia ethusd price feed has a different address or mainnet ethusd has a different address and if we set up this helper config correctly we'll be able to work with the local chain no problem and work with any chain we want no problem so let's go ahead and let's do this so this is a contract once again we going to need to do the SP spdf Tex license identifier MIT once again I'm using gith hope co-pilot which just let me do it by hitting tab we're going to do pragma solidity 0.818 I hit tab again thank you get up co-pilot contract helper config like this and this helper config is going to be a script which is why we have this s.o to signify it's a script so to do that we're going to do import script from for STD script. Soul like this and like I said what this is going to do we're going to say if we're on a local Anvil chain we're going to deploy these mock contracts for us to interact with otherwise let's grab the existing addresses from the live networks so let's go ahead and create this helper config which is going to set this up for us so that we don't have to hardcode this address in here and our test will work no matter what we're on a local chain a forked chain or a real chain so first let's create a function function and we're going to call it get theoa eth config like this this is going to be a public pure function and what this is going to do is it's going to return a configuration for everything we need in sapoia or really any chain all we need in sapoia is going to be the price feed address however we're probably also going to want one for function get Anvil eth config public pure which is also just going to need a price feed address but what if we have a whole bunch of stuff we need maybe a price feed address a vrf address gas price what if we've got a ton of stuff in here well this is where it's a good idea to maybe turn this config into its own type and how do we create types you got it that is with the struct keyword so we're going to create a struct keyword and we're going to call it Network config so we're going to create a new object of type Network config right now our Network config is only going to be one thing address price feed which is going to be the eth USD price feed address and we're going to have both of these return a network config object with this price feed so both of these are going to do that turns Network config and we have to use the memory keyword because this is a special object so we're going to do that for both of them now for get aoia eth config it's really easy right all we have to do is say Network config the polia config equals Network config and we'll just wrap and we'll just create this object by saying price feed and pasting in the address in here we config memory since this is a struct obviously we can use these little brackets here to say the type and the object we could also just do this right we could delete these and just go like this but I like to be a little bit more explicit so put these little squiggly brackets the name of the thing and then the address and then we can just say return toia config and now we have a way to get this aoo config so great so we have a way to grab an existing address on a live network using this how do we get that back over here so we can input into the funme well what we can do is we can create a new public variable Network config public Active network config and we can set this Active network config to whichever one of these configs is the active Network that we're on if we're on sepolia we'll return this if we're on Anvil we'll return whatever is in Anvil and then we'll have our deploy me just point to whatever the Active network config is so how do we so let's pretend for a second we are inoa how would we set the Active network config well in our Constructor what we' do is we'd say if block. chain ID equals equals 1115 55111 I'll explain this in a second Active network config equals get sapoia eth config now what is this chain ID thing okay well first of all we know that solidity has a lot of these Global variables one of these is the block. chain ID the chain ID refers to the Chain's current ID we saw a little bit of that with metamask and ganache and we can see that actually every network has their own chain ID on this site chain list. or you can see a list of a lot of these different chain IDs for example ethereum mainnet has a chain ID of one or 0x1 bance smart chain 56 arbitrum 46161 polygon 137 optimism 10 avalan C chain blah blah blah they all have different chain IDs soia has a chain ID of 111 55111 so we can just say hey if we on the sapoia Chain use the sapoia config great and then we can say if we're not on sapoia let's use the Anvil config fantastic so we'll say else Active network config equals get Anvil e config okay so let's try this out we don't have our get Anvil eth config identified yet we don't have it set up but that's okay let's just make sure that this get seole e config works with our forked tests so let's give that a whirl so let's update this now to work with our helper config so we'll do import helper config from Doh Helper configs dossou and what we're going to do is before the broadcast we're going to create a new helper config and get up co-pilot thank you again I just had to hit tab but helper config lowercase helper config equals new helper config so we're going to create a new contract like this the reason we're going to do this before or the star broadcast is we don't actually want to have to spend the gas to deploy this on a real chain so this is going to be a little bit confusing but you'll get used to this anything before your star broadcast it's not going to send it as a real transaction it's going to simulate this in it's simulate environment anything after start broadcast it's going to be a real transaction so we just want to be very certain and very particular with what we put before and what we put after this vm. start broadcast so now that we have this helper config we now have access to this Active network config which when we deployed it is going to be updated with the correct helper config here now we can get the right address by grabbing it from the helper config so we can say address ethusd price feed equals helper config do Active network config price feed excuse me helper config activ Network config now normally since we're returning a struct we would have to wrap this in parentheses and if we had multiple return values in the struct right if this was like an address and then another address and then another address Etc we'd have to do an address and then another address you know and then another address Etc but since it's only one undo all these as well but since it's only one we can wrap in parentheses like this and solidity will just automatically take those away so so this work so even though Active network conf fig is of type Network config this will work correctly great but now we have the ethd price feed we can stick it in here so if we're doing this right if we run Forge test-- Fork URL sepolia RPC URL we should indeed pass we should have refactored our code correctly fingers crossed and boom okay our helper config is coming along fantastically this is great let's clear let's hide this and let's keep going so we're able to get this working well and now this is a strategy we can work with different chains for example if we wanted to work with another chain for example ethereum mainnet we could copy paste this here we could say get mainnet eth config public P returns Network config we say eth config Network config we could go to docs. chain. link let's scroll over to ethereum let's go to eth mainnet where's ethusd let's scroll ethusd we would copy this address here we'd come back we paste it in here copy this paste it here and now we would scroll back up and and again if I'm moving too fast for you feel free to pause or slow me down copy this we'll come up here then we can say else if and then co-pilot's giving me the answer here but if chain ID equals equals 1 then Active network config equals get main net e config so we can use this little else if syntax here to just toggle through all these different chain IDs and awesome now we have a way we could even get the mainnet eth config and if we wanted to what we could do is we go back to Alchemy create a new app here we'll call it mainnet mainnet ethereum ethereum main net zoom out a little bit so we can click the button and what we can do is we can grab this key copy the https come back in here let's go to ourv file create mainnet RPC URL equals this P up the terminal source. EnV that way this if I do Echo main RPC URL I can now see this as an output what I could do is I could do Forge test-- Fork URL dollar sign mainnet RPC URL and now I can run my test even on a forked main net awesome and even that passes so this is a really important step that we want to get really good at is is running our tests on a forked mainnet or a forked blockchain that we're actually going to be deploying so if we wanted to deploy to eth mainnet we would do something like this these days I don't deploy very much to ethereum mainnet I'm usually going to Ploy to an L2 so maybe I'll do like a polygon Z evm optimism put a lot on arbitrum but something like that and that's where I would do the fork testing against but in any case awesome and the coolest thing about this setup is that if I want to deploy to main net great it'll just work or if I want to deploy to sapoia Great it'll just work and if I want to deploy to any other chain all I have to do is add an additional Network config and we're good to go but the Anvil is going to be a little bit different right if we scroll back to the top we're saying otherwise grab the existing addresses from the live Network great well on a local network those contracts don't exist so we're going to have to deploy those contracts ourselves on the Anvil config so what we're going to do down here is we're going to do something a little bit different so one of the first things that we're going to do is we're going to have to deploy the mocks and then return the mock addresses a mock contract is it's basically like a fake contract it's like kind of like a dummy contract it is going to be a real contract but it's going to be a contract that we own we can control Etc so what we're going to do is actually we're going to do a vm. startart broadcast down here this way we can actually deploy these mock contracts to the anval chain that we're working with and since we're using this VM keyword we actually can't have this be a public pure and addition our helper config needs to be is script in order to have access to this VM keyword and let's also add a vm. stop broadcast as well so in here let's deploy our own price feed in order to deploy our own price feed we're going to need a price feed contract so what we're going to do is actually in our test file we're going to create a new folder called Mox and this is where we're going to put all of our contracts that we need to do testing right it's going to be a real contract but we're going to put in the test folder just so that we separate it we say hey this contract is different than our core codebase and we're going to create a new file call it mock B3 aggregator doou now instead of us actually creating this ourselves there's actually already a mock V3 aggregator in the chain Leake brownie contracts section however it's an older version of solidity it's version 0.6.0 so I'm going to save you all some trouble from having to rewrite that in a new version and if you want to just come to to The Foundry fundme f-23 go to the test folder oh it looks like I don't have it in a mock here but it probably will be in a mock folder here and we can just copy paste this entire contract so we'll copy it go to our codebase and paste it in here this has all the code of a price feed essentially we have if we scroll down we can see some functions that we're familiar with like latest round data which is what we use in our price converter and if we scroll up we can see in the Constructor we get it a decimals and an initial answer and we also have an update answer function so that anytime we want to mess with this contract or update it ourselves in our Anvil tests we can which is great so we're going to deploy this and we're going to use this address as the price feed address on our Anvil chain so in here well first off we need to import them so let's go ahead and import mock V3 aggregator from slmx or excuse me slash test slmx SL mock V3 aggregator doso and down at the bottom we're going to say mock V3 aggregator mock price feed equals new mock V3 aggregator and we can see the Constructor of this it takes a decimals and an initial answer so we know that the decimals of e ISD is eight so we can just put eight in here and then initial answer we can do something like 2 ,000 E8 because it has eight decimals we can say it starts at a price of 2,000 and this will be the address that we put into the network config now we could say outside of the broadcast because we don't need to do this inside of the broadcast we could say Network config memory envil config equals Network config do a little parentheses like this price feed it'll be the address of the mock price feed like that we add the little semicolon there and then of course we say return and build config all right great style guide tip so something you'll see me do a lot is talk about this concept called Magic numbers I hate magic numbers I'm not a big fan of magic numbers if I'm just reading this code and I see this number eight and 2008 if I haven't looked at this code in a while to me I like I don't know what these numbers stand for have to go to the mock V3 aggregator and see okay it's the decimals and it's the initial answer and then come back but if I have a ton of code that I have to do that for this can be really annoying to do so I hate magic numbers using instead of having kind of random numbers lobbed in my code what most developers will do is they'll turn these magic numbers into constant variables at the top of their contracts so if we scroll at the top of our contract maybe we'll make a new line we can say uent 8 because decimals is going to going to be U 8 public constant decimals equals 8 and then a u excuse me and then an INT 256 public constant initial price equals 2e8 like this and then what we can do down here is we can say instead of eight we'll say decimals instead of 20008 we'll say initial price and this makes it much easier for us to know what that 8 and that 2000 stand for that 8 stands for decimals and the 2,000 stands for the initial price this makes our code much more readable and even when I'm doing an audit report if I'm doing a smart contract audit this is something that I will point out it's a lot easier to maintain readable code and that's something that you'll hear me talk about a lot even this is a magic number in a in a sense right I don't think it's that important for me to say hey this is the sapoia chain ID though because to me it's kind of obvious so it's a little bit of an art rather than than a science but a rule of thumb is I hate magic numbers and you'll see me pretty much always do this convention up here all right awesome now just one more thing we're going to add in here is we're just going to say if Active network DOT active Network config price feed is not equal address zero this this is a way to get the zero address or the default default value return Active network config and the reason I'm going to put this in here is if we call get Anvil eth config without this we actually will create a new price feed however if we've already deployed one we don't want to deploy a new one so we do this this Active network config price feed does not equal zero is basically saying hey have we set the price feed up as something remember because address defaults to address zero so if it's not add or zero it means we've already set it so just go ahead and return and don't run the rest of this and with that being said the name of this function I'd argue is not very good because it's not just getting the Anvil e config it's actually creating the contracts in here so I would change this to get or create Anvil eth config and copy this and paste it up here again like I said I love being very verbose with my functions to make my code much more readable but okay so now that we have this remember before every time we ran Forge test it failed right and why did it fail well if we go back to the test when we call test price feed version is accurate the time we called get version this would fail because the contract didn't exist on Anvil now that we have our helper config here we do indeed deploy our own fake price feed if we go to the fake price feed is there a get version there is is indeed a version function which returns zero and let's actually update this to four so that it actually will pass cuz right now if it's zero it'll fail so version is four so now it should be able to call this version parameter because it's a public and return four so let's go ahead Moment of Truth so if we do Forge test-- Fork URL aolia RPC URL we know that this is going to pass because it's going to Fork the aoia chain and our helper config is going to give it the sapoia address we know that if we go to our Alchemy dashboard go to our sapoia we a little do a little refresh here we're going to see just now we see we see a whole bunch of calls coming in and we do indeed see this passes now Foundry was failing whenever we ran this without a fork now let's do a little clear now if I do Forge test without a network without an RPC URL let's see what happens oh my goodness and see this was also so much faster because we didn't have to make any API calls up to Alchemy we have to say hey Alchemy what's the sapoia chain look like and wait for it to tell us what the sapoia chain looks like we were able to do everything locally on our own computer here it was much faster we didn't have to make it any API calls and boom we've got this network agnostic set up so that we can deploy our fundme contract on any network that we want this is incredibly incredibly powerful and I know I keep saying this but I'm being incredibly honest when I say learning these skills right here is making you all better than the current status quo of solidity developer out there I'm giving you the skills to leave this course and not just be a good smart contract developer but I'm giving you the skills to raise the entire bar of smart contract developing so congratulations for getting this far and I know we've gone over a lot of stuff and we're not done with this project we have a lot more to go but this is a great time to take a break because you have just accomplish in a massive amount and learned a ton if any of this is confusing remember to use the course resources to your advantage we have artificial intelligence that can help answer some of these questions we have the discussions form as well with a ton of people taking this course with you who can help you out and remember you can come in here and you can help other people out as well so take a quick break here's a cute picture of a frog here's an even cuter picture of a frog as a reward and I'll see you soon all right welcome back hope we took a break hope it took a rest taking rests are incredibly important especially in this earlier parts of the course where you're learning a lot of these Advanced pieces and it's starting to get a little bit harder if you try to do the rest of this course in a day you're not going to learn anything repetition is the mother's skill but that repetition will only result in you gaining that skill is if you take the rest you need need for your body to recover so let's keep going though we've learned a lot we're doing fantastic work now we've got our deploy fundme holy mackerel we can deploy on any chain we want because we've got this fantastically Advanced helper config setup for us so now that we have this this means that we can continue to write our tests over here we don't even have to care or think about which network that we're actually on because our deployment setup is is going to work no matter what all right great so let's focus now let's switch gears now that we have our testing and our deployment harness set up let's do this again Forge coverage and now I don't even have to put an RPC URL anymore because this is going to work for a Anvil oh feels good doesn't it if I do Forge coverage o but this doesn't feel so good if I do Forge coverage we see oh we are not testing very much of our code now coverage isn't an end all be right if you don't have 100% coverage it's not the end of the world however if you have 0% or 7% That's not a great look so we want to do our best to at least get this up and write some tests for as much of the code as we can if we don't have a test for it it could be wrong the functionality could not work as expected so let's write some tests so we make sure our code is actually doing what we want it to do if we look at our fund function what's the first thing that we want it to do well if we don't send it enough eth it should revert right okay great so let's write a test for that so we'll say function test test fund fails without enough eth and the way that we can test something fails in Foundry is we can use another one of these cheat codes so if we scroll back over to Foundry over to The Foundry docs the left- hand side here we can scroll down to cheat codes cheat codes in the test section and it tells us all about some of the different cheat codes we can work with so if you want to learn more about cheat codes you can select that or we can scroll to the bottom go to the pendex and go to the cheat codes reference hit the little dropdown we have environment assertions and a whole bunch of other stuff let's look under assertions and we can see there's one called expect revert it tells us all about this revert bit expect revert is a cheat code in Foundry it allows us to say hey if we do vm. exect revert we're saying hey the next line should revert and so it's kind of equivalent to saying assert this TX fails SL revert so if I put vm. expect revert the next line we're telling Foundry to revert so if I were to run something like U 256 cat equals 1 this test will fail because this line doesn't fail which is a little confusing right so if we pull up our terminal here our en forg test- m i paste this in remember- m is how we run a single test I hit enter you'll see that this fails because this didn't fail right so we see call did not revert as expected so that's a little bit confusing so we need to do something here that fails so now if I do fundme do fund but I don't send any value right remember if we want to send value we do it in these little brackets here we don't send any value the zero value is going to be less than the minimum rate which again is $5 right so since it's less it should fail with you need to spend more eth so if we add this expect revert fundme do fund we hit clear we're run that single test again now it'll pass because this line is indeed failing and that's what we want so great we're testing the funme fails without enough e being sent great job perfect so what else should we test well okay let's say it we do send enough if we do send enough we update these data structures okay so let's test for that so we'll say function test fund updates funded data structure make this a public function and now we want to do fund me. fund and we'll want to send some value maybe we'll send we need to send a value greater than $5 so we'll send like 10 eth why not because 10 eth is almost definitely going to be more than $5 or I hope so and then we'll need to check if address to amount funded is getting updated now I'm going to do a little bit more refactoring here now I believe I showed you all already that these these storage variables which we haven't talked about too much should indeed start with sore so if you haven't done this already we're going to do a little bit of refactoring address to M funded storage variable funders storage variable price feed storage variable so now we just do a little s underscore here we do a little s underscore here little sore here a little sore here sore sore okay great and typically as a best practice we want to default all of these variables to private private variables are more gas efficient than public ones so we want to default them to private and anytime we actually need to make the public we go ahead and explicitly do that ourselves and this is where if we're not using the updated fundme Doo be sure to just copy paste it from Foundry fundme doso it's got everything we want in here but the most important pieces is down at the bottom it has these view functions so in order for us to actually check that these are actually being updated we want to scroll to the bottom and we're going to create a section for our view/ Pure functions these are going to be our Getters so in here we'll create a new function get address to amount funded we're going to do an address funding address this will be an external U returns un 256 and this will be return sore address to amount funded funding address and I just hit tab there we want to do this for a couple of reasons again I said we want to make our code very readable and using Getters as opposed to kind of this gross sore methodology is a lot more readable and a lot more sensical additionally like I said private variables are more gas efficient so we just want to default them to private and then only make public or external view functions as we need so we want to be able to get that we also want to be able to do function get funer and have a u 256 index be passed in this will be an external view which will return an address and we'll just say return funders at the index so these are two getter functions that we can now use to check to see if these are populated so back in our test after running this fundme fund we can say un 256 amount funded equals fund me.get address to amount funded and then who are we going to pass in here and then we're going to say assert equals amount funded 10 E18 so so a couple things are going on here so this is probably going to be message. sender but this can be a little confusing let's run this test Forge test- M pass that in in here let's see if this works okay it failed so it looks like message. sender isn't the one who called fund well it was probably then the address fundme test is that who it was let's just say address this is that is that correct let's try this now okay looks like it was address this but as you can see knowing who is doing what can be a little bit confusing especially in our tests so in our test we want to be very explicit with who's sending what transactions and that's where we can use another foundary cheat code called ranking so if you go to the cheat codes reference you go to environment you can scroll down and we can see there's a prank cheat code in here this prank code sets the message. sender to the specified address for the next call so we can use prank to always know exactly who's sending what call and remember this only works in our tests and this only works with Foundry so Above This fundme fund we create a fake new address to send all of our transactions so up at the top let's create a fake user who's going to send all of our transactions there's another Force sheet code called make addr where we can pass in a name and it'll give us back a new address this comes from Forge STD as opposed to the VM so we can just use make addr like this so what we can do at the top is we can say address user equals make addr we just give it a name of user and this will be who we use for all of our anytime we want to work with somebody we can't make this constant because because this isn't compile time constant but it's test anyways so we don't really care but in any case so if we scroll down we can say vm. prank user which is saying the next TX will be sent by us user so this fundme do fund will now be sent by user so now in amount funded we can say amount funded equals fund me.get address to amount funded delete that paste that in here and one other thing we can do to make this cleaner is as you know I hate magic numbers so we're going to make this a constant variable as well so if we scroll to the top we're going to make a new value we're going to say unit 256 constant send value equals and we're going to say 0.1 ether decimals don't work in solidity but if you do 0.1 ether that makes it you know 1 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 and now we can do back down in our test instead of some value here we can just Bo you send value each time instead so let's check to see if this works we'll hit up a couple times Forge test oh and it looks like we have an issue and this is good let's learn how to trios this issue so let's hit clear we'll hit up a couple times and then we'll Dash vvv to see what's wrong with this to see where this is actually reverting ah so we pranked the user but we're getting this error out of fund so we created a new blank user who doesn't have any money so they can't send the send value since they don't have any money so what we can do is we can use another cheat code to actually send him some fake money so if we go to cheat code references there's a cheat code called deal which allows us to set the balance of an address to a New Balance oh yeah so what we can do is we can scroll back up to the top and this is a cheat code not a forge standard cheat and in our setup we can just say vm. deal user and we can give them some starting balance so maybe we'll say un 256 constant starting balance equals 10 ether so we'll give our fake user 10 ether to start out with using a cheat code and now if we scroll down we hit clear now we run our test Tada we are now successful as we are now giving them some fake money so that they can run our tests we have a couple more tests going on here so now if we pull up our terminal again we run Forge coverage you'll see we've gotten a little bit better with our coverage we've gotten a tiny bit better here but let's keep going all right let's keep going let's do function test adds fun to array of funders make this public so up here we're seeing that this get Works let's also make sure that the this get funder that we just created works so we'll say bm. prank user fund me. fund I'm going to hit tab a couple times because I'm going to do this exact line up here thanks get up copilot then we're going to say address funer equals fundme do get funer at index zero so this should be user because we're we only have one fun in here an important note is every single time we run one of these tests it'll run setup and then the test and then start over and then run setup and then run the test and start over so even though we called fundme do fund up here we're actually going to reset every single time that's why if we made this a different user we would still go to the zeroth index so now we just do assert equal and say fun is user right so assert equal we're saying this equals this that's what this test is checking so we'll run this do a little clear Forge test DM paste that in here uh okay that worked as well great let's keep going okay so we've tested that this data structure is getting updated correctly this is also getting updated that's great we could probably add some more tests to check to see if multiple work but let's say this is good for now we probably also want to check this withdraw piece so t uh function test only owner can withdraw right we want to be able to we want to make sure that only the owner can call this withdraw function so we want to make sure this only owner modifier is working correctly so well what can we do first let's fund it so we can copy this line here paste it in here and then we'll do vm. exect revert vm. prank user because the user is not the owner we'll do fundme do withdraw so we're going to fund it with some money with this and then we're going to have the user try to withdraw because the user is not the owner now you'll notice that we're doing VM that. expect revert and I said hey the next line is should revert it ignores these VM stuff so this is saying like the next transaction that's not like a VM cheat code so it skips over this one and says this is the one I'm expecting to revert same thing with this if these were in this order it would say I'm going to pretend to be the user for not this one because this is a VM but for this one so now if I hit clear we'll copy this or test- M paste it in boom we see that this is indeed successful awesome now as we get more and more advanced with more and more functionality these tests are going to get bigger and bigger right let's say we want to do test only owner can withdraw after 18 withdraws have happened right we'd have to do maybe a whole bunch of whole bunch of these whole bunch of these or something like that we want to make our tests very minimal like we want them to have minimal lines of code so a really good methodology by a very well-known solidity Dev in the space Paul he has a great proposed solidity best practice organize your unit test by using a state tree start by defining the parent nodes at specific State conditions that drive the behavior of the smart contract so if this is your contract write some tests that test something and once it's good create a modifier for it so you don't have to copy paste the code from those tests if that's confusing don't worry I'm going to make it make sense in just a second we're going to add this modifier called funded like this and I know we've worked with modifiers before and in here we're going to say vm. prank user fundme fund value send value I'm going to go ahead and hit tab there and this little underscore here now instead of every single time we want to fund one of our tests instead of writing a ton of code we can just do public funded in the test declaration and now we can say okay any test we write after this modifier we can add this funded and we can save ourselves a lot of code once some setup gets really big right let's say we had to do some setup to write this test that took a ton of lines of code and we need to write a ton of tests for it it's going to make it so that we don't have to keep repeating ourselves over and over again so big fan of this L best practice thanks Paul for setting this up and now we can just do this instead so let's go ahead and try to run this again now that we're using this modifier and great it does indeed pass Okay cool so now let's say let's actually test with drawing and we'll test withd drawing that actually works so we'll say function test withdraw with a single funer make this public funded and now it's automatically going to get set up to be funded already so there's a single fun and we're going to go ahead and test withdrawing with the actual owner and this is where I'm going to introduce the arrange act CT methodology for working with test whenever I work with a test I always think of it mentally in this pattern first I'm going to arrange the test I'm going to set up the test then I'm going to do the action I actually want to test and then I'm going to assert the test so in a lot of my tests you'll actually see me write these explicitly out so mentally I can compartmentalize the different parts of the test so for a range in order for us to test that the withdraw function actually is going to work we first want to check to see okay what's our balance before we call withdraw so that we can compare it to what our balance is after so to arrange we can do U 256 starting owner balance because it's the owner who's going to do the withdraw and this will be equal to fundme dot then do we have a get owner function I don't think we do we do not have a get owner function so let's actually make this I owner private and create a getter for get owner so scroll to the bottom we'll do function get owner this will be external view turns address return I owner and then my test I'm going to say fundme do get owner. balance so we're going to get the owner's starting balance we're going to do a u 256 starting fundme balance so the actual balance of the fundme contract which since it's funded it's just going to be this send value it's going to be equal to the address of the fundme contract balance and now in the ACT we're going to do V m. prank fund me.get owner because only the owner can call withdraw so we just want to prank make sure we're actually the owner we're going to call fundme do withdraw this and this is what we're testing right we're testing the with draw so we put this in the ACT section and now we can move over to the assert section so we'll say un 256 ending owner excuse me yeah ending owner balance equals fundme get owner. balance balance like that you 256 ending fundme balance equals address fundme do balance and we could say assert equal ending fundme balance should be zero now I know I said I hate magic numbers but zero often I don't create a constant for because it's just zero so we should have withdrawn all the money out of the fundme and then we can also do aert equal the starting fund balance plus the starting owner balance should equal the ending owner balance because we withdrew all the money at of fundme so we should just be able to add it to their address and that should equal the ending balance so let's go ahead and let's test this Forge test DM paste that in here oops I'm doing I owner somewhere oh yep so this actually fails now so this should actually be get owner instead let's clear run this again and awesome so that does indeed pass great work now let's just do one more test a test with multiple funders so this is going to be the big function here so we'll do function test withdraw from multiple funders public funded and so it's going to be funded once but let's add a ton more funders so let's do a uint 256 number of funders we'll say there's we'll do 10 and into 256 starting fun index equals 2 and you'll see why I'm doing this in just a minute let's go through a loop and let's just keep creating new addresses for this number of funders so we'll do a four Loop which I know we know how to do do four un 256 I equals starting funer index I is going to be less than the total number of funders i++ so we're going to go every time we go through a loop we're going to add one to I here and what we're going to do is we're going to do a vm. prank and a vm. deal and create addresses and they're going to fund the fundme we. prank a new address we're going to deal that new address some money and then we're going to fund it so we could do vm. prank and vm. deal but the forge standard Library which again is slightly different from the cheat codes actually comes with this standard cheat called hoax which sets up a prank from an address with some ether so it does both prank and deal combined and since it's a forge standard we can just do hoax some address which we'll talk about in a second and then we'll give it send value but how do we actually populate the address I showed you before we can do address 0 Z to generate an address guess what we can also do address 1 address 2 address 3 address four address 5 address 6 Etc except they must be a uint instead of 256 a uint 160 as of solidity V 0.8 you can no longer cast explicitly from address to un 256 you have to do a un 160 and the reason for this is a u 160 has the same amount of bytes essentially as an address so that's a little bit confusing don't worry too much about it for now just know that if you want to work with addresses if you want to use numbers to generate addresses those numbers have to be a u 60 so actually we're just going to use U 60 for everybody and actually we're going to start with starting index B1 excuse me but what we can do is we can say address of I and we'll make this a un60 as well we're going to create a blank address of I which starts at one and we're going to add send value and the reason we're starting our starting index is actually going to be one here is because sometimes the zero address reverts and doesn't let you do stuff with it when you're writing your tests you just want to make sure you're not sending stuff to the zero address because there's often sanity checks to make sure you don't do that so but in any case we're going to hoax that address and do and add some ether to it and since we're hoaxing it it means we're pranking it so now we can call fundme do fund with this new address we do the value it's going to be send value like this and cool so we'll have this many funders actually Loop through the list and fund our fundme contract awesome so now we're going to do some of the same stuff that we did above right so this is all in our arrange setup so we're going to say un 256 and my get up copile that actually already knows starting owner balance un 256 starting fundme balance thank you get a co-pilot I hit tab again and if you want to just copy from up here you can just copy from there as well and then we're going to say vm. start prank excuse me vm. prank fund me.get owner like this and then we'll call fund me. withdraw like this now another thing that you'll see instead of just prank is you'll see start prank and you'll see vm. stop prank this is the same as start and stop broadcast it's saying that anything in between start prank and stop prank is going to be sent pretended to be by this address here so you'll see this syntax a lot as well and it's a syntax that I actually prefer to use and you'll see that I use it a lot but after we call this withdrawal function which again this is going to be in the ACT we can now move on to our assert phase and we can say let's assert that the address of fundme balance is going to be equal to zero so we should have removed all the funds out of the fundme we can assert starting fundme balance plus the starting owner balance equals fundme doget owner. balance like this okay great so let's run this test there Forge test- M paste that in Tada that has also been successful now if we run Forge coverage let's see what happens how good are our tests now aha they're a lot better at least for the fundme we haven't done a whole lot of testing a price converter but that's fine fantastic we can see we've covered at least 93% of the code in our contracts so this at least makes us feel a lot better that we've done a much better job of writing some tests right like I said writing tests can be a little bit of an art but if everything here is red that's a bad sign so we have green on this line so that's a good sign now you might be asking oh hey Patrick we just wrote this test but shouldn't the balances actually be lower because we spent gas and that is a wonderful observation and we will come back to that so hold on to that we'll come back to that in a minute but let's keep writing the rest of these tests all right awesome so now let's look at some other ways that we can actually debug some of our tests if we run into any issues one of the ways that comes packed with Foundry that I absolutely love is a tool called chisel normally if I want to test that some solidity works really quickly I might come over to remix and I might do some random code and see if it works but instead what I can do is in my terminal I can just type in chisel and I'll get outputed into this shell here if I type exclamation mark help it'll give me a ton of information about what I can actually do in this terminal here chisel allows us to write solidity in our terminal and execute it kind of line by line so for example if I wrote U 256 cat equals 1 and now type cat and I can see oh cat is one I can type cat here again I can do you 256 cat and 3 equals cat + 3 do cat and three and see you know 1 + 3 obviously equals 4 so chisel is a fantastic tool that I use all the time to quickly sanity check some small solidity pieces that I need so chisel you can write you can literally write solidity right in here without having to go to remix and test stuff out chisel awesome tool solidity in your Terminal contrl C contrl C to exit now let's go down to this test withdraw from multiple funders what if I told you there was a way to make this a lot cheaper cheaper gas wise it C it would cost less gas for us to actually perform that would be a pretty valuable piece of information wouldn't it every single time we send a transaction or we deploy or we do anything on chain we have to spend gas and the more complicated and the more computationally expensive our contracts are the more gas we have to spend so what if I told you there was a way for us to make this cheaper let's figure out how to do that now how do we even know how much this is going to cost that' be probably be a good thing for us to Benchmark right what we can do is run Forge snapshot ASM paste that exact test in what this is going to do is it's going to create this file called gas snapshot for us and if let's open this up it's going to tell us exactly how much this single test is going to cost in gas and if we wanted we could do the conversion between gas and guay and price and everything to figure out how much this actually costs but this is now our Benchmark we now have this in our do gas snapshot test withdraw from multiple funders cost this much gas all right cool so now that we have these functions here let's go back up here and talk about that gas thing because we did vm. prank fundme.com of the actual chain we're working on when you're working with Anvil the gas price actually defaults to zero so when working with a local Anvil chain be it forked or not it actually defaults the gas price to zero so for us to simulate this transaction with actual gas price we need to actually tell our test to pretend to use a real gas price and this is where there's another cheat code that we can use called TX gas price which sets the gas price for the rest of the transaction so what we can do is same as where we're doing vm. rank we can do vm. TX gas price and we can set some gas price and up at the top we'll do a u into 256 public excuse me U 256 constant gas price and it could be anything let's just set it to one and down here we'll just say vm. TX gas price we'll set that to the one and now in our test here we'll actually have a gas price in order for us to see how much gas this is actually going to spend we need to calculate the gas left in this function call before and after to do that we'll do U 256 gas start equals gas left this gas left function is a built-in function in solidity it tells you how much gas is left in your transaction call remember how on an ether scan when we scroll down there was a gas limit and gas usage whenever you send a transaction you send a little bit more gas than you're expected to use and you can see how much gas you have left based on how much you send by by calling this gas left function so we can get the gas start and then after we call withraw we can do U 256 gas end equals gas left so this is how much gas we used so let's say we sent 1,000 gas let's say this cost was 200 gas that means down here we would have 800 gas and so we can say you into 256 gas used from this withdraw transaction is going to be equal to the gas start minus gas end times whatever the tx. gas price is tx. gas price is another built-in to solidity which tells you the current gas price and we can use this methodology to do console. log gas used rerun this test the- VV and we'll actually be able to see how much gas that exact call actually did which is right here but I'm going to go ahead and now I'm actually going to go ahead and remove all this gas stuff and just bring it back to this all right great anyways so we have this gas snapshot is there a way for us to make this cheaper and much easier by golly there absolutely is and this is where we're going to actually learn about storage this thing that I keep talking about and keep referring back to we're actually finally going to talk about storage up here so let's watch an excerpt from the previous free code Camp video so that we can understand what storage is and what it looks like we're going to look at one of the first and most obvious gas optimization techniques and it has to do with all of these variables at the top and this thing called storage so this gas snapshot we're actually going to write some code to make this test be much more gas efficient so let's learn about storage so we can learn this gas optimization technique let's say we look at the average gas for these and we go huh this looks like it's actually a lot more than what we originally expected is there a way for us to make this a little bit cheaper we go back to our fundme contract we look at our withdrawal function and we notice something oh there is actually a way to make this a lot cheaper and it has to do with something called storage variables or these Global variables that we've been working with this whole time let me let me paint you a little picture here we're going to look at one of the first gas optimization techniques you can take to drop these down and it has to do within our fundme contract these State variables and how they're actually stored and how this contract actually keeps track of all this stuff this section is going to be a little bit more advanced so we'll have a note here saying that this is an advanced section and if you want to skip over over it you can cuz now we're getting into gas optimizations here this information still is really good to know so if you want to skip it for now and then come back later you absolutely can but let's talk about what happens when we actually save or store these Global variables AKA these storage variables now everything I'm about to go through is in the documentation and there is a link to this of course in the GitHub repo associated with this course whenever we have one of these Global variables or these variables that stay permanently there's stuck in something called storage you can think of storage as a big giant array or a giant list of all the variables that we actually create so when we say we have some contract called Fun storage and we have a variable called favorite number we're basically saying we want this favorite number variable to persist right we saw in a lot of our examples we had a favorite number variable that we could always call to see what this contract's favorite number was well the way it persists is it gets stored in this place called storage now storage works as this GI list associated with this contract where every single variable and every single value in this storage section is slotted into a 32 by long slot in this storage array so for example the number 25 in its bytes implementation is 0x00 with a ton of zeros 19 this is the hex version of the UN 256 this is why we do so much hex translation this the bytes implementation of a un 256 and each storage slot increments just like an array starting from zero so for example our next Global variable or our next storage variable just gets slotted at the next slot that's available so booleans for example get transformed from their bull version to their hex and we modified our Su bu variable to be true and the hex addition of the true buin is 0x1 every time you save an additional Global variable or more correctly one of these storage variables it takes up an additional storage slot and what about variables that are dynamic in length or that can change length what about something that's Dynamic well for dynamic values like a dynamic array or a mapping elements inside the array or inside the mapping are actually stored using some type of hashing function and you can see those specific functions in the documentation the object itself does take up a storage slot but it's not going to be the entire array for example my array variable here at storage Slot 2 doesn't have the entire array in storage Slot 2 what it has actually is just the array length the length of the array is stored at storage Slot 2 but for example if we do my. push 222 we do some hashing function which again you can see in the documentation what that is and we'll store the number 222 at that location in storage the hex of 222 is 0x00 De so we get stored in this crazy spot and this is good this is intentional because 32 bytes may not be nearly big enough to store my array if our array gets massive and it wouldn't make sense for to put the elements inside the array at subsequent numbers because again the size of the array can change and you're never going to be sure how many subsequents that you need so for my array it does have a storage slot for the length for mappings it does have a storage spot as well similar to array but it's just blank but it's blank intentionally so that solidity knows ah okay there is a mapping here and it needs a storage slot for its hashing function will work correctly now interestingly constant variables and immutable variables do not take up spots in storage the reason for this is because constant variables are actually part of the contract's bite code itself which sounds a little bit weird but you can imagine what solidity does is anytime it sees constant variable's name is it just automatically swaps it out with whatever number it actually is so you can kind of think of not in storage is just a pointer to 123 and it doesn't take a a storage slot well when we have variables inside of a function those variables only exist for the duration of the function they don't stay inside the contract they don't persist they're not permanent so variables inside these functions like new VAR and other VAR do not get added to storage they get added in their own memory data structure which gets deleted after the function has finished running now you might be asking okay well why do we need this memory keyword especially when it comes to Strings we saw before before that we had to say string memory the reason we need it for Strings is because strings are technically this dynamically sized array and we need to tell solidity hey we're going to do this on the storage location or we're going to do it into the memory location where we can just wipe it arrays and mappings can take up a lot more space so solidity just wants to make sure okay where are we working with this is it storage is it memory you have to tell me I need to know if I need to allocate space for it in our storage data structure and again everything here you can read in the solity do mentation now in the GitHub repo associated with this course if you go to SRC you go to example contracts we have this fun with storage here as well and if you go to the scripts of this we have a deploy storage fun as well which has some functions in here called print storage data and print first array element that you can play with to actually see where in storage these are being located we're not going to code these right now and I'm not really going to go over what these are doing cuz oh and I'm going to have to change this name here but I definitely recommend trying to run this yourself on Anvil to see what these storage functions actually print out for you one other thing that's really cool about Foundry I can actually check my fund me contract storage a couple different ways the first one I can do is Forge inspect fundme storage layout H enter and it'll tell me the exact layout of storage that my fundme contract has whoa oh and it gives me this giant object here if I scroll up to the top I can see the storage layout here we can see that this s address to amount funded actually is in slot zero we continue down we can see s funders is in slot one we see S price feed is in slot two and we have all this information about types and some other stuff as well but this part of the top storage is where we can easily see where stuff is being stored we can see there too these immutable variables didn't show up in storage which it makes sense minimum constants and immutables don't get stored in storage they are part of the contract's bite code the other way that we can see storage is using cast storage keyword if I spin up an anvil chain create a new shell here and I run Forge script script deploy fundme dos. soul- RPC URL let's use this HTTP SL D private key let's use this one right here paste it in we're going to compile we're going to deploy oops I forgot to do broadcast let's do it again with D- Brad cast let's actually deploy this to our own locally running Anvil chain script ran successfully awesome contract address here what I can now do I can run cast storage paste the contract address here and pick a storage slot for example two which is the price feed address and it's going to give me exactly what's in that storage slot at storage slot index 2 obviously 0o and one are just going to be empty because those are what these two arrays which right now are this mapping and this array which right now are blank if you have a connection to ethers scan you actually don't even need to add an index and it'll fetch the source from ethers scan and tell you the whole storage layout but I'm not connected to Ether scan this will be something that you should try in the future is actually doing C storage on a live contract and seeing a live contract storage so that'll be your homework for later so this is just a double down that even when you have the private keyword that doesn't mean your data is private everything on the blockchain is public information and anybody can easily read that information off of your or anybody's blockchain now you might be asking yourself hey cool Patrick but why are we talking about this storage thing yeah this is really interesting to know but I thought we were trying to optimize gas wise the reason that we're talking about storage is because reading and writing from Storage is an incredibly expensive operation anytime we do it we spend a lot of gas remember how before when I said when you compile your code it gets compiled down to this weird bite code let's go back to remix let's hit compile let's go to compilation details go to remix and we select bite code and we scroll down a little bit all the way to the bottom we'll see this thing called op codes and object the object is the contract in pure bite code and these op codes are the bite code converted to something called op codes these are the lowlevel computer assembly level instructions that are actually executing and actually doing what our smart contract should do and guess what each one of these incredibly low-level codes has a specific gas cost associated with it we go to ev. codes this is a website that actually keeps track of a lot of these op codes gas costs and right on the le- hand side we can see the op code in its bite code format and then the name of the op code and then the minimum amount of gas it actually spends to do that op code so anytime you add two numbers it costs three gas multiplying costs five gas dividing five gas so on and so forth and if we keep scrolling keep scrolling we're seeing a lot of Threes a lot of twos a couple of hundreds some 20s we get down to here oh my goodness SL load and s store are both 100 that's way more expensive than a lot of these other ones that we're seeing which are like two or three or five s load is the op code that loads a word from Storage anytime you read from Storage you're spending a minimum of 100 gas s store is the op code that stores a value in storage save a word to storage which also costs a minimum 100 gas if we look just up above that we actually see M load and M store which stand for memory load and memory store if we load or read from memory it only costs three gas so it's almost 33 times more expensive to read and write to storage than read and write to memory so a real easy gas optimization we could do is we can read and write from memory way more than we should be read and writing from Storage so with this in mind if we come back to our fundme with draw function we look in here are we reading and writing to storage a lot in here oh my my goodness let's look at this Loop here so we're saying U and 256 funer equals z okay sure whatever funer index is greater than sorf funders do length the length of the funders array is stored in storage so every time we Loop through this for loop we're rereading from Storage ah let's create a new function function called cheaper withdraw this will be public only owner as well let's keep this memory to storage gas optimization peace in mind and let's rewrite this function so that we're reading it and writing from Storage a lot less so first off instead of reading from Storage every single time we could say U 256 funders length equals s funders do length that way we'll only read it from Storage one time and then every time we Loop through we'll only read it one more time and this is why this syntax of adding this sore here is really good anytime you see this sore your brain should go oh my goodness I'm actually reading from Storage maybe I should consider not doing that and reading from memory instead so we're going to read from Storage once here and for our for loop we're going to say four do the same thing you went 256 funer index equals z funer index is less than funder's length which is now a memory variable instead of a storage variable and then funer index plus plus okay cool now okay in the withdraw function what do we do okay we get the funer address from Storage there's really not a great way around this we pretty much have to read from Storage every single time here so let's go ahead and stick that in here and then we do this mapping there's really not another way around this so we're just going to stick this in here as well we still need to reset the storage so we'll do that and there's not a whole lot much to do in here so we'll just do this as well so we now have this cheaper withdraw function that we're going to Loop through this array reading the length from memory as opposed to reading the length from Storage over and over again so now that we have this cheaper withdrawal function let's go back to our funme test. soul let's scroll down and we have this test multiple withdraw funders I'm actually just going to copy paste this whole thing which wouldn't be good practice in an actual test file but for us we're going to do it I'm going to paste it I'm going to call this Let's test withdraw for multiple funders cheaper and instead of calling withdraw we're going to call cheaper withdraw and that's it that's the only difference that we're going to do now let's pull up our terminal and we'll run Forge snapshot so now we should create a gas snapshot with all of our tests but will we have test withdraw from multiple funders and test withdraw from multiple funders cheaper and if we go to our gas snapshot go to the bottom we see test withdraw from multiple funders 987 915 gas test withdraw multiple funders cheaper 987 136 we're saving almost 800 gas by using this cheaper Less storage intensive reads for running our contract amazing this is fantastic we've learned so much and we only have a couple more things to do for this lesson and then we're going to push this code up to GitHub and have your first project which is incredibly exciting so I fumbled this a little bit I didn't really talk about it too much but I did update some of the errors and I updated some of the variables without explaining it too much a mutable variables again these are not stored in storage so it's good to have some identifier to say that a they're unchangeable and B they're actually not in storage so I go by the chain link style guide which does this iore for mutable variables and uppercase for constant variables having style guides is really important and gets more important the more advanced you get because it makes your code much more readable and much you look like a more advanced developer so immutables have I underscore storage variables have S underscore and we just explained why that's so important to know what storage variables actually are a lot of people use the solidity visual developer which also automatically points out storage variables for them as well I don't really like to use it though because I feel like it clutters up my user experience a little bit but if you're having a hard time identifying storage variables maybe that's an extension for you the solidity docs actually have an entire style guide as to what to do for code layout function names line length and all this other stuff so I've already updated these to I owner S price feed we've added some Getters at the bottom there's a couple of more style guide things for us to do but we'll do that in later sections of the course I subscribed to the chain link solidity style guide which I've left a link in the GitHub repo associated with this course which talks about everything that we went over here want to keep everything private use sore use I for immutables s for storage variables Etc and you can read this if you want style guides seem like they're a little bit bored but the more you code the more you'll realize how they make your life way easier but all right awesome so we have some tests we've done mocking we have a gas snapshot we're of course going to want to add a readme.md at some point later on if you want you just copy from my read me in here we've only got a couple of things left to do these are the four things we have left for this project just do a proper read me a couple integration tests where we're going to programmatically verify our contracts inside of foundary and then we're going to push our code up to GitHub and this we absolutely need to get here because this is how we're going to build our portfolios and so oh and how other people are going to see oh my gosh they're such awesome Engineers so let's push through the rest of these so for a readme you can use my readme here as an example of what a good readme should look like a read me in your contract in your GitHub should really explain hey what your code actually does and then how to actually do it right so you'll notice in most of my readmes I have a getting started section which tells you the requirements that you need to actually run anything we have a quick start which starts with a get clone which I'll explain in a little bit and then how to actually use it if you look up best readme and Google or Brave search or whatever you want to use there are some fantastic templates to write amazing readms okay okay cool that's done what's next right integration tests so if we want to actually interact with our contract here right now we don't have a programmatic way to do that like funding and withdrawing and in our test here we tested funding and withdrawing but we didn't test funding and withdrawing using the methods that we're actually going to use to do that when we actually call funds and withdraws we're probably going to do cast send and then you know the address and then fund or whatever and the value and everything or or we're going to do it with Forge script right let's do it with Forge script so that we can have a reproducible way to actually fund and withdraw so in our scripts section we're going to create a new file called interactions. S.S and in here we're going to have all of the ways we can actually interact with our contract so we're just going to make a fund script and a with draw script so let's go ahead spdx license identifier MIT thank you get up copilot we're going to do pragma solidity 0.818 we'll do a little carrot do contract interactions this is going to be a script so we'll say is script we're going to import script from forg STD script. we're going to spell contract correctly okay great excuse me not interactions we're we call this fund fundme so this is going to be our script for funding the fundme contract we're also going to make a contract called withdraw fundme so this is going to be our foundary script for funding this is going to be our foundary script for withdrawing so in here as we're going to do function run it's going to be external external this is where we're going to put the code to actually do our stuff now something that's important though is we are pretty much going to want to fund our most recently deployed contract so what I typically like to do is I have a script I've got a tool called Foundry devops that I use to actually grab my most recently deployed contract address there's some other Foundry devops tools coming out and I will have a link in the description to the most upto-date one that you should use because I'm probably not going to maintain this moving forward unless people unless a lot of people use it this package helps your Foundry keep track of the most recently deployed version of a contract because I'm pretty much only going to want to run fund on my most recently deployed contract so to work with this we're first going to install it and you'll see why this is important very soon we're going to run Forge install chain XL org D found devops D no- commit great we're going to install that now what we can do is say import Dev Ops tools from and we'll just grab it right from the package so we'll say Foundry devops slsrc sdop tools. soul and in here in this Library found devops SRC it has this script called get recent deployment. sh so in Foundry you can actually run bash scripts or other types of scripts from Foundry but in order to do this in your Foundry doomo you need to set ffi equals true now a word of caution here if you set ffi to true this means that you're going to allow Foundry to run commands directly on your machine more often than that I recommend you try to keep this off as long as possible but it is important for us to know how it works and how we can use it for something like this to get our most recent deployments so this Foundry devops tool you just install it and then to use it it has this devops tool to get most recent deployment that we can use to get the most recently deployed version of a contract this way we don't have to pass the fundme contract address that we want to work with every single time so the first thing we do in our run function is we can say address most recently deployed equals devops tools. getet most recent deployment and we pass the name of the contract which is going to be fun to me and the block. chain ID so it knows what to do the way that this works is it looks inside of the broadcast folder based off the chain ID and then just picks the mo this run latest and grabs the most recently deployed contract in that file so now that we have the most recently deployed contract address we can just call fund on this most recently deployed address now I'm actually going to separate where we actually do the funding into its own function and you'll see why soon so I'm going to say function fund fundme address most recently deployed make this public say vm. start broadcast and in order for us to actually do anything with the fundme contract we're going to need to import fundme from. srcf fundme Soul we're going to wrap this mostly recently deployed address in here we're going to say fund and I'm going to create a u into 256 constant send value equal 0.01 ether send value we're going to fund value is going to be send value close that off here v. stop broadcast this and we actually have to type cast most recently deployed as a payable because we're going to be sending value here but then I like to do a little console.log and we'll say funded fundme with and if we do percent s we actually populate that with send value so since we're using console this is also located in the script that MD so we can import console from there and I just like to see that hey this actually went through so we have this fun funme and instead in our run we're just going to say fund fundme with this most recently deployed so we're going to have our run function call our fund fund our fund fundme function big mouthful so this is what we're actually going to do to fund our fundme contract so if I pull up my terminal I would run Forge script scripts interaction. s.o and I'll put this little colon here to pick the contract so we have fund fundme and we also withdraw fundme I'm going to pick the fund fundme here and then I would do- RPC URL blah blah blah D private key blah blah blah and that's how it actually call fun funme so that's how I would call it as a script and we want to test this as well and this is where our integration tests are going to come into play so integration tests are when you test a lot of your interactions you test combinations of systems and I usually like to separate my integration tests and unit tests in different folders so I'm actually going to go and do that I'm going to create a new folder called Unit I'm going to take this fundme test. T.O stick it in here and since we did that we need to update some of our Imports because they're now in different areas I think I did it right I do Forge test I'm doing everything right I'm kind of like halfway done with a bunch of stuff yep okay cool test pass that's great and I'm also going to make a new file called fundme test. FME test integration. T.O and I'm going to copy a lot of this from the fundme test paste it in here fundme test integration or we can also just call this interactions test. T.O so maybe in here we'll have our function set up going to be external we're going to say deploy fundme deoy equals new deploy fundme so we have deploy fundme great say and then same as the test we're going to do this bit here so I'm just going to paste that 's let's copy a lot of this actually change the name here cool so we copied most of this let's change this name to interactions test is test all the setup is the same the only difference is now we're going to say function test user can fund and user can fund public instead of funding directly with the functions we're going to import fund fundme from script interactions. s.o and in here we're going to say fund fundme fund fundme equals new fundme isn't that wonderful stay with me here I swear this makes sense and then we can do fun fundme do fun fundme with the address of fundme and this is why I separated those scripts out right because I I can't run with this I want to run fund fundme and be able to add my own address in here so we're testing this specifically to make sure our funding works and we can actually go back to our test and do something similar to when we did the fund we can make sure that they get added to the list of funders we could do something like this in our test paste it in here test user can fun inter actions this we'll run this single test Forge test- M paste that there boom Oh insertion failed and let's actually put these VM broadcasts in the Run that's actually where we're going to be doing them that we want to put the broadcast down in the Run not up here and I should probably have deal user just do 1 E8 and this is where we're actually going to test that script but let's also make the withdraw I'm actually just going to cheat a little bit we're just going to copy pretty much all of this paste it in here instead of fund fundme we're going to call this withdraw fundme and instead of fund we're going to call withdraw no value close this off close this off and instead of fund fundme we're going to call withdraw fundme and now in our test we're going to say first we're going to call fundme do fundme with the address fundme then we're going to say draw fundme withdraw fundme equals new withdraw fundme we do withdraw fundme withdraw fundme address fundme stay with me and we're just going to assert address funme balance equals zero stay with me here so we need to import withdraw fundme from interactions as well excuse me what we're going to do is we're going to fund using our scripts and then we're going to withdraw using our scripts as well so let's go ahead let's run this Forge test- M paste that in here looks like we got a revert Let's do let's do- vvvv see what's happened oh looks like we are indeed out of funds oh and in the withdraw fundme we need vm. start broadcast and then of course vm. stop broadcast this now let's run this test here and we get it's passing okay so I know we wrote a lot here and I know I went through that kind of quickly but feel free to pause and take a minute to re understand what we did here right so now we can run Forge script interactions. s.o fund fundme and then our Network information here so that we're always calling the fund the way we want to call it and then we created some integration tests which kind of bring it all together and then we did the same thing with withdrawing money as well and now we've got a huge Suite of tests that we can test all at once with Forge test we see we pass everything and then we also can do Forge test-- Fork URL aoia RPC URL or even mainnet RPC URL and we see everything pass passes here as well so even when we're pretending to deploy to a live Network everything is passing awesome now you might be asking hey Patrick running Forge script all that other crap there's so much text there's so much stuff to do there I don't want to write all that stuff and to that I say you're thinking correctly we want to work incredibly hard to be incredibly lazy so I love the way you're thinking and I know we're diverging from this a little bit but we learned how to do integration tests this is what we have left but we're going to make a pit stop I lied Pit Stop how can we make running these scripts a lot easier and this is where we're going to use something called a make file so if you right click and you create a new file called a make file this is where we're going to add some shortcuts for ourselves so we don't have to write those long scripts every single time a make file is a simple text file used by the utility called make to automate the process of building and compiling programs for projects it's pretty it's really popular in The Foundry world you should have if you create this make file in your folder and you type make you should get something like no targets stop if you don't get this it means you don't have make installed and you'll need to install make if you have a hard time installing make be sure to leave a discussion on the GitHub repo associated with this course additionally make files are great because they allow us to automatically grab whatever in ourv without us having to do source. EnV every single time so what we can do in our make file we can do something like Dash include. EMV and now we can create shortcuts for commands including whatever is in ourv file so for example if we wanted to make a shortcut for build which wouldn't be much of a shortcut we would type build colon semicolon and then just do Forge build now what we could do in our terminal is Type in make build and you'll see it'll run Forge build so this was a short example but what about a much bigger example right what if we wanted to do something like deploy aoia what would that look this little semicolon is if you want to do the command on the same line if you don't want to do this command on the same line you just hit enter and then tab and write your command down here so for deploying this to sapoia we've done this a couple times here but it would be Forge script script SL deploy fund me. s.o deploy fundme - rc- URL is going to be zolia RPC URL space- private key it's going to be private key to actually deploy it we would do das broadcast and then finally we probably would also want to automatically verify it which we're going to teach you how to do right now we would do D- verify D- ether scan D api-key and ether scan API key D1 2 3 4 and then just some visibilities like that now if I toggle my word wrap this is obviously a very big command and this would suck to have to write out every single time for us to verify every single time up and actually excuse me in make files you need to Circle your environment variables with the dollar sign and these parentheses in order for Foundry to automatically verify stuff for us we need to get we need to go to Ether scan and we need to sign up for our own API key so we're going to go ahead and sign up boundary course we'll get our email we'll go ahead and log in not a robot and cool once we're logged in we can go up to our profile down to API Keys we can add to create a new API key maybe Foundry full course and now we can use this API key copy it bring it over here drop it into ourv as our ether scan API key like this and while I'm here I'm also going to add in my private key but remember this is for your dummy account only I would never ever add my actual private key associated with real money in aemv file that is ridiculous let's copy the private key go back in here we'll do private key equals this okay and cool and now we have this super giant script but we can run this whole thing in one command by just saying make deploy sepolia now you don't have to run this command with me because again we are deploying to a real Network here and this does cost money but feel free to watch and follow along here so now you can see what the actual script is doing down here and we can see it's actually running our script without us having to do this giant command here and just to note I am doing toggle word wrap all this is on one line but if you do jump into the command pilot which again this is command pallet this is file viewer command pallet file viewer command pallet and you do toggle word wrap it'll automatically wrap the words around but we can see we're actually sending this contract we can see we actually are starting to verify the contract as well right from our command line just because we have an ether scan API key in fact now if I go to poia IO paste this contract address in here we can see oh my goodness it's already been verified for us us we didn't even have to go to Ether scan ourselves and verify it did it for us fantastic so we deployed it and verified it all programmatically directly from our command line great job so we've done this and we've done this now I'm not going to go too deep into make files however I going to give you a framework that I like to use to make setting up make files a lot easier if you go to Foundry fundme f-23 the GitHub repost assed with this course and you scroll down to the make file we've got actually this whole setup to make it a lot easier that you can go ahead and use using that make file if we scroll down to usage in here oh and by the way you can of course always do cast send to interact instead of scripts but whatever you want to do you can use this as a much easier way to get set up so for now I'm actually just going to copy paste this whole thing paste it into my make file here oh I copied too much way too much WoW okay oopsies and let's just walk through this so This pH just tells make that all of these are not folders and just anytime I have any command here I pretty much just always put it in phony default Anvil key this is the just the default private key for Anvil we add this little help section so that if you just run make help it'll tell you exactly how you can do stuff which is really helpful so if we want to deploy something we do make deploy ARS equals-- Network sapoia which is really nice or make deploy args equals or make fund R equals Network apoia we can do Forge clean remove git modules we can reinstall all the packages update packages compile test snapshot format our code run an anvil node and then this is the most interesting stuff down here because if I wanted to if I did this I could do clear I could do make anvil which will spin up in Anvil node I can spin up a new terminal and then run let's run make help real quick so I'll do make deploy args equals-- Network Anvil actually we don't need to do any args for Anvil because it defaults to Anvil if I just do make deploy we'll automatically deploy to our Anvil chain here and we do indeed do that wanted to deploy to Folia we do make deploy ARS equals D- Network aoia like that like I said I'm not going to go too deep into make files if you want to learn more about make files you can definitely chat GPT them AI them or Google them but they're incredibly helpful for making it so that we don't have to write these super long commands anytime we want to do something basic now there's actually one more thing that we're optionally going to do before before we push this up to GitHub so if you go over to the GitHub repo associated with this course this Foundry fundme CU or f23 depending on when you're watching this if we go over to the test folder we go to unit we go to funme test. t. you'll actually see a lot more stuff in here than we just went over right you'll see the setup actually has all this extra stuff you'll see this ZK sync chain Checker this Co constant what what what's going on in here so we didn't actually go over compiling and deploying to ZK syn here for a number of reasons and one of the reasons actually was because of what I'm about to show you basically certain tests will work on vanilla Foundry but not on ZK sync Foundry and certain tests will work on the zync Chain but not on a evm chain like ethereum and so I've actually created a package inside of our Foundry devops tool well I've created two packages one called ZK sync chain checker and one called Foundry ZK sync Checker and actually help us to see if a we're working on ZK sync and then B if we're working on Foundry ZK sync yes I know it sounds a little bit redundant there but trust me there's there's a method to the madness here so I want to just show you and highlight some of those differences and depending on when you watch this some of these might be updated the ZK sync team is working on reducing a number of these differences but right now if you go to the ZK sync documents there's a whole lot of differences between zync and ethereum there's a whole doc site called ethereum Differences now we're not going to go over this right now because this gets really low level we go over this much much later in the advanced Foundry section because this is starting to get really low level here but what I do want to do is highlight and show you kind of what the differences are so again remember this is optional if you do want to follow along feel free to do so it is a great exercise for you so in this GitHub repo we have this file zking devops. T.O and this is a really minimal small test kind of similar to the example contracts where there's a couple tests in here that show you where a test will fail on ZK sync but pass on an evm chain it'll also show you where a test will fail on Foundry ZK sync but pass on what I'm calling vanilla Foundry right so what I want you to do is let's go ahead let's just copy this whole thing so we're going to copy this and we're going to go into our test file into unit we're going to create a new file called ZK sync devops. T.O and we're just actually going to paste this directly in here now depending on how you've done your installations you might get some right squigglies like this this is because we have not installed Foundry devops here so since you actually just learned about make files we can go into the make file here and we should use whatever version is in this make file so in the get a Breo asso with this course as of recording it's 0.2.2 but you should use whatever is in the mink file by the time you watch this and we're actually going to copy paste this line into our codebase here and run it and if you get something like this this is actually because you have to run this make remove command now I'm going to do something and I want you to follow along with me you're not going to understand it until the next lesson just roll with me here in yourg ignore file you should have a dog ignore first I want you to go in here add this. dsor store if you haven't already then add this ZK out with a little slash there if it's not already there's a chance you don't have this file here that's also okay hit contrs or save and you should see this ZK out file kind of be gray out if you don't have it and and you save it might be green here but put this ZK out thing in this dog ignore first and then we're going to run this make remove command and again if this doesn't make sense to you don't worry about it too much right now but you can just copy paste this line what this is going to do is it's basically going to reset our modules here so if you get that error just copy paste that it's going to remove get modules remove get modules and then it's going to do a get commit so if that's all super confusing don't worry too much about it then we can just run make install or we can say you know what let's just copy this whole line here and paste it them so and just roll with me I know this is a little bit confusing right now this will make sense to you much much later right now this is optional but if you can follow along to me at this point great now in our ZK sync devops tool now all those errors should go away you should see kind of a setup like this and what this is going to do is we have two tests in here that are going to show the differences between Foundry and Foundry ZK sync and then also the differences between ZK sync and an EVN chain so the first thing we're going to do if you're following along with me again this is completely optional this will be really helpful for later on when you're running tests with ZK sync and with other evm chains what we're going to do is we're first going to run this test here on what's I'm calling vanilla Foundry so the base installation of Foundry so in our terminal here we can just run Foundry up to make sure we're on vanilla Foundry we get an output that looks like this and then once again if we do Forge d-el we won't get any ZK sync stuff but if we run this test as it is right so I'm going to copy this do Forge test d-mt paste it in- vvv to just run this one single test it's going to go ahead and pass like this which is great now though if I switch to Foundry ZK sync so I'm going to do Foundry up- ZK sync like this now if I run Forge excuse me I'm just going to press up a couple times and I'm going to run this exact same test this will also pass however if we get rid of this skip ZK Sync here if we run this again and then add the D- ZK sync flag here and we run it again without this skip ZK sync it's going to compile and it may take a while to compile here and we can see that this actually failed now the reason this fails is because we're calling a very specific address known as a pre-compile that doesn't exist on ZK synad again you don't need to know what a pre-compile is but there's some really lowlevel stuff you also don't need to know what this assembly is you don't need to know anything about this function there's some really lowlevel stuff that ZK Sync has that's different from other evm chains so this function actually fails like that so there's going to be a lot of scenarios where a test will actually only pass on an evm chain and not pass on ZK sync when you add that-- ZK sync flag there will also be interestingly enough some scenarios where a test only passes on ZK sync and fails on any other evm chain so if we go to this Foundry devops package that we just installed and kind of scroll down in here and see what's going on we can scroll down to this usage ZK sync Checker so this ZK sync chain Checker comes with a couple different functions and modifiers like skip ZK sync only ZK sync is ZK sync chain Ison ZK sync pre- compiles Ison ZK sync chain ID and you can use these functions and modifiers to basically skip a test or only run a test if you're passing that dash dash ZK sync flag okay so if we put this skip CK sync flag back in here what is going to happen is this test is going to skip if it notices you're running with that- DK sync flag and it'll pass which is what we want to do right so if we run this again it'll take a while to compile now that we have that skip ZK sync modifier in there this test will pass because we're just skipping the test right we're saying hey we know that we're doing some stuff in this test that ZK sync doesn't support so we're going to go ahead and skip it so and we can see that we passed again because we skipped right what we don't want to do when we write our tests is have a whole bunch of them fail right anytime a test fails that should be a signal to us hey go back and fix this thing okay so that's the first thing this ZK sync chain Checker comes with this skip ZK sync modifier which will skip tests if it notices you're passing this --zk sync or running on the ZK sync Network now additionally and here's where gets a little confusing there are also some tests that will fail depending on what vers version of Foundry you're using so this Foundry ZK sync Checker is another package that I've created to check to see if you're on Foundry ZK sync or not and this test is commented out because it contains again some more advanced stuff in here again don't worry too much about what this advanced stuff is as we go deeper in the course it'll make more sense but this one will also fail if you're using Foundry ZK sync and it doesn't even matter if you pass the dzk sync flag or not right so let me show you so I'm going to go ahead I'm going to uncomment this out oops I'm gonna need to leave that commented out though and if we say test zync Foundry fails this only vanilla Foundry means that this test is only going to run if you're using vanilla Foundry and it will skip otherwise so if I'm in my terminal and I do Foundry up so this is going to switch us back to vanilla Foundry and I'm going to run this test so I'm just going to do do this without the dash cync obviously paste it in this will pass of course because we're on vanilla Foundry oh excuse me ffi is disabled uh we do need to have ffi so this is one of the more advanced things that I haven't quite taught you yet so in your Foundry Doo we'll do ffi equals true like this this is something that can be considered a little bit dangerous to use so just after you're done you want to delete it that would be great we'll learn more about it later but we'll go ahead we'll run this again and now it will actually pass because we have ffi turned on and it doesn't need pass now I'm going to do Foundry up- dzk sync we're going to switch over and you'll see that being on ZK sync Foundry even if I don't have this --zk sync flag so we can run this without the --zk sync flag and it would fail right so if we get rid of this only vanilla Foundry here let's run this test real quick paste it in here it's going to go ahead and fail it's saying reason unknown selector so this is like a very specific cheat code that currently Foundry ZK sync doesn't support maybe by the time you watch this it will support this cheat code but as of today it does not support this so we add back in this only vanilla Foundry clear the terminal here and we'll rerun this test and it'll now pass because it's now skipping this and what's interesting is you notice we didn't even do --zk Sync here right it's because on ZK Foundry it doesn't support all the same cheat codes that vanilla Foundry has so there's a little bit of a difference there now let's go back let's remove ffi let's recomment this whole thing out and remember in our DOT G ignore we want to make sure we have this ZK out now because you've compiled with ZK sync and we don't want to push that up to GitHub you'll learn about that in a minute but uh this is a little bit more confusing I know because I I asked you to kind of kind of blindly follow me here but I just want to reiterate what we just learned here this D- ZK sync flag means we're running on a ZK sync type Network and and if we do a test like we did in here that doesn't work on ZK sync it'll just always fail so we can go ahead and we can just skip those tests same thing actually the other way around there's some tests that will only pass on ZK sync so we have this other flag called only ZK sync where you know let's say this was a test that only worked on zkc syn we would add this only ZK sync modifier but right now we have this skip ZK sync modifier in here and if you go to the GitHub like I said you'll see kind of those all over the test Suite right so if we go in here um yeah you'll actually see oops sorry that's The Foundry devops one if we go into the test file of The Foundry fundme we go to test here go to unit fundme test we scroll in here we see some of these functions right is ZK sync chain right we have skip ZK sync modifier because we're doing something that ZK sync actually doesn't support for this test here that's actually the only one um but as we get deeper and deeper into the curriculum into advanced Foundry you'll see this more because some tests won't work on ZK sync and some tests won't work on vanill evm so so this is the tool that you can use this is the package that you can use to only run certain tests on ZK syc or only run certain tests on other evm chains and this is what you can use to only run certain tests on vanilla Foundry or only run certain tests on ZK sync Foundry again this is optional this will be helpful as you get later and later into the curriculum and as you go out and about into the real world and build these protocols and build these things you want to get really good at knowing okay like yes this test is only going to work on ZK sync so I need to do this this actually becomes much much more crucial way way way later in the advanced Foundry section when we get to minimal account abstraction we scroll down down in here there's actually a number of tests that only work on ZK sync and you'll see us use this only ZK sync modifier because the test actually won't work on vanilla evm because ZK sync actually has a lot of functionality a lot of power that is only native on ZK sync so all right but hopefully you learn some from this optional lesson when you go through the test Suites of cipon updraft and you'll see stuff like this it's because certain tests only work on either ZK sync or an evm chain so cool all right so now let's finally do our last step here which is going to be push to get Hub you have done a ton this project and this is the final step oh my goodness what a badass GitHub repo you are about to push up a couple of notes when we do this the first thing is make sure thatv is in yourg ignore I additionally like to add broadcast in here as well I don't like to push broadcast up anything that's not in here you could accidentally push up publicly to your GitHub so we don't want to do that sometimes it's good to even keep Li out and I'm actually going to do that here I'm going to put take lib out as well all right so let's learn how to push our code up to GitHub re this hardhead free code Camp because I made it in one of my previous videos and we're starting from a blank GitHub so at this point you should have a GitHub repository and you'll probably see even less on here than what you see right now because yours will be totally blank GitHub and get inversion control is so crucial because it's how most of the crypto Community interacts and builds with each other so anytime you go to any GI up repository like for example the a protocol which is completely open source you can come in here and you can make issues on the repo you can make poll requests you can actively participate in working with these protocols for example solidity which is what we're working on right now is also an open source repo and I know I've been saying this a lot but repo is slang for repository a code repository is where all the code of a project belongs it's one of the the beautiful things with web3 and crypto is that all the smart contracts you're going to work with are open source you can actually see the code learn from the code and get better yourself and if you're asking for places to participate and contribute most of these protocols have grants and they'll actually pay you to help them work with their code or if you just want to learn you can make PLL requests to code basis as well when I was first getting started in web 3 one of the best things I did was make contributions to the brownie repo which is a pythonic smart contract framework similar to Foundry and I did it for free because I wanted to learn and I wanted to see if I could contribute doing stuff like this allowed me to learn much faster and get to meet and interact with a lot of people in the community and it's a ton of fun and like I said this will be your profile for careers for jobs Etc anytime I'm interviewing a candidate for my roles one of the first things I do is actually look at their GitHub now GitHub is a centralized company and there are decentralized git Solutions being worked on right now but none of them are really popular at the moment so with that being said if we're at the GitHub docs right now we can go ahead to get started and we can even go to the Quick Start start there's a whole lot of docs here we should of course already have a GitHub profile set up and if you want you can go to this create a repo section which will teach you how to create a repo directly through the website but we want to do it from the command line why because we are engineers and we want to do what that's right we want to work incredibly hard to be incredibly lazy and we don't want to have to log onto the internet every single time we want to make changes to our code so what we're going to do is we're going to follow this documentation called adding locally hosted code to GitHub because our code here is obviously locally hosted we're going to push it to GitHub so if we scroll down in the docs here it gives us a little bit of and we down we get to our first bit initializing a git repository so if we haven't already installed git which we should you want to First install git before we keep going the directions for installing git can be found here and the GitHub repo associated with this course and you'll know you've done it right if you can do get-- version and you see something like this could be a slightly different version if this Git Version doesn't pop up pause the video and go and install git if you run into trouble of course you can use the discussions here or your AI friend now that you have git we need to initialize a git repository Foundry actually automatically initializes a git repository for us most of the time you can just run git status and see some type of output that might look like this if you don't see an output that looks like that after running git status you might have to do get init dasb Main and if we run this now we'll get a warning reinit ignored reinitializing existing git repository because we already have a git repository in here if you're using an earlier version of git we could do something like this but then what we want to do is we want to do something called adding our files so if we do clear now so first let's make sure we're on this correct folder right so we'll do an LS ah we can see all the stuff that we're in we'll do PWD as well PWD allows us to see the path that recurringly in LS prints all the folders and files in our current directory or folder right this is indeed the correct folder if you're not in the correct folder you can CD down or CD up into your correct folder but before we do get ad we usually want to do a git status this git status will tell us let me just pull this up here this git status will tell us what files and folders we're going to push up to GitHub one of the things we should always check when doing get status is is a EnV in here or is there any sensitive information in here and then I'll explain some of these greens and reds stuff in a second but looking at this I see get modules that's fine those libs are fine get ignore is good we definitely want to push up get ignore because get ignore is good we deleted those counters so those are good get snapshot make file okay the rest of this looks pretty good let's clear this for now if I were to pull pull this down now we're to open up myg ignore which we can do by either going to here and selecting dog ignore or we can open up our File Explorer with command P or control P depending on your environment and typing in dog ignore we scroll to the bottom we see this MV if I were to remove this and then save P my terminal up and do get status you'll now see this EMV does indeed show up in here we absolutely don't want this because these are the files that we're going to potentially push up to GitHub and expose to the Internet so we don't want to we absolutely don't want to do this we want to make sure ourv is in our doget ignore so we can do that or if you're being a total badass you've encrypted your key in a separate file outside of this package or maybe you're just going to use third web deploy instead of actually putting private keys in here but in any case we're going to do clear and now we're going to do get add period this period says add all of the folders and all the files that are in here in that git status except for the ones obviously in the duck G ignored now if I do get status now you'll see they're all green this means that all these green stuff are changes to be committed they're staged if you will they're in a stage position these are all the changes that we're going to commit to our history so if we type get log right now we can actually see a list of something called commits we can see see two in here right now you might see a different number I see two git keeps a versioned history of your code base this way in the future if you make a mistake you can revert back to a previous version very easily so now if we do get status again we'll see all this green stuff we'll look through these and looks like these are good there's nov here in here all of this looks like looks solid we'll do our first commit so we'll do get commit DN M which stands for message our first commit little exclamation point and hit enter and you'll see something like this pop up and then you might get something like this if you've never worked with Git before your name and email were added automatically a little bit confused here we'll talk about this in a second now if I do get status it says on Branch main nothing to commit working tree clean but if I do get log I now see a new commit our first commit even though it's the third commit it's fine our first commit great but if you flip over to your GitHub and you hit refresh there's still nothing up here so this commit history is stored locally in our computer we want to push up all that code up to GitHub here that's what we're going to do next so we did get add we did get commit and then we're going to do this bit importing a get repository with the command line after you initialize the get repository you can push the repository to GitHub using GitHub CLI or get one thing we can do is you can download this giit Hub CLI with GH we're going to do it directly with Git because if you want to work with gitlab or radical or something else in the future you'll be able to do it fine so we're going to scroll down to adding a local repository to GitHub using git it's important to note that GitHub and git are actually different git is this version control thing if I do git log it's this tool that allows us to do this Version Control GitHub is a website that allows us to push our git log and our git commits and all of our git stuff so git is a tool GitHub is a company and a website that allows us to push our git stuff so first thing we're going to need to do is create a new repository on github.com so we're going to go to GitHub our GitHub we're going to go to repositories we're going to do new we're going to call this foundary fundme f23 or whatever you want to call it you call it Foundry first repo probably no exclamation mark or be like thanks crypto is awesome or something like that I'm going to do Foundry fundme f23 add a description if you want let's make it public we're going to do some open sourcy stuff and we're going to skip the rest of this for now if you're really nervous about private keys and stuff you can make this private but keep in mind even making this private doesn't mean your private key is safe because anybody who works at GitHub could see your private key so we're going to make this public and it's good to get used to make making public projects and now you have a project on your resume and that's really cool if you make a private nobody can see your sick projects on your resume so let's create this repository and now we see we have a repository here and it's completely blank right there's no code in here there's nothing going on in here so we've done that though let's move to the next step at the top of your repository click the little copy thing to copy the remote repository URL so here so on my GitHub we scroll down here quick setup if you've done this kind of thing before just go ahead and copy this bit here and we're going to run a couple of commands here so first we're going to run get remote add origin and then paste that URL this remote keyword refers to a website like GitHub add is saying we're going to add a remote place for us to push our code origin is a shorten name for this giant URL and this giant URL is the actual place so with that if we do get remote- V we actually can see all the different places we can push and pull our code from right now it's just the single because that's the one we added so fetch is pull and push and they're both pointing to the same place next we're going to do get push dasu origin main get push D origin main this is saying we want to push all of our current code to the URL associated with origin which it's this one right here and on the main branch don't worry about branches yet now if you run into an issue like this or if you just run into any issue there's a couple different ways to troubleshoot one of the ways is actually asking chat gbt chat gbt is pretty darn good at troubleshooting get and get Hub issues one thing I can do for me my issue is that I'm logged in as my main account but I'm trying to push to this hard hat free code Camp account so I might do get config user.name and then I'll add user.name and I'll add this and what this will do is it'll change the user that I'm trying to sign in with and then we can do get push origin because origin is now pointing to this repo that we made and this is where we want to push to and then we'll say main because main is the main branch that we want to work on again don't worry too much about branches and for me it's asking for my GitHub password and and hopefully you'll see an output that looks like this if you go back to your code and you and you hit refresh you'll see all your code being pushed onto this GitHub repository fantastic now you have a project on your GitHub like I said if you run to problems chat TBT or find or some other AI buddy are normally very good at helping you out and working with get and making sure that git works this is phenomenal now of course we're going to go ahead and check this off our reading me looks pretty terrible here so if this were going to be more professional we would have a little about section this is a crowd sourcing app we'd have a quick a getting started with requirements quick start and some and yada yada yada we would do if we save that we would do then get add dot get commit minus M updated read me get push oops and then actually we can just do this so that we can just run get push instead of get push origin main every single time I'm going to copy this line now if I come back over to my project and I refresh we'll see there are now four commits this update read me is my most recent one if I scroll down to the read me we now have an about blah blah blah and stuff if you're looking for some extra credit try set up this read me without reading my readme and then once you think you have a pretty solid read me go to The Foundry full course get up repo associated with this course scroll down to lesson seven go to the code base here and you can actually go ahead and see if your read me is better than mine now that we know a little bit more about how git works you can see actually in my read me if you scroll down we have this thing called quick start with Git clones anytime you want to copy somebody else's codebase locally you can just run this get clone for example if I'm in myvs code pull up the terminal I'm going to go down a directory PWD great great I'm here LS I can make a directory Patrick fundme f23 I can come in and do get clone paste that URL the chain Excel org Patrick fundme f23 hit enter now if I type LS I'll have Patrick fundme f23 and if we do code Patrick fundme f23 which will open up our vs code or do file open this folder we can see this this is actually Patrick's project pulled down from GitHub for us awesome work and with that being said you now have a project on your GitHub that you can show off if you're excited about this scroll down hit this tweet me button and tweet at me like this and just get super hyped up right like I said it's great to celebrate the little wins so I know this was an absolutely massive section so let's do a little refresher on what we learned and then we'll call it a day so here's what we learned we learned more about how to set up a Foundry project more professionally we have our source folder with many different contracts in here we learned how to refactor our codebase so we can make it more modular we're passing a price feed in so that we can deploy deoy this fundme contract to any chain we want we've added an interactions script which has two different contracts fund fundme and withdraw fundme which we can use to withdraw and fund our most recently deployed contract we learned more about working with mocks in testing running integration test forking testing we learned a lot about gas we learned about storage we learned a tiny bit about make files and we built our first GitHub repo and we pushed it up and we are incredibly proud that we've done so so now is a great time to take a break and if you've made it this far you have most of the basic knowledge to begin going on your own if you really wanted to you could stop taking the course right now and just be on your way however we want to make you not just okay but phenomenal and prepared for everything this space has to offer so take a walk take a break get some coffee get some ice cream do whatever you want to do to take some me time and we'll see you in the next project all right welcome to lesson 8 you come down to the GitHub repo associated with this course we could scroll down to lesson 8 and all the code that we're going to be working with is here now it's going to be a little bit easier you do not have to code at all for this one congratulations for this one we're going to do it a little bit different for this one I'm going to teach you the basics of how your metamask or how your wallet interacts with a website so that you have that foundational knowledge I think it's incredibly important for you to know how to do this and it's incredibly important for you to verify that your wallet is sending the transaction that you actually wanted to send we are not going to be teaching you how to build a full snack application here however we have plans to launch a full stack course on cyphon updraft so be sure to follow along cyphon updraft and see if it's already out however this HTML fundme f-23 has a very basic raw JavaScript full website ation that if you want to try to replicate it you can absolutely do so but it is important that you understand what's going on under the hood when you're interacting with these websites and the knowledge we're going to teach you here will work for every single website that you interact with so you can actually know exactly what's going on when you interact with a website sending a transaction to the blockchain so normally I walk you through what we're going to do but for this one we're just going to go ahead and we're going to jump right in and now that you've downloaded git and you've been working with gting in GitHub we can actually start working with this code base as if we had just come across it so if we pull up our code base we're at Foundry f23 that reap it with all of our code in it what we can do is we can copy this URL and begin to work with it as if we just downloaded right from GitHub now all of my readms like I said are going to have this quick start which you can go ahead and follow this of course should be cyphon but what we can do to get started with this git repo is we can go go ahead and clone it get clone paste that in here then we can code HTML fundme f23 or file open that oh it looks like I already have it open here and great we have this HTML fundme repo here now what I'm going to do is I'm actually going to spin up this website so this HTML fundme has some very basic HTML in JavaScript to run a website I'm going to use this extension called live server which you can install to run the website right from ABS code alternatively you can open this up you could rightclick reveal and finder or just open this up in whatever file explorer you that you use double click it and open it up right in your browser and this is what the website looks like I'm going to go ahead though and use this go live button instead which will open it up here as opposed to in my path vs code will actually be serving it up so this is the website this is the minimalistic website that we're going to be using to show you exactly how menam mask interacts with the website now the first thing to understand when working with a website is this metam Mass bit if I rightclick and I hit inspect I get this little window over here and if I hit this double arrow I can go over to the console now this is a live JavaScript shell which has a lot of information about the browser that we're working in here if you don't know JavaScript don't worry about it but the most important bit here is that if you have metamask or some wallet what it does is it injects it into your browser object this browser object in this JavaScript shell is known as the window object and if I type window in here I get all this stuff all these functions that I can call on this window object and one of the objects that comes with the window is this window. theum metamask injects this window. theum object into our browser and it's this window. ethereum JavaScript object that these front ends these websites interact with to send transactions to our metamask or to any wallet that we're working with if for example we were to switch to a browser that does not have metamask installed go to that same site we rightclick inspect we go over to console and I type in window. ethereum here we get undefined because this has no metamask it has no API for us to connect with the mamass documentation has all of the information here that you need to know to actually send and work with this window. ethereum object if you want to learn more so cool so this is our website and we know we have this window. ethereum object now in our HTML fundme f23 if we scroll over to this index.js we can actually see the code that a website will use to actually interact with our wallet and usually one of the first things that you'll see is most websites will have some connect button it's a button for them to know hey there is a m mask here and there are accounts in here that we can actually connect to and send transactions to so here's an example if you go to this index.js file of some JavaScript that allows people to connect and work with the metamask this is what one of those async functions will look like so one of the first steps they do is they check to see that this window. ethereum object even exists and if it does exist they'll do something and they'll call something like this function await ethereum do request eth request accounts this is a function that the metamask object has that allows the website to see that there are indeed accounts that it can send transactions to It's not taking your private key or exposing your private key it's just allowing the website to send transactions for you to actually sign so in my HTML here I've got this button and again you don't really need to know HTML or JavaScript here but I've got this button called connect button and in my JavaScript I've got this line connect button equals document. get element by ID connect button and connect button.on click is going to call our connect function and this connect function is going to first check to see if metamask exists with this line and then try to connect one of those accounts right now if we go to our metamask we can see here that we're not connected to the site but if we go ahead and we click the connect button you'll see metamask pop up and ask to connect to one of our accounts to which we can select an account to connect and this is how our website actually gets connected and now we can see oh let me switch to account one now we can see our account one is indeed connected now that we're connected and we have some accounts we can then lower on call one of these functions and great so this website has some functions that look pretty familiar or should look pretty familiar we have a get balance a withdraw and a fund this website is actually designed to work with our Foundry fundme that we just created so if we go back to Foundry fundme it's designed to work with this contract if we go to SRC fundme doso function fund it's designed to work with fund and then also withdraw and then finally see the balance if I right click and I hit inspect I hit the drop down I go to console I hit get balance depending on the networker that I'm on i' get the balance of some address and if we look in the code there's this constants folder which has this contract address that's hardcoded in and we'll get the address of whatever contract is here on eth mainnet apparently there's a contract there how is it actually making this call how is it reading off the blockchain we go back to this index.js and we look for that get balance function we can see it's doing some interesting stuff here so first it's checking to see that metamask exists and then it's doing this line cons provider equals new ethers provider. web3 provider this ether's package is a JavaScript package that makes it easy to interact and work with metamask remember how in metamask we go to our metamask we select the little button we go to settings networks add Network we can actually see in our menam Mas popping up you see all these different networks we can go to add a network manually actually let's just go back to networks we see that each one of these networks comes with this RPC URL so what's happening when we call this get balance function and it looks like for some reason this address has some balance in it it's making an API call Via this RPC URL in our metamask so if we try to call fund or withdraw it would try to call fund or withdraw onto this address now in our M mask right now we're connected to eth Main and what we're going to want to do is we're going to want to practice interacting with a real contract using The Foundry fundme that we just created so if we pull up our terminal we'll go down in directory we'll go to CD Foundry fundme f23 what we can do is we can say make Anvil and we'll start a local Anvil chain create a new terminal here now we'll go down to directory we'll go down back to Foundry fundme f23 now we'll run make deploy this will deploy a fundme contract onto our Anvil chain remember foundary fundme we go to our found ref fundme repo we go down to our make file we go to the deploy Target in the make file we see we're running Forge script deploy fundme with network args which if you don't say anything it'll default to the Anvil Network so now we ran make deploy we deployed a contract fundme to this address and if you look in constant. JS it looks like that's already the address that's right here perfect so what we can do on the front end then is we go up to our menam mask we'll go to settings networks add Network and we'll go go ahead and we'll add a network manually for Anvil we'll type Anvil the RPC RL we can find right here from our terminal we'll copy that we'll do HTTP dot dot paste that in I already have this network so it's going to tell me hey this URL is already currently in use the chanity is 31337 currency symbol is eth or go or whatever you want to make it and there's no a block Explorer and then you normally hit save like I said I already have it in here so we can just select Anvil and boom all the details are right here now in our metamask what we can do is we can flip over to this Anvil chain and begin to interact with this website connected to our blockchain with this fundme contract that was just deployed so now we go and we can go ahead and connect we can hit get balance which is going to be zero because we just deployed this contract and we have our withdraw and fund functions here now obviously if I try to fund with 0.1 head fund we're going to get an error here because this account doesn't have any money but what we can do is we can grab one of the private keys from Anvil copy this go back go to accounts import account private key paste it in hit import and I've already imported it so it's saying the account I'm trying to import is duplicate then we can scroll down to that account that we just imported and connect to that account instead and now we have an account with some actual money okay great so now we have an account it's actually connected via the Anvil chain now an important note if this Anvil chain goes down or for example you are following along and you turn off and you come back to metam mask and maybe you'll switch networks switch back to Anvil you're going to get this whirling Circle of Death and you can X Out or do something like that or you can kill the network and reort it or you can just turn your chain back on come back switch over to anvil and we're connected again now since you just killed this network and restarted it though if you did deploy with make deploy you'd have to run make deploy again and great and we can go back to our front end we can see it was this account four that was one that actually deployed that contract so let's do a little refresh to get rid of that re warning we'll go ahead reconnect looks like we're good if we go to menam mask here we're connected awesome so now we can hit this get balance function like I said and it's returning the balance of that contract address that we just deployed so what we can do now is we can call this fund function by putting an amount in the amount section if I call fund metamask actually pops up saying hey do you want to call this fund function and we're going to go oh how does it know actually how to do that if we go back to our git repo and we'll go ahead and hide the terminal not delete it we can go to our index.js we'll look for the fund function CU we have the fund button and we're saying fund button. onclick call the fund function we'll scroll down here what it does when we call this fun function is it first it gets this eth amount by calling document. get element by ID eth amount. value so it's grabbing this 0.1 out of here on the front end we're checking to see if metamasks exists on the front end we're doing this provider line which gets the RPC URL from inside of our metamask again we use e ethers to get the RPC URL out of it we get this signer which allows us to grab this contract this account four that is connected this signer equals provider. geter it gets that account four and then we're doing this line contract equals new ether's contract and to interact with anything remember we need a contract address we need an ABI and to send the transaction we need a signer so the contract address we're getting from our constants file which is right here and if we pull up our terminal it's the same as what we deployed here and if it's not the same we would just copy paste it in there the ab we also get from our constants file and this ABI has all the functions that we can call on that contract one of them obviously is the fund function down here I'll go ahead and hide this again and then we have this transaction here where we do await contract. fund the transaction and we send some value by doing this ethers utils parse ether which turns that 0.1 into way like 0.1 gets sent to one one two 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 right and that's how this metamask actually pops up here because we're sending this transaction in JavaScript now what this does is it sends the transaction to our metamask so the website never accesses and never actually sees the private key the private key always stays inside of this metamask so the website sends a transaction to the metamask the metamask pops up and says do you want to sign this with the private key and you can confirm or reject now in here there's a lot of data right if we go to data it looks like menam mask was smart enough to know that this is calling a fund function but it's having a hard time knowing what is actually happening but we can see the raw transaction data in this hex section of the transaction and then of course we can see 0.1 go or ethereum the value being 0.1 right so this should be the fund function and we can actually verify that this is indeed the fund function by using the cast command to verify this data so here now I'm going to be teaching you a little introduction to function selectors and we're going to talk about this a lot more later on but the important thing to know is that in our contracts all of our solidity functions get transformed into this thing called a function selector and like I said we'll learn more about it a lot later but if we go to our function fund this needs to get broken down to some low-level bite code right and when we send this transaction we need to convert this human readable fund into the actual bite code the actual evm low-level code for ethereum to understand what function we're actually calling so what metamask actually does when calling this fund function is it converts it to its function selector and we can actually find the function selector ourselves by using a cast command so we'll run cast Sig which stands for Signature fund like this and we'll get an output like this this means the function signature fund returns the function selector this and again don't worry about these terms right now we're going to explain them in depth much later and this will make sense much later but what we can do is we want to make sure that this website that we're using isn't calling a malicious function right we want to make sure it's actually calling the fund function so we can run this command get this function select there and then go check out the hex here and say do these do these actually match so I can actually copy this hex data maybe I'll drop to the bottom of this paste it here and we'll grab what it should be here and boom okay great these do indeed match if I were to for example reject this transaction and I'm going to go to our constants I'm going to update this fund function from fund to Steel money let's say there was another function called steel money right I'm going to go ahead and save this cast Sig steel money would have a different what's called function signature and again don't worry about it too much but it just has a different like lowlevel hex encoding of this so now if we change this to Steel money and maybe the website was malicious and instead of the fund function calling fund called steel money instead we would want to make sure that we're not calling this steel money function so if I refresh the front end I'll put 0.1 in here I'll hit fund if we go to the data if we go to the hex what we can do then is we can copy this hex bring it back to the bottom paste it in here we can say oh it looks like this is the function that our menam mask is calling and we can run C Sig steal money like this and see oh my goodness our website is actually calling the steel money function and not the fund function that I wanted to be calling so this is a taste of how we can actually verify the transactions that we're calling now if this has function parameters we can do this thing called call data decode so these are functions that don't have any parameters right fund and steal money both don't have any parameters if they did have parameters this hex data would be a lot bigger right because we'd have to send a lot more data to call the function so later on on when you want to verify a transaction that has parameters what you do is cast D- call data- decode you paste the data actually let me see what this does goes say call data so you do cast D call data to code maybe something you know paste the signature paste the call data and if there are parameters in here and parameters with the call data it would tell you what each parameter of this function is and it's not a great example because there's no parameters in here but like I said you'll learn about this methodology later later so I just wanted to introduce it to you here that when you are sending transactions in metamask you are going to be the developers you are going to be the ones smart enough to know how to actually decode them like I said we'll go in depth more with that a little bit later but I'm going to go ahead and reject this for now we're going to go back to our constants we're going to change this back to fund going to refresh we're going to go back to index and we're going to steal money we're going to change this back to fund like this okay great so now if I go ahead and refresh now I put 0.1 in here I hit fund minam mask is going to pop up I can go to hex I can see this here I can go down I'll do cast I'll clear I'll do cast Sig fund like this I'll see that I'm expecting to call this function here so I'll paste this here I'll go to my metam mask I'll copy this I'll see if they're the same and sure enough they are okay great so now though I'm going to go ahead and hit confirm and when we hit confirm our metamask is actually finding this transaction and sending the function via that API call right that 127.0.0.1 55 that RP crl that we gave it for Anvil right and if we're on a main net or test net it's going to be that infura endpoint that comes built into minam mask right now that we've sent it we can actually call get balance now we can see the balance has indeed increased right the balance has upped what I could do now is withdraw As We Know we go back to our Foundry fundme we go to SRC go to fundme go to function withdraw we know that this is an only owner function so if we go back to our our application here calling withdraw from the owner will of course work but if I switch let's go ahead and switch to a different account we'll go actually let's go ahead and we'll send some money between our accounts we'll send some money to account three send maybe 100 doesn't really matter we'll go ahead and confirm this and this is sending of course on our Anvil chain right because that's the one that we're on now if I switch over to account three which now has 100 I'll connect to my account three if I try to call withdraw we're going to get this RPC error right execution error right call withdraw maybe we'll go ahead and refresh are we still on account three we sure are withdraw we're getting an error right because it's only owner but if I switch back from Anvil from account three back to account 4 now we're connected via count 4 I'll call with draw here we'll see metam mass does indeed pop up we go to the hex we can see this hex here I'll pull up my metam Mas to make sure I'll do cast Sig withdraw okay great this is the hex for our withdrawal function those look like they're the same awesome so I can have some assurance that I want ahead and confirm and call this withdrawal function so we're going to get that 0.1 out remember before the balance was 0.1 once this finishes mining the balance will go back to zero and sure enough that's exactly what we see so I know this was a quick lesson but I wanted to show you from a low level what actually interacting with these websites really looks like and if you're interested in doing more full stack work feel free to come check out this repo this HTML which has all the HTML and raw JavaScript for interacting with a website there are a ton of tools for working with react and spelt and other Frameworks as well if you're interested in building more full snack applications too and if you're unfamiliar with JavaScript some of this might have been a little bit tricky but let's at least do a refresher on the important things to know when it comes to interacting with websites and what's actually happening under the hood in order for a website to send a transaction to your wallet you need to connect to that wallet in some capacity and one of the most popular ways is by injecting your browser extension into right into the browser a browser can check to see that the metam mass object is there by doing a check on window. ethereum and seeing if it gets a return there are other ways to inject other types of wallets into browsers as well like wallet connect Ledger Etc but at the end of the day they're all going to connect some type of object to the website so the website can send transactions to the browser you'll usually hit connect and then you'll see in whatever wallet you're using that you're indeed connected when a website wants to send a transaction to our wallet what it does is it first needs to get the provider or the RPC URL out of the metamask and with ethers you see that the line that does that right here and what that line is doing is essentially is saying hey metamask I know you got some settings I know you have some networks in here I would like access to that RPC URL please so I can send transactions and additionally I would like access to one of those accounts in there so I can send transactions to one of those accounts can you tell me who's connected so I can go ahead and send transactions once it's connected it'll send a transaction to our wallet again the private key never leaves your wallet and we wouldn't want to use a wallet that actually exposes the private key so the website sends a transaction to our browser where if we do one now the browser will prompt us hey would you like to sign this transaction to which we have to confirm or deny we learned a very basic way of checking on something called the function selector or the function signature to make sure that the website isn't trying to be malicious and do a bad transaction for us we will learn later on in the course how to decode more complex transactions and more complex functions rather than just this one which has no parameters but we could go ahead and for example confirm this in my YouTube I've got a much longer video if you want to check it out which goes over how to actually connect your front end if you're interested to your smart contracts a couple different ways we have a raw HTML a nextjs and ethers nextjs and web through react nextjs and Morales nextjs and web3 Modell there's a lot of different ways to actually connect your front ends to your websites but if you want to learn more about how this works definitely be sure to check out this video the link to this will be in the GitHub repo associated with this course and of course all the code associated with this lesson is in the GitHub repo associated with this course as well if you want to learn more about how front ends and websites work so that's it for this lesson I know this one was quick but I do think it's really important that you understand how websites work when working with these smart contracts so you can work with them intelligently and know what to look out for this was a basic introduction and as we learn more like I said about function selectors and function signatures we'll get a lot better at working with these websites and then additionally being sure to protect ourselves against malicious transactions so now is a great time to take a break and was a quick one and I'll see you in the next one all right welcome back to the next section this says recently been updated for the new year and if you're following along with the GitHub repo and we can scroll down to section n all the code that we're going to be looking at is right here or of course if you're following along with cyphon updraft just write in GitHub resources scroll on down to section nine or basically The Foundry smart contract Lottery section now for this we're actually not going to be deploying this to ZK sync however we will be showing you a couple of tricks with ZK sync the reason we're not going to be deploying this to ZK sync is we have an integration with a certain chain that isn't active on ZK sync at the moment however we will be showing you other chains that you can deploy this to so that you can have a very cool very badass final project this is going to be a wonderful project for your portfolio why because we are going to not only write an advanced lottery or raffle smart contract we're going to give you even more best practices to work with so that not only can you build a really cool project but you understand the best practices and your code looks phenomenal so we're going to be learning a lot in this lesson we're going to learn about events working with true random numbers working with modulos chain link Automation and so much more we are actually going to create a verifiably random smart contract Lottery and we're going to learn a lot of really cool best practices doing this and let's go ahead and do a quick quick look at what the final product of this is going to look like so we in our vs code we can do a quick get clone like this and then open this up by pressing tab doing a little auto complete and boom get this going here all right and we can see here what our final project is going to look like and now that we've cloned everything in here we can go ahead and we can use the make file and ideally we use the make file because in here we're going to have this thing called pinned dependencies which we'll talk about in a little bit do a little make install like this we're going to be installing some very specific versions of some different dependencies some different smart contract libraries basically it's that same equivalent of doing you know Forge install then of course we can do a little make build or Forge build to actually compile our contracts here and great now that it's actually built we can actually go into our codebase here and we can see exactly what this is going to be so if you look in here there's really just this raffle dossou this is going to be the main contract we're working on here and we'll get to the Su lesson in a little bit but at the top here we see all these comments which we'll talk about in a little bit and if we scroll down a little bit here we can actually see some really professional looking natspec and this is also one of the reasons why I'm so excited for this code base for your portfolio because when you have really nice looking natspec this is an indicator to other developers and security researchers and other people this industry that you actually know what you're doing you actually know what good code looks like you know how to comment your code Etc so we're we're going to be going a little bit deeper going a little bit harder with some of this nice natspec to really make our code be a lot more readable and look a lot nicer and we have this raffle smart contract and what this is going to allow us to do is run a basic minimal smart contract Lottery completely automated so we're going to have this function called enter raffle where people can actually enter this raffle they can participate they this is like kind of the equivalent of buying a lottery ticket or a scratch ticket we have some interesting functions that won't make sense quite yet like check upkeep and perform upkeep but these are going to be the functions that are going to actually kick off and automate it so that once we set this up and fund it we pretty much can be hands off and we never have to say Okay start Lottery the lottery will just automatically start whenever it finishes running right whenever one Lottery ends the next one will automatically be triggered and automatically start without us having to interact with it which is really really exciting so we have a lot of functions in here like fulfill random words which handle dealing with the randomness and to work with this Randomness to get this provably random numbers we're going to be working with chain link vrf version 2.5 which is the most up to-date version this fulfill random words function essentially is going to be the function that governs picking the random winners right to actually facilitate getting who's going to be the winner of the lottery and then resetting the lottery so that it can start again so this is actually going to be a provably fair Lottery and then down here of course we have a whole bunch of different getter functions to actually read some of those view functions in the smart contract then we're going to be writing some more scripts and some more advanced some more really cool looking scripts here and we're going to be using some more advanced Foundry code as well and this is just going to be a really solid example of a very badass a very cool codebase for you to put on your portfolio and like I said before we're actually not going to be deploying this to ZK sync we're just going to be working with spolia because chain link vrf currently is not supported on ZK sync however we are going to show you some things about ZK sync that's needed for us to actually work with this and deploy if we go into our make file we can see all the different commands we can work with to actually interact with this codebase and interact with our smart contract like funding a subscription adding consumer create subscription these probably won't make sense to you right away but the most important one here is going to be this deployment piece right but with that now that you've seen a little bit of what the end result is going to look like let's go ahead and let's dive in so you have git Clon this already we can do a little CD dot dot go down on directory rm-rf Foundry smart contract Lottery f23 this RM stands for remove recursive Force so we're just going to basically delete that folder that we get cloned and now if we look in our folder this is kind of our vs code is like uh I'm empty now uh I'm a little confused here be very careful whenever you run this because you will forcibly remove everything so let's go ahead let's get started with our classic spdx license identifier and pragma solidity as of recording 0.827 is just around the corner however we're going to be working with a very specific set of contracts that work best with 0.8.9 so we're actually going to be using a slightly older version but that's all good here then we're going to do contract raffle like this pull apart terminal here and just do a little Forge build to make sure that uh stuff is looking good and it looks like it is so cool now like you saw us just walk through having natspec is a great way to annotate your smart contracts and especially right at the title right at the top of your smart contract you want to annotate it and tell random users or other developers who going to be looking code a little bit about the code base and if I do a little thing like this because I have a vs code plugin it actually gives me a little popup saying natspec contract documentation and if I click it it automatically populates it with a lot of normally what you'll see in some classic very nice natspec right so we're going to give the title we'll call it you know raffle contract we'll call it raffle or a sample raffle contract author is going to be Patrick Collins or you know put your own name here don't put Patrick Collins and then your notice is just going to be some notes here I'm going to say this contract is for creating a sample raffle maybe we'll also do add Dev implements chain link vrf v2.5 this little Dev tag is specifically for notes to give to Developers and this notice is really for anybody who's reading this codebase so let's do a little bit of a skeleton setup here where we just kind of name some of the functions here oh and actually I want to do MIT up at the top here but let's see we're probably going to want a function enter raffle like this we probably make this public or maybe external we're probably going to want a function pick winner and and this is really all of what our contract needs to be able to do right people should be able to enter the raffle they should be able to buy a lottery ticket and then the raffle should be able to pick a winner and that rewards people the money right so when people enter the raffle they buy the lottery ticket they pay their entrance fee and then the winner is going to be the randomly selected winner so in here this is where we're going to want to have our users enter the raffle and then pay some type of raffle entrance fee that will get added to the pool right the pool of money for the winner to actually collect at the end so in here this is where we're going to want to have our users enter the raffle and then pay some type of raffle entrance fee that will get added to the pool right the pool of money for the winner to actually collect at the end and this is where we're going to want to make some type of State variable maybe like a u into 256 uh entrance fee and this is where learning some of those Advanced pieces from some of our earlier sections is going to help out here right we want to think about okay well what should we identify this entrance f is well for me I'm always going to default to making these private and then making some Getters later on but we want to ask the question okay do we want to make this constant do we want to make this immutable uh what what do we want to make this obviously we're starting to understand some of the trade-offs if we make this constant that'll be the cheapest gas wise a mutable is also really cheap however if we set them as constant or immutable we can't go back and change them right for me I don't really care about changing this too much so I'm going to set this as an immutable variable which means that we're going to need to Define this entrance fee right in the Constructor so and then I gave it that iore prefix here to tell me hey this is an immutable variable it's pretty cheap gas wise to work with however you cannot change it so because of this we're going to go ahead we're going to make this Constructor here oh looks like get up co-pilot's already helping me out and we'll say U into 256 entrance fee like so and we'll say iore entrance fee equals entrance fee oops equals entrance fee like that and boom now we have some type of entran and this is going to be in you know the native eth or the native blockchain currency or whatever chain that you're working on here and since we're going to have some type of entrance fee our enter raffle function of course should be payable right and it should be payable because we're going to have to pay some of that message dot value right and so so then down below what we want to do of course then is going to create some getter functions and we're going to say function get entrance Fe and this is where get up co-pilot is very helpful as well we'll make this external view returns ENT 256 and then return iore entrance fee like so and then we'll pull up our terminal here just to do a quick Forge build make sure it actually is building and it sure is building correctly awesome and now that we're touching on this we're noticing that every single time we make some of these contracts we kind of have a very similar layout kind of have these State variables at the top we have different public and external functions here and then we usually have these View and pure functions at the bottom and having a very solid style guide or a guide on your coding style that you follow will actually help make your code much more readable later on and it'll actually help with security because if people can read it easier then they can know what it's doing much easier which leads us to the next lesson so we talked a little bit about the style guide for solidity and the different code layout and different and we talked about natspec however we didn't really talk about the ordering of our functions and The Ordering of our calls the solity docs actually do have an order of layout where we first start with our pagma which we're actually doing great then we do import statements we don't have any yet interfaces and libraries we don't have any contracts comes next okay great and inside the contracts do type declarations State variables okay no type declarations but State variable right here no events which we'll talk about in a little bit no modifiers obviously we have some functions which are coming next awesome and even the functions have an order where you do Constructor receive fallback and then your external on public functions and then your internal on private and then within a grouping Place The View and pure functions last and I really like that code layout but sometimes I forget to do that so what you'll see me do actually sometimes at the top of my code is all I even just paste this at the top this version layout so I remember how to do that if you go to the GitHub repo associated with this lesson me scroll down to where is it the code base here you go into SRC raffle doou you can actually just copy this and paste it at the top so this is the layout that we're going to be following here and I think this layout makes your code base just look so much more professional and it helps you know where to look for stuff when you're working with code so this is the layout we're going to use if you want to use your own though you're absolutely more than welcome to use your own code layout but this is what the solidity docs recommend and I'm down to go with the solidity doc all right so now that we've gone ahead and got the layout we can now finally come back to our enter raffle function and add some require okay so we want people to pay a little bit of eth to actually enter this Ravel right so that we can have a pool of money for the winner so we can add our require statement so we'll do a little require message. value is greater than or equal oops greater than or equal to iore entrance fee we'll do a little comma not enough eth sent sent this way if they don't send enough value boom it'll revert with not enough ecent however I have a little update to this I really want to teach you require because in a lot of Legacy codebases you'll actually see this functionality however there's actually been a couple of updates to solidity in regards to this require keyword so as of 0.8.4 of solidity they introduced this new thing called custom errors and you'll see something like this where at the top or somewhere in the codebase you'll have like error you know in the example in the slity blog here is error unauthorized and you'll see a little conditional or a little if statement right if some condition like message that sender does not equal owner revert with unauthorized or revert with the custom error now the reason they introduced this custom errors thing is that they say right here until now you could already use strings to give more information about failures but they are rather expensive especially when it comes to deploy cost and it's difficult to use Dynamic information in them so right now because we're storing this as a string here it actually costs a lot of gas to kind of have this as a string and and store it as such and you'll learn a little bit later about storing strings versus storing selectors and the different sizes that they are but essentially just having this string here is actually not very gas efficient and it's a little bit less performant that we would like so what we can do instead let's go ahead and comment this line out and the way I did that by the way on a Mac I did command backspace I think on Windows it's like control backspace or Linux it's control backspace there's some fun little shortcuts like that um but anyway so let's comment this out with the two backslashes here and what we want to do instead of this require statement we can say if our message. Val is less than iore entrance fee then we're going to revert revert with our custom error and there's a couple different places we can add custom errors we can add them actually even outside of our contract like error you know not enough eth but for testing this kind of is actually really annoying so most of the time we want to put it directly into our contract oops and then we'll even have like a little section here where we just say like errors like this so we'll say error not enough ecent or maybe something a little bit more descriptive like send more to enter raffle and we can say revert send more to enter raffle boom just like this now us another update to this as of even newer versions of solidity 0.826 they actually allowed you to add custom errors inside require because doing this conditional is actually much harder to read than this so they made another update where you can can actually do this and instead of that you can just say message value is greater than iore entrance fee send more to enter raffle like this however for this video we actually can't use that feature because we're using 0.8.9 of solidity so we actually can't use the custom errors in here and and I know this's a lot of information here so it's okay if you don't remember all this and technically this feature is only available if you compile your solidity with this thing called viir which takes a lot of time to compile and hypothetically this is still less gas efficient than this I'm not going to go into why because it's kind of really low level and for Stuff much much later on but the takeaway from this is that okay this is not very gas efficient because we're storing this big string here this only works on very specific versions of solidity with a very specific compiler version and this is the most gas efficient out of all these methodologies anyways so we should just so we should just continue to default to this as you get more and more advanced you will later on figure out kind of what the differences are and I'll you know we'll go over that much later but for now just always default to using this conditional so if some condition then revert and that's how we're going to do our checks in here now whenever we create some type of revert when we're actually getting these revert transactions it can be very difficult to tell where these reverts are coming from right imagine you send some transaction and it says Hey revert you know send more to enter raffle but maybe there's like eight raffle contracts it can be very difficult to know where the revert is coming from so a great best practice for errors for these custom errors is to actually give them a little prefix of the contract name and then two underscores before the actual error this way users who are reading and who get this error code will see ah okay there's raffle send more to enter raffle there's an error that says send more to enter raffle that's coming from the raffle smart contract so this is just a way to make your errors more readable so in remix here we've got an example of two different functions which are essentially the exact same we have one which is revert with an error so we're saying if false do this revert and we have this error up at the top and down here we have revert with require where it's required true otherwise do this revert so the functionality of both of these is pretty much exactly the same right it's just a little bit backwards this is saying if false revert and this is saying require true otherwise revert with this and if we actually deploy these contracts deploy drop down and pull up our terminals here if we if we call revert with error we can see how much gas this would have cost if we actually sent it right because remember even a revert you're still going to spend gas so this revert with error would have spent 142 gas versus revert with require if we hit that would have spent 161 gas and you can even see remix kind of gives a little gas heads up over here so this revert with error this custom error is actually much more gas efficient so whenever we're working with a is at the moment we actually don't ever even want to work with require so I know I taught you require and require is important to know because a lot of people still use it but as of recording you pretty much should always use custom errors because they're going to be more gas efficient in the future I'm willing to bet they're going to allow custom errors in here but at the moment they don't so please default to this syntax up here so so we've already added in our error here but we can actually scroll back up and see where we need to put our errors so if we see layout of a contract version import errors okay we scroll back down okay version we don't have any Imports okay cool errors so that's how we're going to make sure that we're putting these errors in the right spot in our contract layout so okay great so now that we've learned a little bit more about that let's move on to the next step so we have our function enter raffle and we want to keep track of all the players who enter our raffle so we're going to need to keep track of all these players now I want to ask a question okay well what data structure should we use how should we keep track of all these players you've learned about a couple different data structures now right you've learned about arrays you've learned about mappings you've learned about un 256s different state variables what data structure should we use to keep track of the players what makes the most sense now there's not necessarily a right or a wrong answer here and the more you do this the more you'll get better at understanding which data structures to use in which scenarios but most of the time I'll actually tell you to default to some type of mapping and that's usually a really good scenario however for this one we're actually going to use an address array so I'm going to make an address array as a state variable private sore players right because it's going to be a storage variable and this address array is going to be just a list of all the players who entered this raffle and I'm making this a storage variable because the number of players the amount of players is going to keep changing right more people are going to constantly be entering so I don't want to make this immutable I don't want to make this constant I want this to be updatable but I'm going to actually update this I'm going to make one more change to this as well since whoever wins this Lottery is going to need to be paid the money I'm going to make this a payable address array so this is the Syntax for making an address array payable so we have our players array and then what we can just do is anytime somebody enters the raffle we can do s players. push the payable message. sender like so remember we need this payable keyword here in order to have an address receive eth and now this function's almost done there's actually one or two more things that we need to do however there's a rule of thumb that we should always follow whenever we update something in storage and this rule of thumb is going to always be emitting an event whenever we update a storage variable and events are this new place in smart contracts and a new place really in blockchain that we haven't really spoken about and when I say new place I mean there a new place that we haven't worked with yet it's not really new and we're actually going to watch a little video that I've made before that goes deeper into events and understand why we need them and how to work with them but the two main reasons that people might want to work with events are going to be making migrations easier if you ever have to redeploy a Smart contract it can be very difficult to move all the storage to the new contract if you admit events it makes them it makes it much easier to do it also makes front-end indexing much easier and this is something that to be honest it's not going to make a lot of sense to you until much much later in your smart contract Development Career the summary is getting data off the blockchain even though it's this public Ledger that anybody can read can actually be really challenging depending on what type of data you're looking for since this isn't going to be a full Sack or a front-end course this second section probably won't make sense to a lot of you now however much later we are working on a new Full stack course and those of you who are interested in taking that can feel free and this second one will make a lot more sense then but let's go ahead and watch this video I previously recorded about events that will give us a better understanding of what they are what they look like Etc but let's go ahead and let's watch this video that I previously recorded about events now I have two videos on this one is on my channel one is on the chain link Labs YouTube channel the one on chain link Labs uses hard hat the one on my channel uses brownie let's watch just the part about setting these up and working with these and we won't actually watch the brownie or the hard hat Parts because we're going to be working with events in Foundry ourselves now if you've worked with solidity you've probably seen these things called events before or maybe you haven't seen something like events but you've always wondered how chain link or the graph or some of these other offchain protocols work under the hood or maybe you just love watching these vods in any case in this video we're going to learn all about logging and events in solidity how to view them on ether scan and we'll work with them in brownie as well now if you like hard hat once again I also have a hard hat version of the code that we're going to go over and got a hard hat blog as well links are in the description all right let's get froggy now it's the ethereum virtual machine or evm that makes a lot of these blockchains tick like ethereum and the evm has this functionality called a logging functionality when things happen on a blockchain the evm writes these things to a specific data structure called its log we can actually read these logs from our blockchain nodes that we run in fact if you run a node or you connect to a node you can make a f get logs call to get the logs good function naming design get logs gets the logs now inside these logs is an important piece of loging called events and this is the main piece that we're going to be talking about today events allow you to print information to this logging structure in a way that's more gas efficient than actually saving it to something like a storage variable these events and logs live in this special data structure that isn't accessible to Smart contracts that's why it's cheaper cuz smart contracts can't access them so that's the tradeoff here we can still print some information that's important to us without having to save it in a storage variable which is going to take up much more gas each one of these events is tied to the smart contract or account address that emitted this event in these transactions listening for these events is incredibly helpful let's say for example you want to do something every time somebody calls a transfer function instead of always reading all the variables and and looking for some to flip and switch all you have to do is say listen for event listen for that event to be emitted instead of writing some weird custom logic to see if the parameters changed at the certain time and doing some weird stuff like that listen for these events so a transaction happened an event is mitted and we can listen for these events this is how a lot of offchain infrastructure works when you're on a website and that website reloads when a transaction completes it actually was listening for that transaction to finish listening for that event to be emitted so that it could reload or could do something else it's incredibly important for front ends it's also incredibly important for things like chain link and the graph chain link for example in the chain link Network a chain link node is actually listening for request data events for it to get a random number make an API call or Etc sometimes there are way too many events and you need to index them in a way that makes sense so that you can query all these events that happen at a later date the graph listens for these events and stores them in the graph so that they're easy to query later on so events are incredibly powerful and they have a wide range of uses they're also good for testing and some other stuff but you get the picture they're really sick now that we know what events are let's look at what they look like how we can use them and how we might use them in our smart contract development Suite now here's what an event is going to look like we have an event here called stored number so we have basically a new type of event called stored number we're saying hey solidity hey smart contract we have this new event thing we're going to be emitting things of typed stored number in the future when we emit this event it's going to have these four parameters it's going to have a u 256 for called old number a un 256 called new number a un 256 called added number and an address called sender now for the astute people here you might have noticed that there is another keyword in here the indexed keyword and this is a really important keyword when we omit one of these events there are two kinds of parameters there are the indexed parameters and the non-indexed parameters you can have up to three indexed parameters and they're also known as topics so if you see a topic you know that that's going to be an indexed parameter indexed parameters are parameters that are much easier to search for and much easier to query than the non-index parameters in fact way back in that F get logs function it even has a parameter allowing us to search for specific topics so it's much more searchable than the non-index ones the non-index ones are harder to search because they get ABI encoded and you have to know the ABI in order to decode them if that confused you don't worry about it we're going to explain it isn't this video great now this has told our smart contract that there is a new type of stored number a new kind of event here we need to actually emit that event in order to store that data into the logging data structure of the evm to do that we need to do something that looks like this this is what it looks like when we emit an event it looks very similar to calling a function so you call AIT and then the name of the event and then you add all the parameters in there that you like here's the full example of a smart contract that has an event and is going to be the example that we're going to walk through in brownie again if you want to see a hard hat edition of this link in the description for the hard hat Edition both of this video and the blog now in this smart contract whenever anybody calls the store function we're going to emit this event here's an example of a transaction where we called the store function with a value of one let's look into the logs to see what this event actually is going to look like an event is going to be broken down like so the address of the contract or account the event is emitted from the topics are the index parameters of the event data this is the ABI encoded non-index parameters of the event what is this mean this means that we took those parameters that were non-indexed we matched them together with their ABI or application binary interface pumped them through an encoding algorithm and boom this is what we got if you have the ABI they're very easy to decode if you don't have the ABI they are very hard to decode these non-indexed parameters cost less gas to pump into the logs and are harder to query like we said so if you think something's important but like not that important you dump it in data you dump it into non-indexed now in this particular contract since we have verified the code we verified the contract ether scan knows what the API is and we can view this in deck or decoded mode hex mode is obviously the non-coded mode or in its raw hex or hexad deal or encoded mode you can read more about the layout of these events in the solidity docs all right great so now that we've learned a little bit more about events and why we need them let's go ahead and use them in our smart contract so for us we're going to actually scroll up and see where we should put our events here we can see that our events are going to go right after our state variables so if I scroll scroll down okay cool here are our state variables so maybe we'll do a little events comment like this and we'll create our events and we're going to want to create an event called raffle entered or raffle enter or whatever you want to call it we'll say raffle enter and I like to do verb based events so maybe like raffle entered like this and then here we'll just do address index next player like this to say okay a new address a new player has entered the raffle and then in here we can do Amit raffle entered message. sender like so and now whenever somebody calls this enter raffle function they will get added to our s players array and we will go ahead and emit this event which like I said for now it's okay if you don't really understand why we need these events just know as rule of thumb anytime you update storage you want to emit an event like so and awesome our enter raffle function is just about done we're going to update it pretty soon with something else but this is pretty good so seems like our code is pretty straightforward right this enter raffle looks pretty good it's pretty much done so now we want to go ahead and pick a winner right and we're and you might be thinking wow Patrick this code base is about to be so easy this is so quick well this is actually where it gets really interesting and a lot more advanced so buckle up so our pick winner function needs to do a number of things first off it's going to need to get a random number right obviously in order to pick a winner so then it's going to need to use that random number to pick the player and then three this needs to be automatically called I can't be bothered to call pick winner every week or month or however long these lotteries are I'm busy I have stuff to do so I want this to be programmatically automatically called however as you may start to be thinking about huh smart contracts can't really automate themselves so how are we going to do this Patrick well we're going to get to that and we should probably also make this an external function because we want this to be a little bit more gas efficient we probably should also make our enter raffle external and again as you kind of code more and more you'll get better at sniffing that out and there are some tools that we can use to help sniff that out whether to use public or external but so for now let's not focus on this number three let's just focus on getting a random number and using that random number to pick the winning player so in order for us to get this random number we're going to want to check that enough time has passed right we want to check that hey the lottery has gone for enough time so it's time to call a random winner right we want to basically deploy the contract say every say every minute we should run a new Lottery maybe every day maybe every month maybe this is a yearly Lottery whatever we want this to be we want to first check how long it's been and so we're going to need to pick some type of interval for our lotteries to last how long do we want our lotteries to last so up in the Constructor I'm going to create a new variable a un into 256 interval like this and I don't really want to change this I want to set it once and then kind of forget about it and because of that we kind of know what type of variable this is going to be so this will be a unit 256 private iore EXC a mutable iore interval and this is going to be the interval between Lottery rounds so we'll do iore interval equals interval and in interval not internal and it's going to be set right in the Constructor I'm going to get rid of this line now too and this is where comments are a little bit helpful we'll do a little at Dev tag here and we say the duration of the the lottery in seconds so this will be how many seconds between each Lottery run so now in our pick winner function we want to first check to see we want to first check to see if enough time has passed and we can do that by getting the current time by doing block. timestamp and this is what's known as a globally available unit similar to message. sender and message. Val it's going to be the current approximate time of according to the blockchain so we'll get the current block the time stamp minus some last time stamp and it should be greater than the iore interval interval right so this is to say let's say the block time is a th000 you know for it's like 1,000 seconds the last time stamp we recorded was like at 900 seconds and our interval is you know 50 so 1,00 - 900 = 100 that's greater than 5050 so we can go ahead and start a new Lottery run however if the interval was 200 this would mean that only 100 seconds passed we need another 100 seconds so not enough time has passed but what we do though of course is we need to take some snapshot of time right we need to keep track of the every time we picked a winner so that this last time stamp is constantly updated so since this is probably going to be some storage that persists we're going to make this a a storage variable and we'll scroll up to our state variables and we'll create a new variable here U into 256 private sore last timestamp like so and we're going to want to set this right away right in the Constructor right when we deploy this smart contract this last timestamp should be the most recent block. timestamp right so right when we deploy this contract it'll be populated with something that way the lottery doesn't get kicked off right away right when we launch this we'll basically start the clock if you will and then what we can do is now we can say okay well let's do a little conditional here so we'll say if block a timestamp minus the last Tim stamp let's say actually is less than the interval then what then we should revert right because not enough time has passed and then we're going to want to fix this conditional here and of course since we're going to want to revert here we're going to want to add one of our custom errors so we'll do a little revert in here and I'm going to tell you right now we're going to refactor this pretty soon so I'm just going to leave this like this for now and we'll add the custom error in a little bit so if enough time has indeed passed then we're going to want to go ahead and get our random number now getting random numbers on the blockchain is actually quite difficult for a number of reasons the biggest reason is that the blockchain is a deterministic system by default and we are looking to get a random number in a deterministic system and that's very hard so what we're going to do is we're actually going to go to docs. chain. link we're going to go to the vrf documentation and we're going to work with chain link vrf to actually get a provably random number and to teach us how to get a random number using chain link vrf V2 we're actually going to go watch Richard's video from the chain link team who will walk us through that now for our code base we're actually going to be using the most upto-date version which is going to be version 2.5 so the code that we're going to be working with is going to be pretty much exactly what he goes through here it's going to be slightly different but this will still give you a really good understanding of how it actually works chain links verifiable Randomness function or vrf gives developers better scale flexibility and control hi I'm Richard developer Advocates here at chain link labs and today we're going to take a look at chain links vrf the big important thing to know about vrf is you're funding a subscription which is basically an account that allows you to fund and maintain balance for multiple consumer contracts I like to think of it as a bucket that all your contracts can pull from let's dive into the docs and see what using vrf looks like and feels like in order to show that let's Dive Right In to getting a random number from the documentation so we'll take a look at the documentation now if you head to docs. chain. link you'll see this page and we have data feeds functions Automation and vrf if we head to the vrf documentation we'll go directly into getting a random number now the documentation does cover a lot of other information that is very useful to know but for this tutorial we're skipping right to getting a random number you can read about subscription management here and how it works instead of reading through this we'll actually just walk through this process if we click open subscription manager we'll see the subscription manager and we'll need to create a subscription now you can give it your email and project name if you like I won't for this example but we'll be creating a subscription and you'll notice here that we're prompted to actually confirm this on a test Network now something to note I'm doing this on the sepolia test Network most of the chain link documentation references the pooia network as the default test Network so that's what I'll be using just to make life a little bit easier you can use test networks that are supported if you like you will need some eth and Link tokens for this if you don't have those you can head to faucets. chain. link to secure that and we'll take a look at that here in just a moment so we create our subscription we'll need to add some funds so click add funds and it'll take us to the next page and I mentioned the faucet right here if we need link for testing you can get that from the chain link faucet it's at faucets. chain. link you'll need to connect your wallet I've already done that once you have you pick the network netor that's appical remember we're using ethereum sepolia in this example we can request link and eth if you do need eth you will need to verify via Twitter but for link itself you'll just need to complete a capture so once you've done that you should be able to get your link so we need to add some funds for this example I'll just use five it's going to be more than enough we'll approve that transfer as well and our link has been transferred now we'll need to add consumers and this gets to an interesting point in creating VF so we've created that bucket right that subscription we have funded it with link and we have what we need there but we haven't actually deployed a contract yet and the way that vrf works a mental model think of besides the bucket of link for our subscription is that you need to let your subscription know about the contract you're deploying and when you deploy your contract you're going to need to let that know about your subscription we'll see what that looks like but basically they need to know about each other in order to function properly so at this point we'll head back to the documentation we'll just leave the subscription manager right here on this ad consumer page as we scroll through the instructions we'll see deploying a vrf V2 compatible contract and there's this awesome open and remix button here we'll click that and from here it'll take us to remix so remix will allow us to deploy and interact with this contract on the blockchain let's take a look at the actual contract that we'll be deploying briefly at the top here you can see that we have our Imports of the coordinator interface our consumer base and confirmed owner coordinat interface is going to be what allows that coordination of reaching out to the Oracle Network to get the actual random values consumer base contains some functions we'll be importing and using within our contract as well as confirmed owner which will bring in information that allows us to ensure that only the owner of this contract can do certain functions if we look at the contract itself you can see we declare some e events we have struct for the request status that'll let us check the status of our request we have a mapping for those request statuses we have our subscription ID this is what I was mentioning we need to let the contract know about our subscription so that's what we'll store that information we have a few variables for the request IDs we have a key has now this key has is important because this is specifying the gas Lane that we'll be using it's basically how much we're willing to pay as a premium for gas for faster responses on the test Nets there's only one if you take a look at the link there in the documentation you can see the different gas lanes that are available on the different networks each gas Lane will have its own address so it's something to keep in mind we also have the Callback gas limit the way that vrf works is it goes and makes a request to the Oracle Network and when it makes that request the Oracle Network goes off generates the random numbers and then comes back right and when it comes back that's when you to actually do something with the random values that are returned if you don't do something with them as soon as you get them back then they're stored and that information becomes public so they're not really as random as you would like now when it comes to that call vat gas limit that's going to be the maximum amount of gas that is available to be used in that callback function and we'll see that callback function here in just a moment we have a number of confirmations that we would like to have this is how many block confirmations need to go by before those values are returned the way I like to think about this is the lower this number the faster you'll get your response back but the less secure the higher it is the more secure but the slower so it's a trade off you need to balance it with what's important for your project and then we have the number of words when it says words here if you were to look up words from a computer science standpoint you'll find that's technically the correct term for the values that we're getting back I like to think of them as just random numbers because it makes my life a little bit easier when I'm thinking about them so this is a number of random numbers that you'll be getting back in this case we're getting back two uh but it can be more than that and it can be as little as one so you can get multiple values back in a single transaction which is really cool so we have our Constructor here where we set things up we give it the coordinator when we deploy this contract we'll give it that subscription ID and then we have the function request random words again this is going to be reaching out to the Oracle Network to make that request so we store a few things in here like the request ID and we get that information and we emit the event then then once everything has happened within the Oracle Network we get our random numbers back the way it comes back into our contract here is through the fulfill random words function now this function doesn't do much right it just stores the information this is where though you would want to actually do anything with those random values think if you are assigning traits to an nft or something like that you want to do that here as soon as they come back into your function we have one last function get status request just to see what's going on with our request so let's deploy this contract now we'll need to make sure that we change it to our injected provider and then we need to give it our subscription ID if we had back to our subscription we'll notice your ID is 1 1923 if you're following along doing this yourself your ID is going to be different most likely paste our ID in here and click deploy and confirm this transaction all right so our transaction is confirmed we have our contract down here now we'll need to grab the address of this contract and head back to our subscription this is going to be the consumer address so we'll paste it in here and we'll add a consumer all right so our consumer has been added let's look at our subscription now we can see here A Brief History of what's happened right we created our subscription we funded it and we added that consumer now when we actually make a request we should see it here in our subscription that the request has happened so let's go do that now let back to remix and we will request random words we'll confirm this as well and then we can head back to our subscription and take a look but we'll need to wait for our transaction to actually be confirmed before we'll see anything here all right so it's been confirmed if we take a look at this page now we'll see that we have a pending transaction right now remember depending on the network you're on depending on how many block confirmations you said this can take a while so we'll wait for this to go through and then we'll see it actually in the history here that we have completed our transaction while we wait for the transaction to be completed if we take a look here and we say last request and we copy this ID to get the status we can see that it's actually been fulfilled while I was checking this so our Boolean is filled is true and we have our random values now the thing to note is that we ask for two random values right and if you look closely right here in the middle there's a comma so we have one number here and the second number afterwards so that's it this is what it takes to get random values back using chain link vrf now from here you have tons of opportunities with what to do with this right it's everything from determining Randomness when it comes to game assets nfts anything that you like really so yeah I can't wait to see what you'll build with this and I'll catch you in the next [Music] one all right all right great so now we know a little bit more about chain link VF let's go through the documentation and actually implement this in our codebase and in particular I think actually going through the documentation here even on video with you is incredibly helpful because guess what you're going to be doing this a lot going through documentation working with AIS that have read the documentation and can help you implement things but getting good at reading documentation and traversing documentation is a skill that you will need to get good at and to work with chain link vrf there's a couple different of methodologies you can work with to get it going there's the subscription method and the direct funding method so we're actually going to teach you the subscription method because I think it's a little bit more scalable and this will enable us to do a little bit of upfront work so that later on we don't have to do as much work we want to work incredibly hard to be incredibly lazy and if we can do a little bit of extra work now so that later on we could be very lazy we will choose to do so and for people who want to get a really good feel for how chain link VF actually works I highly recommend you come to the documentation here go to either the getting started page or one of the migration pages and you could scroll down in here and there's this open in remix button which will open up an example in remix for you to actually work with the chain link vrf that you can play with right in remix this remix example is defaulted and hardcoded with working with the suia chain so so if you want to give this a try feel free to pause the video and try this out so if we go to the documentation on the left side here we can see there's V2 subscription method V2 direct funding and we're actually working with v2.5 but basically you know same thing here and the subscription method is going to be where we're going to have a smart contract a singular subscription smart contract that we send link to we send basically Oracle gas to to fund the chain link node and then we have direct funding where we actually directly fund the contract that implements VF so basically like this would be us directly funding the raffle smart contract versus the subscription method is US funding some separate subscription smart contract the subscription method I think is arguably a lot better because with the direct funding method every single time we deploy a new raffle we would have to refund it as well whereas with the subscription method we only need to fund that singular subscription and apply that to as many Raffles as we want like I said we're going to be learning the subscription model however it requires a couple of extra steps and we're going to learn how to do those extra steps programmatically which is very exciting let's go ahead and let's add this randomization now remember according to Richard getting a random number is actually a TW transaction process we first have to make a transaction to request the RNG or the random number generator or the random number and then in a second transaction the chain link Oracle will actually send a transaction to give us or add some random number on chain and what we've been doing so far has been Atomic or in a single transaction where everything happens automatically and this is one of the reasons why I love showing the chain link vrf functionality and chain link automation as well because it's going to get you used to working with some of these two transaction processes so pick winner is actually just going to be us actually requesting the random number from chain link vrf and then the chain link VF is going to give us that random number in What's called the Callback function basically the function that chain link vrf is going to call back to so we're going to send the request in a transaction that we send and then the chain link node is going to give us the random number in a transaction that it sends so to begin actually working with chain link vrf and requesting and getting this random number we can actually go to getting started with chain link VF 2.5 we can go to this remix example and basically just copy paste some stuff from here and even if you want to go into remix you go to Remix 2 or that ever that giant remix button is boom yeah open a remix and we can kind of use this as our template here if we scroll down in here there is going to be this section here this request ID equals s vrf coordinator. request random words and then does this huge chunk of stuff here and this is the actual call to the chain link coordinator to the chain link node that we're going to make and there's a whole bunch of stuff in here and don't worry we will explain what everything does so for now I'm actually just going to go ahead and cheat a little bit I'm going to copy this going to come over to our code base here and we're just going to go ahead I'm going to delete these comments and I'm going to paste this in here and then if we pull up our terminal now and we do a little Forge build you're going to see hey uh it doesn't actually work and maybe you even see some red squiggly lines in here H but don't worry we're going to fix that very soon so there's a whole bunch of stuff in here that needs to happen in order for this to work so uh first we can see we're having this sv. request random words so you can already kind of tell now that you've been learning more and more about smart contracts and solidity like what this is trying to do so we can probably see that this SV of coordinator is going to be some type of coordinator smart contract right and it's going to have some function called request random words and the first thing we're going to need to do is actually get thisf coordinator address here so what we can do is actually back in the remix back in kind of our our demo here if we scroll to the top we actually can see two contracts that we're actually importing and then one of them in this example that we're actually inheriting this vrf consumer base V2 plus I know it's kind of a mouthful um so what we can do then is we can actually grab this whole line we copy it come back over and go all the way to the top and import it here and we're going to tweak this just a little bit so since we're actually importing from the chain link contracts here we're going to as you know we're going to have to install this with Foundry using the chain link brownie contracts so once again chain link brownie contracts these are going to be these minimized contract examples scroll down here okay cool forage install um we're going to cop copy this here pull up terminal do a little clear paste it in and for this walk through I'm actually going to be using what's called pinned dependencies pinned dependencies this is where we install very specific version of packages so I'm going to be using version 1.1.1 so that no matter when you watch this as long as you use the exact same versions that I'm working with the code will always work so that's what we're going to be doing here so to just do that we're going to do Forge install Smart contract kitchan Leake brownie contracts at and then we're going to pick a tag in the releases section of GitHub so we're going to do 1.1.1 -- no commit and hit enter and this is going to go ahead and install chain Leake brownie contracts at 1.1.1 so now if we go up here we can see boom chain Leake brownie contracts is now inside of our lib and we're going to update our Foundry do tumml and since this is installed we're going to go to our founder. TL and do a little re mapping section right you're already starting to figure out what you need for these and we're going to do remappings equals little at chain link SLC contracts like so equals lib slash chain link brownie contracts SLC contracts like this and this should now work actually we're even getting a little red underline because this has some of these versioning bits in here so the remix adds kind of these versioning bits in here if you copied right from remix we can actually just get rid of that at 1.1.1 and the rest should be good the file path of this might be a little bit different depending on when you watch this but now we have this vrf consumer base V2 plus and we can inherit all the stuff by just saying raffle is this and obviously you know a little bit about inheritance so if I go ahead command click or control click it'll pull me up right into the code base here and if that doesn't work for you for some reason you can of course go to lib chain Brown and contracts contracts SRC v08 Dev uh vrf excuse me v08 excuse me uh where is it vrf vrf Dev vrf consumer V2 base plus. s vrf consumer base V2 plus. Soul like this and this is going to be the contract that our raffle is going to be inheriting and there's a whole bunch of stuff in here don't worry about it too much for now but in this vrf consumer based v2+ it has a Constructor that looks like this where it takes an address of a vrf coordinator here if you inherit a contract that has a Constructor like this what you need to do is in your Constructor you need to add that contract's Constructor a little confusing right so the Raffles Constructor right now is just this right we're just kind of adding these variables but if we inherit a contract we also need to add that inherited contract's Constructor right so if we say is some contract we got to add their Constructor and the contract here's Constructor is just taking this address VF coordinator so what we'll do then is next to our Constructor we'll add the name of the contract we are inheriting and then add add what goes in its Constructor so in its Constructor it takes us vrf coordinator which is the address of the vrf coordinator contract so this vrf coordinator contract is the contract we actually interact with to request random numbers right so we need to get that get that adders kind of similar to how we did with price feeds from the chain link documentation you would get this directly from the chain link documentation right kind of same as what we did with price feeds but what we want to do is we want to make this kind of modular so we want to go ahead and do a little comma we'll say address VF coordinator we'll put it in our Constructor and then pass it from our Constructor to the vrf consumer base V2 plus Constructor right so a lot of words there but summary real quick if we go ahead and we inherit this then we need to use the Constructor of the inherited code base and we just kind of stick it on like this this inherited cbase needs a vrf coordinator address we will pass that to our Constructor from our Constructor to their Constructor and boom now what's cool is this vrf consumer base V2 plus has this s vrf coordinator variable and now we actually have access to this variable as well and what's kind of cool so if I actually come in here you know we see all these squiggly lines now let's actually just comment this out let's do a quick Forge build just make sure we're doing everything right looks like we're not doing everything right oh it's because we need we need to add our fulfill random words function I'm actually going to copy paste that real quick just so I can show you something cool uh fill random words internal virtual override internal uh now let's go ahead Forge build Okay cool so now that we've done that what we can do is we can do stuff like VF coordinator do request random words or whatever right in our WRA of contract we've never specified vrf coordinator as one of our state variables but since we're inheriting it from this vrf consumer base V2 plus I know it's a mouthful we can actually work with this svrf coordinator address as if it was in our list of state variables which is really really cool so if we go ahead and do Forge build boom it's compiling fine pick winner we're going to have to update pick winner in a little bit but because we've inherited that codebase we can now do stuff like vrf coordinator. request random words like this because we have access to this s vrf coordinator variable since it's in this vrf coordinator vrf consumer base V2 plus right mouthful I know so anyways let's keep going so we're going to call this vrf coordinator. request random words and we have to pass a whole bunch of stuff in here so let's actually go to this vrf consumer based v2+ we can see this vrf coordinator is of type I vrf coordinator v2+ and if I command click on this I get Pro into the interface and if for some reason you can't command click or control click same thing we can kind of go scroll up see that this is that location interfaces vrf coordinator v2+ so we'll open up the lib again we can see there's interfaces I VF coordinator v2+ is here we can scroll down and we can look for request random words and we can see it only takes one variable it's this type it's this struct type it's this one single parameter vrf V2 plus client dot random words request call data wreck so we've learned a little bit about strs already but now obviously we're getting into more kind of advanced strs here if this is a little bit confusing to you right now don't worry about it just kind of blindly follow along it'll make more sense later on right so if the strs don't make perfect sense the worry basically we have to pass some this struct this kind of object to our request random words right and we can actually see if we go into our this vrf V2 plus client we can look in that contract for this random words request struct I'm going to command click you can also you know go to the lib look for this specific contract but basically we need to pass it this struct which has these parameters and that's it so we're going to need to populate this random words request with whatever is in here and if we go back to our raffle we can actually start thinking about what each one of these is so in this call we're going to be calling this external contract we're going to be calling this coordinator contract with request random words and we're going to be passing this giant struct object as a parameter and so I know there's this is kind of confusing here but uh well first we need to do a u into 256 requested equals this and I know this is red let me just uh copy this actually and comment this I'm going to make this a little bit easier to understand paste this up here we're basically going to create this struct here put a little semicolon here we're going to say vrf V2 plus client. request random words request equals this and then we're going to pass this request object into here right so doing these two things is essentially the same but this kind of like might make it a little bit easier to understand so now this is a way right here vrf V2 plus client. random wordss request is a way to work with this struct and again if this is a little bit confusing don't worry just roll with me here um but we get this little red underscore because our contract is saying hey what the heck is vrf V2 plus client uh all I see is vrf consumer base v2+ so what we need to do is we need to actually import that vrf V2 plus client contract and once again if we go up into our contracts here we can see this is actually located or even cheat if you hit command P or control P or depending you know or basically just open your command pallet you can actually type this in and see that this is in chanle browny contracts contracts SRC v08 vrf Dev libraries and it has this struct in here but we're going to go ahead and import this from at chainlink SLC contracts srcv 0.8 again this might be in a different place depending on when you watch this slvrf sdev SL libraries slvrf V2 plus client. soul and now that we've imported this if we scroll down oh some of those red squigglies are gone because now our solidity goes vrf V2 plus client. random word request ah okay I know what vrf V2 plus client is I know that it has this struct random words request you're trying to create a struct with all these arguments in it got it makes sense so this is some tax here on how to basically make a struct so you do like the name of the contract the name of the struct a little parentheses here and then these little bracket people and we're going to populate uh all the values in here so there's a number of different values in here and if we go to the chain link docs there's a little section which kind of defines what each one of these variables are going to do so we're going to give this a little bit of read to figure out which each one of these do so the first thing in here is this little key has thing so according to the documentation the key has is going to be the gas Lane keyh value which is the maximum gas price you're willing to pay for a request in way if it functions as an ID of the offchain vrf job that runs in response to requests so each chain link vrf has a specific gas Lane right if you're going to spend a lot a lot a lot of gas on the Callback you need to tell the chain link VF node that UPF front this won't make a ton of sense right now now but that's okay for for now just know that okay we need to have some type of keyh variable no problem let's make it modular let's go ahead and we'll put that up in our Constructor and maybe we'll call our byes 32 Gas Lane and you know this is the key has so I think that's a little bit more descriptive but then we'll do a bytes 32 private sore keash actually excuse me Let's do iore keyh let's do immutable like this and let's kind of put it up with the other immutable variables then in here we'll say I keyh equals that gas line so and since we're using i keyh instead of s keyh we're going to swap this out and okay great that red line has gone away okay what's next subscription ID okay the subscription ID that this contract uses for funding requests initialized in Constructor so whenever we work with the chain link view of subscription every single node is going to get its own subscription ID like I said if this is a little bit confusing right now don't worry too much about it right now it'll make sense soon but what we're basically going to do go back up to the Constructor and we're going to go ahead and add a new uint 256 subscription ID like so and we're going to add a new uh immutable variable u56 private immutable iore subcription ID like this we're going to say I subscription ID equals subscription ID like this and then we're going to scroll back down paste that over like that okay great what's next request confirmations where is that request confirmations this is going to be how many confirmations The Chain Lake node should wait before responding so basically after you send a request it'll wait X number of blocks before trying to give you the random number we are actually going to make this a constant variable so you're going to get rid of this here we're going to make this a constant variable we're going to say and this is going to be a ENT 16 private constant and for constant variables we like to do request confirmations and we're going to default to three here for constant variables we kind of like this style here where it's cap locks with underscores so request confirmations so we're going to scroll down boom request confirmations is going to be request confirmations the Callback gas limit this is going to be the limit for how much gas to use for the Callback request in your contracts fulfill random words function so when the chain leag node responds it's going to call that it's going to call a fulfill random words function which we have not defined yet the key hash or the gas Lane is going to be the price you're willing to pay and the gas limit is going to be the max amount of gas you're willing to spend so this is the gas price this is the gas limit I know it's a little bit confusing but like I said it's okay if you don't fully understand this uh we're going to go ahead and add this as another variable as well we're going to say this is a ENT 32 private immutable iore callback gas limit oops sorry this doesn't go here this goes up here mutable callback gas limit and then we're going to say U int32 call back gas limit paste this in here equals call back gas limit and you can see that my codebase actually autof formatted here if yours didn't and you want to get it to format you can just run Forge format like that and that'll automatically format your code as well so now that we have the call back gas limit we can copy that paste that in here next is number of words this is the number of random numbers that we want we are pretty much just always going to want one so we're going to do a uint this this is a un 32 we're going to say private constant num words equals 1 if you wanted more random numbers you could set this to being more but we only care about one and we're going to get this squiggly line saying hey this needs to be Memory so we're going to have this be memory and then if we uncomment this this should now compile fine Forge build and we did compile and we're just saying hey we haven't used request ID but a awesome so this is how we're actually going to populate our chain link V request let me zoom out just a hair here so we're going to call this contract that we don't really fully understand yet and that's okay with request random words and we're passing this request struct which looks like this it has a kyash which stands for some gas Lane for some gas price to work with the chain link node a subscription ID and this is going to be how we actually fund the Oracle gas for working with chain Ley VF request confirmations how many blocks we should wait for the chain link node to actually give us our random number the call back gas limit so that we don't accidentally spend too much gas on the Callback how many random numbers that we want and then extra args so this is where we can set some extra arguments depending on the chain link vrf version there is actually a version the chain link VF where you don't have to pay in link token where you can pay in Native eth or native blockchain token whatever you want to do we've set it to false for now but if you want to learn more about how to work with Native eth you can go ahead and check this out and if you're like who pay with link what are you talking about don't worry we'll get to that too now you'll saw a little bit before I added this fulfill random words and I set it to override and I didn't really explain why um so let me explain why the reason we needed to add this is because because when we imported when we inherited this vrf consumer based v2+ this was an abstract contract and in here there was this function fulfill random words internal virtual whenever you inherit an abstract contract abstract contracts can have both undefined functions and defined functions and so the reason chain link set this up as an abstract contract is they said hey if you're going to go ahead and import this contract you need to Define this fulfill random words and it's this function that our chain link node our chain link VF node is going to call back to to do stuff right so when we hit at the moment when we hit pick winner this is going to kick off this request it's going to give us this request ID chain link node is going to generate the random number and then the chain link node will respond by giving us this random number back to us because they're going to call this fulfill random words function and we need to Define hey chain link node when you give us back the random number we're going to do some stuff and now I had to add this keyword override here because in the abstract contract it was marked as virtual meaning it's meant to be overridden meaning it's meant to be updated meaning it's meant to be implemented in our contract and so we're basically overriding the functionality of it in here which in this abstract contract there is no functionality right it's just it's not a there's nothing in here so we need to actually Define what the chain link node is going to do when it returns us the random number so if we go back to our remix example here and I scroll down a little bit you can actually see they have a lot of these hardcoded in here like a lot of the same things we worked with the key has call back gas limit request confirmations number words blah blah Etc if we scroll down we can see they call this roll dice function which does something similar to what we did but then additionally they have this fulfill random words function with a whole bunch of comments in here where they basically do some stuff once they get that random number right so you can see the parameters here are going to be the request ID and this is going to be the same request ID that was generated when the request was generated and then it's going to have a u 256 array of random words and I know this is It's call data if the call data versus memory thing is a little bit confusing for you now don't worry too too much about it but basically it's going to give us this array of random words and since we're only asking for one we're just going to get one random number and we're going to tell our raffle what to do with this random word which is going to be what it's going to be pick a winner and I implemented it here already just so that our code would compile but again the reason that this is added to this abstract contract is to remind you hey you need to implement this now you might be kind of astutely asking hey Patrick uh if that's an internal call how is this function being called I thought if it's internal it another contract can't call this contract well you'd be right if we go back to this vrf consumer base v2+ right and remember we are inheriting this in our raffle and we scroll down we can actually see there is a raw fill random words which is external now this raw fill random words has basically just one check in it it says if message. sender does not equal address SF coordinator then revert otherwise call fulfill random words so the chain link vrf the chain link node is actually going to call Raw fulfill random words and then raw fulfill random words is going to call fulfill random words and fulfill random words is going to be what we Define so we're going to get the random number back and we're going to say hey once we get the random number here's what you need to do we're going to Define it in this fulfill random words function and of course we're going to say pick the random winner and give them the money so I know I've talked a lot so far so let me just do a quick recap of all the different things that we just learned okay so first of all when we want to pick a random winner what we're going to do is we're going to have to make a request to the chain link VF contract and we're going to make that request by calling the vrf coordinator contract and calling request random words we get access to this s vrf coordinator variable because we're inheriting vrf consumer base v2+ and it has this svf coordinator State variable inside of it and since we're inheriting it boom we get access to these State variables too this I vrf coordinator v2+ contract has this function request random words right this is an interface of course so there's some contract in the world out there that has this request random words function defined and it actually kicks off telling a chain link note hey uh I need a random number please could you please give me a random number since we're inheriting this vrf consumer base V2 plus oh my gosh I'm going to get sick of saying that and this vrf consumer based V2 plus contract has a construction we need to add this contract's Constructor to our contract the way that we do that is we just paste it next to our Constructor and add whatever variables need to go inside of it inside of this pasted Constructor inside our Constructor now to make this to make this request we actually have to add all of our parameters inside of this struct object this vrf v2+ client. random wordss request since we're inheriting vrf V2 plus client and this vrf V2 client has this random words request struct we can actually get this exact same type by doing vrf V2 plus client. random wordss request we can say memory request equals vrf V2 plus client. random words request and we can populate what's inside of this by doing these little squiggly brackets and we can say okay the keyh of this struct will be our iore keash the sub ID will be our iore description ID request confirmations call back blah blah blah etc etc then we're going to call request random words with this request struct being pass to it and we're going to get back a request ID and once we send this request the chain link node is going to wait some number of block confirmations and then it's going to generate the random number and then it's going to call back to fulfill random words and that's how we're going to get the random number back but it's not going to call fulfill random words directly it's actually going to call raw fulfill random words which is inside of our vrf V2 consumer base plus it's going to call this raw fulfill random words and that's going to call fulfill random words and since our raffle contract is inheriting this contract it's going to get all of that functionality it's not super important you memorize what any of these do and if you forget that's totally fine you can go back to the documentation to check it out but it is important you do kind of understand some of these other things like work with Constructors of inherited codebases overriding functions from inherited codebases and getting structs with this kind of methodology here you can see that this vrf V2 consumer base client is actually a library and that's how we can get a struct from a library by doing that syntax so so we're going to send a request with this function and then we're going to process the response with this function let's learn how to do that now so now that we have this list of random numbers or we just have our random numbers we want to pick a random winner from this s players array so what we're going to do is something called a modulo function to use that random number to actually pick one of the people in our array so let's talk about the mod function here in remix I've got this contract called example moduo with two functions get mod 10 and get mod 2 this module function is going to basically do a divide operation it's going to divide our number by 10 but instead of returning our number divided by 10 it's going to return the remainder so if we think of it like this we think of 10 / 10 this divides evenly so the remainder is zero there's zero groups or zero numbers on counted for but if we did 10 mod 9 let's think of this even differently 10 / 9 = 1 point something right some fraction so basically nine of the 10 are divided evenly but there's one left over so 10 mod 9 would equal 1 or even easier take two mod 2 we'll get zero because two and two divide evenly but two two mod 3 would equal two even though I wrote here one just sorry 2 3 equal 2 not not one so our modu function is going to be it's going to get the remainder after dividing so we can even do some examples of mod 10 and this is going to be in the GitHub repo associated with this course if I have 1 2 3 I get the mod we have three left over because 120 divides evenly into 10 and then we have three 123 we have three left over so if I do this major huge number what do you think our remainder is going to be yep it's two because this number divides evenly into 10 and then we have two left over so if we do mod 2 what do you think this is going to be it's an even number so it's going to be zero if I do this what do you think it's going to be it's going to be one right so this is this modulo function and we're going to use it to pick a random winner out of Ouray so how are we going to do use this module operator or I said function but it's really the operator to get our random winner well let's say that there were 10 players so sore players would be 10 people l right so be 10 different people and let's say our RNG we got back was 12 or I should say our random number keep saying RNG but it's really our random number was 12 well what we could do is if we did 12 modulo 10 we would get uh two back we would get two back and then we would say whoever is at index two in our players array is going to be the random winner right this is going to be our winner now in reality the random word that we're going to get back or the random number we're going to get back is going to look something like this it's going to be this horribly long monstrosity of a number we would do is we would take this huge monstrosity we would modul it by 10 and for this one for example you know if our s players was 10 we would get what's the left over here it's going to equal to n soever is at index 9 is going to be the winner so this is how we can always get a number between zero and nine remember in arrays it starts index a zero to get our random winner so what we're going to do then is we're going to say U 256 you 256 index of winner equals random words at index zero right because random words right because random words is only going to be an array of size one because that's the numb words that we've set we're going to say modulo it by sore players. length so the length of the players array or mod if you will so this is how we're going to pick the index the winner cool so then once we get that we're going to say address payable recent winner equals sore players index of winner like this Tada and now this winner what are we going to do well for me I like to keep track of this most recent winner just so that we can have ADV very easily readable who's the most recent winner and so maybe up at the top I'll make a new variable I'll do address address private sore recent winner like this I'll come back down here and we'll say s recent winner equals recent winner like this and then we're going to want to pay them right so we've learned some of the better paying methodologies so we're going to do a little parentheses bull success comma equals recent winner. call Value is going to be address this. balance with this right here so we're just going to give the recent winner the entire balance of the contract right and it's going to have a balance this contract will have a balance because because even to enter the raffle they have to give some type of entrance fee right so this raffle will have an entrance fee it will have money so all the ticket sales are going to go to this winner blank bytes for the object and then we're going to make sure this transfer went through successfully so we're going to say if not success then we're going to go ahead and revert so this little exclamation mark here this stands for bang AKA not so anytime you see this it means like if not success and we're going to revert with some custom error so we're going to go up to our custom errors that we have we're going to create a new custom error we're just going to say error raffle uncore transfer failed like this copy this scroll back down paste it in if this transfer fails for any reason we're going to go ahead and revert right here all right great so there's a couple of things that we probably want to keep in mind though when we make this request when we pick the winner and will we use this request ID and a little bit so if it's if this squiggly line is bothering you don't worry about it quite yet but if we're in the middle of picking a winner right remember we have to wait a certain number of blocks to get that response back so what we're probably going to want to do though is say hey if we're in the middle of calculating the winner we should restrict people to not be allowed to enter so we should only allow people to enter if we're currently not picking the winner right so what we can do is we can actually keep track of the Lottery's current state by giving it a new type with something called an enum so what we could do to keep track of the raffle and figure out okay are we in the middle of calculating the winner is we could you know we could scroll to the top we could do like you know bull sore calculating winner and then just like set this to false and then down here once we start picking the winner we could set it to true but as we create more sophisticated typing and having more interesting requirements just a bu isn't going to be enough so we want to learn actually how to create new types using enum maybe instead for example you know we had some like instead of like bull you know uh calculating Lottery we had like Lottery State and then this could be like open close C paying blah blah blah many different states a Boolean would no longer be good enough and I don't want to have to have a different variable for each one of these things so what can we do so what we can do is we can create a single variable of a new type that we come up with called an enu and if we scroll up to the top with this layout of a contract here we can actually see you know we have version Imports errors interface libraries contracts we have type de type declarations even before our state variables so an enom is a kind of type declaration that we're going to put up near the top of our contract so let me even label this we'll call this state variables ebles like this and we're going to add add type declarations right here and this is where we're going to create this new enum and in this L docs we have this section called enom types enums can be used to create custom types with a finite set of constant values they are explicitly convertible to and from all integer types but implicit conversion is not allowed so we can see here's an example contract and there's this enom action choices go left go right go straight sit still and so once we create this enum they get this new action choices typ typing that they can use throughout their contract for us we're going to create an enom called raffle State and this is just going to be open or calculating and that's it these are going to be the two options for our raffle state to be in it's either open or it's calculating either it's open or it's calculating the winner because somebody called that pick winner function and you should not be able to enter the raffle in solidity each one of these states in our new type actually be converted to integers so open is going to be integer zero calculating is going to be integer one if we had like another state that would be integer 2 and so on and so forth but now that we have this raffle State type in our state variables we can create a new storage variable we can say raffle State kind of the same as what we've done above here right what's where we do like type visibility name and then you know constant if constant so we'll do type visibility name sore raffle State what we can do is we can default this to being open so in our Constructor we'll say s raffle State equals raffle state. openen and this is actually the same as if we did raffle State and then cast zero right because raffle state. openen is equivalent to zero here but we'll do raffle state. openen so our code is more readable and then actually I'm going to move this down here as well so all the immutables are here storage ones are here and then now that we have this in our ENT raffle function we can do a little if sore raffle state does not equal raffle state. openen then we should not be able to enter so we'll do revert with a new custom error of raffle uncore uncore raffle not open like so and I need to go ahead and Define this up here in my custom errors so we'll do error raffle not open like this so you can only enter the raffle if the raffle is open now down in our pick winner after we do our little check here and we'll still have to give this a a custom error in a little bit but we can do a little update we can basically now say Okay sore raffle State equals raffle state. calculating like this so now once somebody kicks off the chain link vrf request we will now be in a calculating state and since this is calculating people will not be able to enter the raffle anymore but then when we get the actual winner we're going to want to flip the state back to open so after we get the winner down here we're going to say s winner equals recent winner and then right below that we're going to say oops say sore raffle State equals raffle state. openen cool now our fulfill random words function is still not done right there's still some more things that we need to do right now our fulfill random words it's like oh cool like cool we have a winner but the Raffles the S players array is still populated with players right we still have a whole list of players so if more people enter the new raffle the old players were still able to keep their spots essentially so we need to actually reset this players array so we're actually doing a couple of State updates right we're saying s raffle state equals raffle state that open we're reopening the raffle we also need to update this players array to a brand new array right we need to empty out all the players so what we could do is we could go through the whole players array and like delete one element at a time in the array and that would be awful and it would take forever but a much better way to do this is we could just say Okay s players is now going to equal a new equal a new address payable array of size zero and this is going to basically just wipe out everything in that s players variable and just reset it to a brand new blank array and then additionally we want to update that under that sore last timestamp equals block. timestamp so that our interval can restart right so our clock can restart on on when somebody can actually call pick winner so we want to add that down here as well all right and so since we've learned about events now we've picked a winner and we've updated the state we can now emit a log so we can do a little Amit winner picked and we'll say the recent or we'll do the uh yeah we'll do the recent winner in here sore recent winner and we're going to take this event we're going to copy it scroll all the way back up to our events here we'll do a new event winner picked and we'll say address indexed winner like so but all right great so this is starting to shape up this is starting to look pretty good now I want to say something important as I'm building this now it looks like I'm just going from start to finish right and a big reason for that is I've already I've done this demo many times right I've written this code many times I've written a lot of solidity in my career however most of the time instead of me just writing a contract beginning to finish I don't do it in one go in fact it's incredibly difficult to do it in one go most of the time instead I'm actually writing a deploy script and then testing individual components of my contract as I build it out so at this point in my coding I probably would have wrote a test get entrance fee function I probably would have wrote a test pick winner function I might have wrote a test enter raffle function I'm writing tests as I'm coding this the reason that I'm not writing tests and not writing the deploy script right now is we're going to do a lot of refactoring as we go along here and the way I'm coding this is I'm coding it away to explain the different concepts of what we're doing piece by piece as opposed to coding it in a way that I would code a real project but I do think it's important for you to keep in mind that this doesn't actually look like what really coding this project looks like it's going to be you going back and forth you compiling code stuff not compiling you're going wait why why doesn't this compile you debugging stuff and that's okay and that's good so just wanted to give you that heads up now whenever you're coding functions there's going to be a concept that I want you to keep in mind and this is going to be called the Ci or the checks effects interactions pattern and this is going to be one of the most important patterns for you to keep in mind anytime you're coding solidity and you're coding smart contracts and the goal here is that you want to set your functions up where you do some checks at the beginning our fulfill random words doesn't really have any checks yet our fulfill random words doesn't have any checks but then you want to do effects which is going to be like your internal contract State changes right so this is going to be all our state variables that we're going to update in here and then we're going to do interactions interactions and this is going to be external external contract external contract interactions and I know kind of the E and the I is a little bit confusing here but yeah the way say I think of it is checks effects which is internal contract State and then interactions which is going to be external contract State much much much later in the course we will talk about security and re-entrancy and a lot of the and a lot of the trickiness of smart contract development but for now if you just keep checks effects interactions in mind that will help you just be safer by default and of course if you want to go super super deep into security we have our security and auditing course that you should definitely check out whether you want to be a top developer or security researcher it's really really important to have Security in mind whenever you're building smart contracts so your checks are going to be basically your like requires right requires or your conditionals conditionals and if we scroll up we can see we're actually doing that for pick winner right one what's the first thing that happens at pick winner okay well we have a check in pick winner we go to enter raffle we actually have two checks right at the top of enter raffle so the first thing you always want to do is is your checks the next thing is going to want to do your effects your internal contract State updates and then finally your external contract interactions now you'll see down here we actually emit this event technically this is internal to our contract right this doesn't interact with any external contract so we actually would want to bump this up up to here and adid our event before we do this interaction this external contract interaction and why do you want to start with the checks at the top well the biggest thing is it's more gas efficient right if we had let's actually scroll way up to the top here if we didn't send any message out value and this was going to revert but we did a whole bunch of work first and then we reverted later like that would really stink so it's much more gas efficient to revert early than to do a bunch of work and then revert later and then let me get rid of all this stuff here the biggest reason for this pattern this methodology is to defend against re-entrancy attacks which like I said we'll learn much later now there is some debate about events and a lot of people will tell you that putting it after an external contract interaction is fine and that's kind of the default but I'm going to tell you that it's not fine and you should practice better best practices and do it before you admit your events because there is a scenario where an external contract interaction does change a storage variable of yours and therefore the events that you're emitting are wrong and and we don't want that biggest takeaway is just remember this design pattern checks effects interactions all right great so our code is starting to shape up here right we haven't tested it yet but it looks like we're looking pretty good right we have a way to pick a random number right we're getting a random number hooray we are also using that random number to pick a random player and give them the money okay cool great like we're doing that as well uh-oh oh we're not doing this automatically we're not automatically calling this hm we want to work very hard to be very lazy I would love to figure out how we can automatically have this called well guess what there is a way for us to do this so what we can do is we can use chain link automation to automatically kick off calling this pick winner function so that we never have to rely on some good Samaritan calling this pick winner function and our Lottery will just run programmatically without us ever having to interact with it so to get started with chain link automation we can actually go to the docs once again and we can scroll up to the top let's go click here let's go look for Automation and same as normal we can actually see all the different code in here for working with chain L automation if we scroll down we can see getting started with automation uh if you want you can go through the documentation deploy this to sepolia etc etc for us if we're working with automation we're can look on the side here there's some different concepts there's some different guides there's going to be time based versus custom logic versus log trigger we are going to be using kind of a derivative of time base but we're going to be using custom logic stored on chain because custom logic is kind of the ultimate way to do this anyways where it allows you to do literally anything you can customize your smart contract to be called at any time and there's going to be a video that we're going to watch pretty soon that's going to show you how to set up a lot of this code through the UI there's a website that you can actually go to to help get you a lot of this setup but like I said we're actually going to write a whole bunch of scripts so that we can do a lot of this programmatically so that we can have a very professional setup with working with these tools and if we go to these guides like create automation compatible contracts we can scroll down in here and same as normal we'll get hit with this chunk of code that we can go ahead and select open in remix which will open up in remix and we'll get this big Chun of code that we can use kind of as a baseline for working with chain link automation so we can really learn what's going on here and if you want to try this out yourself by following along with the documentation trying this out in remix I highly recommend you do so so let's go ahead and let's go back over to Richard who will go over chain link automation as well and show you how to work with chain link automation now kind of same as with chain link VF the version we're going to be use is going to be slightly different but all the high Lev concepts are still going to be the same and it's still good to go over this as well now just the heads up chain link automation was previously known as chain link Keepers so you might hear that terminology used a a little bit as well so just if you hear chain link Keepers just know that that is chain link automation hi I'm Richard one of the developer Advocates of chain link labs and today we're going to take a look at an update to [Music] Keepers now maybe you're like me and you know on a regular Tuesday you're just browsing the chain link documentation and you come across these chain link keeper release notes you say whoa what's changed what's new let's dive into that and see what's new with Keepers if you head on over to the documentation and look at the keepers release notes you can dig in and see what exactly is new with Keepers but I want to jump right in and head on over to Keepers do chain. link when we head there we'll be prompted to connect our wallet so let's go ahead and do that first and then we'll take a look at what's new with Keepers so here everything looks mostly the same but when we register a new upkeep we're presented with this new Option trigger this is amazing in my opinion because one of the most common use cases that I use are time-based trigger mechanisms and that used to mean dealing with block hashes and trying to figure out how to do all that within a contra ra using check upkeep with those block hashes to see if enough time had passed on a blockchain in order to trigger that upkeep now you can do that right here through this UI I'm going to head back to the documentation and we'll take a look at creating a time-based automation now this will walk you through all the different steps that you need about connecting your wallet how to register and everything like that but let's look at creating a keeper compatible contract this is what we used to have to do every single time we used to have to create a check upkeep function and then we had to create a perform upkeep function right you remember that well you can still do that if you need some sort of more complex logic behind what's going to trigger an upkeep if it's not just time based you can still use those two functions but we want to that time based function how can we make a contract and do that let's take this sample contract and we'll modify it and go from there so we have our sample contract if we click open in remix we'll get it popped open in remix and remix is an online IDE for developing solidity smart contracts we've got our contract here and we'll know that this one is based upon the way that we used to always use keepers by creating a keeper compatible contract with check upkeep and perform upkeep both as functions available within the contract now we don't need those anymore this is a good example I think for showing this change because this contract it checks upkeep based upon the block time stamp the last time that we did something in an interval so when we deploy this contract we set the interval that's what the Constructor does the constructors run every time you deploy a contract and in this case we pass in an interval to the Constructor based upon that interval you then will check the block time stamp and the last time that we actually performed upkeep and compare them to see if enough seconds have pass in order to need upkeep again this is a perfect use case for that time based upkeep so how do we go about doing this I think probably the best way to start is by creating a new function to to count right that's what this contract is doing it's taking a counter starting at zero and then it's increasing it at a regular interval so let's do that let's create a new function and we'll call it count and it won't need to take anything in because we're just going to be increasing that counter and so we'll just say counter equals counter + 1 now what type of function does this need to be we can let anybody run this so we'll say external and that should be it right we have this function count it's an external function and we don't need check upkeep anymore for this use case we don't even need perform upkeep we can get rid of both of these our contract just got a whole lot simpler right so anytime that we want to increase our counter we just call count fantastic let's go ahead here and see what we have as far as compiling we have a warning it's saying that it should not be a keeper compatible interface anymore that's true we don't need that as well we don't need last Tim stamp and we don't need interval we'll set those in the keeper interface so we can get rid of them as well suddenly this contract just became really really simp simple so we create a Constructor and let's clean it up all all the way we have our Constructor it's going to set the counter equal to zero it's a public variable that we can see and then we have a function to increase that counter that's it that's all that the other version of this contract was doing using check upkeep and perform upkeep this one much simpler and if you're using a use case like this where you just need to perform an action based upon time passing this is all you need so we're good here we've got our green check mark that means it compiled correctly we'll need to deploy this so let's do an injected provider I'm going to be deploying it to the Fuji Avalanche test Network just picked one and we have my account we need to make sure we deploy the counter contract let's go ahead and do that we'll approve this transaction we should see it pop up here we've got another green check mark that means we're good to go we have two values here we have counter it'll tell us that we've counted zero times and we have count this will actually increment the counter so let's do that go a and make sure everything's working before we head over to Keepers cool awesome we have counted one time now let's head over to Keepers and what will we need over there so we're going to be using time based triggering for this contract now we'll need to give it the address of our contract and this is going to give us a couple of interesting options here so if we had verified this contract on the network that we're working on it will populate the values of the functions that it can call we haven't verified this contract are we out of luck we're not we can get the ABI the application binary interface it essentially gives Keepers and other applications interacting with your contract the information about hey what does this contract do how do I interact with it if we head back to ethereum we can see under the compilation tab here under the compiler we have an ABI now make sure that you pick the correct contract this contract is counter so we'll need to make sure we select that and then we'll click on copy for the ABI head back to the keepers window over here paste it in and click next at this point it should give you all of the functions that you can call now our contract is pretty simple it has one function it's called count so we'll use that function right we've told it what function we want to call now we need to tell it how often do we want to call this function when it comes to automating Smart contracts on the blockchain we're going to have to wait for blocks to be verified right and blocks to be mined on that blockchain that can affect how quickly we can do things I'm going to run this every minute the Fuji test network is pretty fast some other networks it takes a little bit longer for those block confirmations to come in that's just something to keep in mind the syntax here is the same as Kon if you're not familiar with KRON there's a basic breakdown of it over here it has five different values it's got minutes hours days of the month the month and then day of the week now you can get really fancy with KRON schedules and there are some tools out there that are fantastic if you're not familiar with KRON head on over to KRON tab. Guru and you can kind of get an idea of what is happening they have an example in here we'll just talk through it real quick so the minutes is five the hours is four the rest are stars stars mean means always so this says at 4:05 every day every day of the month every month of the year every day of the week right you can get some pretty interesting things going on so this one would run at midnight 5 minutes past it on the F like every day in August only in August so every day and every day of the week in August the 8th month at 14:15 on the 1st of the month this is a great place to kind of get a easy human readable output from cron tabs so let's head back here we want to run this and I'm going to say every one minutes and this is what I mean by interesting things we can divide up every minute divided by one so that's going to say every 1 minute right if we had just one then it would only run on the first minute of the hour so 1 minute past the hour but we want every 1 minute we'll click next and this is very similar to what the keepers used to look like right so we'll say uh count every now let's do something more fun make every minute count we'll give it a gas limit 15 150,000 should be plenty we'll pop in some link link do you need link if you don't have link you can get it from the faucet right here we've got a link to the link faucet right there we do ask for your email address that's to email you in case your keeper starts to run out of Link or there's a problem with and you can give it a project name if you need to we'll click register upkeep we'll need to approve this on the blockchain we'll wait for that approval process we'll need to approve one more time to actually request the upkeep as well so this will transfer the link from our wallet to the keeper subscription that we've got going on here uh and it will set up our upkeep and then we can view that upkeep so if we take a look here we can see the history we can see hey we set up our upkeep and we funded it we have when it's going to run based upon our KRON expression uh we've got all that information we also have the ability to say Hey you know I don't want to run this every minute that's way too often maybe every hour we can go in here we could edit the upkeep change things we can add more link if we need to we can edit that gas limits that will be important too if you have a function that costs more gas than your gas limit your upkeep won't run just a few things to keep in mind but you can see here we've performed our upkeep already so if we head back to remix go back to our contract right last time we ran counter once and then we had one on our counter if we check now we can see our counters too and again in just a minute we'll be able to see that our counter has increased again so just like that we've taken our contract and we've automated it using Keepers timebase triggers to create that decentralized automation of our smart contract I think that's really cool this use case I'm stoked about it because I do this a lot where I want to just have something trigger on a regular interval a regular Cadence and having the ability to do that is awesome and it simplifies the contracts down so much right look at this thing it's tiny when you compare that to this my goodness it's so much easier to understand so much cleaner because our use case is so simple so thanks for watching another tutorial and for checking out the new Keepers version 1.2 I'm Richard and I'll catch you in the next [Music] one all right now that we know a little bit more about chain link automation we can actually use chain link automation which like we said used to be called chain link Keepers to actually automatically kick off our lottery so that we don't ever have to call any f functions and the lottery will just run to do this we're going to need these two main functions and they're going to be called check upkeep and perform upkeep and Richard went over them briefly in the last video essentially what the nodes will do is they will periodically call this check upkeep function they will call it as a view function right they won't actually send a transaction they'll just keep checking to see if it's time to actually perform an upkeep AKA start the lottery so they will keep calling this check upkeep this is where we will Define the custom logic and then we will implement this perform upkeep which they will call to actually kick off the lottery start the lottery which picks the random number Etc so so our checkup keep is basically going to say hey is the lottery done is it time to pick the winner and then perform upkeep is going to say okay let's actually pick the winner so right now in our code base we have this pick winner function which we're kind of assuming that somebody is programmatically calling but we're going to actually revamp this function so that it works with chain link automation so that nobody ever has to actually call this function so we're kind of going to split this function up into a checkup keep and a perform up keep so what we can do is right below our enter raffle function is we can actually create that first new function so we'll do function check upkeep keep I think it's lowercase check upkeep yep like this and this needs to take a byes call data like this so whenever you see syntax like this bytes call data and then the actual variable commented out like this this means that it's not being used anywhere in the function if we want to use check data we can go ahead and implement it like this for now we're going to ignore check data but check data is a way to further customize your chain link automation if you want the chain link nodes to pass some specific information in order to check if it's time to actually do the update so this check upkeep function they have it in the docs as external View override we are going to have RSB a public view override because we're actually going to use this checkup keep someplace else and I'll show you where in a minute they're actually using override as well because in their example in here they're actually importing this automation compatible interface and implementing it this is a good best practice to do so that you always implement the functions needed for something like chain link automation however we're going to actually ignore it and just not use the override key here since like I said this is just an interface and I just don't want to add it to make it a little bit easier make our code base a little bit smaller and this function is going to return two things so it's going to return a Boolean called upkeep needed and a bytes memory perform data so I'm actually going to just copy this whole line paste it into my vs code here and then it's saved and it auto reform for me which is nice so the bull upkeep needed is going to be true or false simply hey is it time to restart the lottery is it time to pick the winner and then byes memory perform data this can be some type of return information about what to do with this upkeep as you can see here in the example it's also wrapped in these common brackets here so we're going to ignore it similar to how the docs ignore it because we're not actually going to use this perform data in any way so for us this checkup keep we really only need to worry about this Boolean hey when is it time to pick the winner right this checkup keep who's going to be answering that question when should the winner be picked and have this upkeep need to be true whenever the winner should be picked so we can actually write this answer as a bit of natat speec here and uh my vs code autocom completed a little bit for me which is really nice and what we can do is say at Dev this is the function that the chain link nodes will call to see if the lottery is ready to have a winner picked the following should be true should be true in order for upkeep needed needed to be true one the time interval has passed between raffle runs right so that interval is up to date number two the lottery is open number three the contract has eth and then number four implicitly implicitly your subscription has link like this and the prams are going to be uh null here ignored and then we can just kind of delete this bit here just say like null or ignored it's going to return upkeep needed true if it's time to restart the Lottery and then I'm going to say ignored now what's kind of cool about our returns here is that this is actually a way to initialize variables right in the return section right so just by doing bull upkeep needed this upkeep needed variable is now initialize and we can use it in our function right it automatically starts off as false if we just had like return bull like this in our function we would need to say like bull upkeep needed you know equals true or whatever but since we have it defined in our return function boom We automatically get this upkeep needed and it defaults to false and doing it like this it'll automatically return whatever is in this bull upkeep needed right so we could have done like bull hello equals true return hello well we have to return hello and then also you know perform data be like blank but what we can do instead is just do this and we can say upkeep needed equals true and boom it'll automatically return upkeep needed is true because whenever this function ends it's going to return the variables defined in here since we actually defined them there so little bit of cool solidity syntactic sugar so if we said upkeep needed was true it would return upkeep needed was true if we said upkeep needed was false it would return upkeep needed is false so now that we actually have this we can actually start to implement this here and what we can do is we can first say okay what's the first one the time interval has passed between raffle runs we can actually copy this paste it here because this is the conditional and let's do a little bit of refactoring here let's say this is bull time has passed equals like this and then block a Tim stamp minus s last time stamp this should be no greater than or equal to because this is going to be time has passed this was kind of time has not passed so we're going to say time has passed okay the next one the lottery is open so we can say bull is open equals sore raffle State equals equals raffle state. open this is kind of the equivalent of saying s raffle State equals equals zero so if it's indeed open this will return true otherwise this will be false okay next the contract has eth this is basically checking to see if the contract has players right if people have entered the raffle so we could say bull has balance equals address this this balance is greater than zero and you know what we should probably check for players as well like bull has players equals sore players do sore players. length is greater than zero and then we can say upkeep needed is just whatever the combination of all of these are right so if this and this and this and this are all true then check upkeep should return true so we'll say upkeep needed equals time has passed double Amper sand is open double Amper sand has Balan double Amper sand has players so this double Amper sand is basically saying and so we're saying if this is true and this is true and this is true and this is true this whole thing should return true if any one of these is false this will be false so now it would just automatically return upkeep needed and then blank 4 bytes of memory however we however it's still best to be very explicit I don't love just kind of leaving it like this so we can do return upkeep needed and then we can kind of do any like ox Oxo for hex you maybe we even type the hex word here oh we could even do this syntax here hex and then just like a blank string we could even just do like a blank string there's lots of different ways to basically return null here so all right great so now we have a function to actually check if it's time for for this Lottery to automatically be called and updated and so now what we can do is we can convert our pick winner function into this perform upkeep function right this is going to be the function that says hey uh it's time to kick off a vrf call we need a random number please so the chain leag nodes are basically going to continuously call this function they're going to call it over and over and over and over and over again and whenever this returns true it's going to return true and they're going to go oh my gosh it's time to pick a new random winner let's call perform upkeep which is what we're going to refactor our pick winner function to be so first we're going to have to refactor our perform upkeep excuse me we're going to have to refactor our pick winner function to perform upkeep so we'll paste it like this we don't need the override keyword here and boom and already most of our performal keep is looking good it already has most of what we want here we're not going to pass any perform data in here kind of like what we were saying before cuz we're not returning any perform data from checkup keep now since this is an external function that means anybody can call this and we want to just have this function have some validation in here so we want to make sure that the chain link nodes or really anybody can only call this when it's time to call this so what we can do is we can say if and we can actually get rid of this if or excuse me not if we can do bull upkeep needed comma and I'll explain this in a second equals check upkeep with a blank input so we're going to get the output of us calling check upkeep and this is why we made this public and we get this R squiggly line here and I'll explain that in just a second but then we can just say if the upkeep is not needed so bang upkeep needed then we're going to revert with some type of custom error here now if we keep the code as such we're going to get this error here invalid type for argument in function call invalid implicit conversion from Little string to call data requested so this is a little bit lower level and this is okay if you don't really remember this quite yet but in our check upkeep function we've specified this as a bytes call data check data now whenever you use some type of variable inside of a function it can never be call data and the reason for that is because technically anything generated from a smart contract is never call data call data could only be generated from a user's transaction input that's probably a little bit confusing for now but that's okay for now if you see something like this just Swap this over to memory save and that will go away so having this Beall data just makes this function a little bit more gas efficient having this be Memory makes it a little bit less gas efficient however it's more permissive like I said you don't really need to worry about the lowle differences there quite yet now when we're doing these reverts here just if you send a transaction and you just get some revert it might be very un clear to you as a user of this protocol or a developer why this actually reverted right and that's you know that's why we do these custom errors up here however what we could do is we could just for our revert here we could say revert you know come with a new custom eror raffle uncore uncore upkeep not needed but you might say ah the upkeep's not needed but I I don't understand why so what we can do is we can actually add parameters in our custom errors to give more information in Reverse as to why this actually errored so we could add an address this. balance so maybe we could check to see maybe there isn't a balance we could say s players. length maybe there are no players in here you went 256 sore raffle State like so so if it's open right if we go back up to the raffle state if it's open it would be zero calcul would be one and then in our definitions here we could say error raffle upkeep not needed U 256 balance uent 256 players length and then U into 256 raffle State now when we revert here raffle upkeep not needed we'll have more information as to why we actually reverted here we could also do raffle State raffle state or u56 raffle State because like I said each one of these parameters inside of raffle State get mapped to a un 256 anyways so but we're just going to do a un 256 sore raffle state to make it a little bit easier to understand in the actual revert all right great all right great so now we have a way for the chain link automation or the chain link Keepers to automatically kick off our raffle to kick off our vrf request it's the chain link nodes that are actually going to call the chain link vrf for us and let's just make this a little bit nicer let's get rid of the warning here so we'll just get rid of that and then we'll also come this out here just for now we'll probably add it back in later but we'll just make it a little bit easier for now okay great and cool stuff's looking pretty good let's just do a little compile here so we'll do a little Forge build or make build and cool compiler run successful awesome all right great so we've written a lot of code and we've learned a lot of things so let's do a quick midsection recap here of what we've kind of learned what we've gone over so we're using this layout guide that we just kind of copy pasted at the top of our codebase here to guide us into where to actually put our functions our raffle is inheriting this VF consumer base v2+ and this vrf V consumer base 2 plus if I command click or control click or open the command pallet and go to this contract it has this s vrf coordinator variable inside of it because it has this sore VF coordinator inside of it it gives us access to this sore vrf coordinator and that's actually what we're using it's that contract that we're inheriting in our raffle contract to actually call this request random words using this request struct that we built ourselves from the library right we're using a key has subscription ID request confirmations call back num words some extra arguments and this is how we're actually calling the chain link VF to get a random number and then the chainlink node will respond to our fulfill random words and we will use the random number it gives us to pick a random winner now because we want to be incredibly lazy here we are actually going to basically hand off calling this Lottery and restarting this Lottery to the chain link automation so we have a check upkeep function which the chain link nodes will consistently call to make sure it's time to call the lottery and then we will have a perform upkeep function which is what they're going to do to actually pick the random winner the chain link automation is going to call perform upkeep which will call the chain link vrf the chain link VF will then call fulfill random work and that's how we're going to get our random winner here to actually get into the raffle we have this enter raffle function here which we have a couple of checks right at the top which makes sure that they're actually sending an entrance fee and that the raffle is currently open they will get added to an array and we will emit an event there and in order for us to work with this vrf consumer based V2 plus we have to pass the vrf consumer base v2+ in its Constructor by just kind of adding it to our Constructor like this VF consu V2 plus has its own Constructor and whenever you're working with a codebase that has its own Constructor you need to also use that Constructor in your code as well and boom actually just like that we've pretty much written most of the code to have a provably fair automated smart contract Lottery let's go all right great so we've actually written some really good code here so now we want to make sure that this code actually works it actually does what we want it to do and we're going to write some tests and you'll probably hear me say this more and more but it's really important we get really good at testing and devops and writing scripts with our smart contracts because smart contracts are a little bit different than other software if you screw up one of your smart contracts you could potentially lose a lot of money right away so we want to make sure we get really comfortable writing tests because often times writing really robust really strong tests is actually the majority of your work as a smart contract developer or a security research anyways so now we're actually going to go ahead and go into writing these tests and we're going to approach writing these tests by following this path here so first we're going to write some deploy scripts in order to use directly in our tests so that we can test the exact same way we're going to deploy these smart contracts and note that deploy scripts as of recording do not work on ZK sync so if you want to actually test these on ZK sync on running like a local ZK sync chain what you would need to do is you would actually need to write some bash scripts to deploy your smart contracts to a ZK sync chain deploy your mocks there and then run your test Suite on your local ZK sync chain as if it was some type of forked testnet so the deploy scripts that we're going to write here they're not going to work for ZK sync however that's how you would do it and this is just as of recording there are plans for them to actually add this functionality in so in the future your deploy scripts will work exactly the same on ZK sync as they work on any other chain but we still want to write these anyway so that we can get a good understanding that our codebase is actually doing what we wanted to do so this is the approach that we're going to take let's go ahead and let's dive in and all right let's go ahead and let's get Kraken let's open up our codebase here and let's go over to script we'll create a new file called deploy raffle dos. soul and you already know the drill we do a little pragma my vs code already kind of populates this for me let's make this MIT 0.8.9 we'll call this contract deploy raffle is script like this and we'll say import script from forg sd/ script. like that all right cool let's do a little sanity Forge build or Forge compile and Yep looks good here okay great and what we're going to need to do in here of course is we're going to need to create a little function run function like we did with our Foundry fundme and if we pull back up our fundme scripts here we're going to do something similar to what we did before right so we're going to have this run function this is what's actually going to get called when we call run we're going to have this deploy fundme script that we're actually going to use in our test and this is going to be how we work with this so I'm actually going to create another function called function deploy raffle and I know this a little confusing the contract name is deploy raffle and then we're also going to have the function name deploy raffle if this is too confusing we can call this like deploy contract uh actually you know yeah let's do that so that it's a little bit less confusing here and kind of exactly as we did with our fundme bit we're going to have this deploy function return it's going to be external or you know let's just make it public returns it's going to return our raffle contract and a helper config right so that we can use it directly in our tests which we haven't defined these yet but you know that we definitely will so let's grab that raffle first least so we're going to say import import raffle from s c/ raffle doou and what's interesting is that there's actually a couple different ways to do Imports so you can do import contract from and then kind of this direct path right where the root directory where we just say SRC raffle doou we can also do a relative path where we do like dot do/ SRC raffle doou both of these work so raffle doou is located in relation to the script down a directory and then SRC raffle doou or we could just say SRC raffle Doo and you'll kind of understand the distinction there a little bit later but for now either way it's going to work fine so let's go ahead how do we actually deploy our raffle well let's go to the codebase it takes an entrance fee interval coordinator gas Lan subscription ID call back gas limit now as you know a lot of these are going to depend on the chain that we actually deploy to at least the vrf coordinator the address of that contract is going to be different if we deploy to arbitrum ethereum main net py uh ZK sync whenever it's added to ZK sync so we're going to have to make a helper config with each one of these parameters so before we can even finish this I'm actually going to go ahead and even comment this out before we can even finish this let's go ahead and create a new helper config s.o and this is where we're going to add a lot of that helper config information so let's go ahead let's add a pragma make this MIT 0.8.9 contract helper config is script like this say import import script from forg STD script. saw like so all right cool in here we're going to create our struct called Network config and what do we need to put in here well let's go back to our raffle okay we're probably going to need all of these in here so what we're going to do is we're going to say U 256 u in 256 what else do we have entrance Fe interval coordinator gas Lane entrance fee interval U into 256 interval address vrf coordinator gas line subscription ID call back limit bytes 32 Gas Lane uint 32 call back gas limit uint 256 subscription idid oh and these should all be semicolons not commas okay great now we're going to need a couple other things in here in a little bit but for now let's just assume that this is correct now I'm planning on deploying this to seoa you can optionally deploy this to sooo you do not have to because like we said you know takes actual test s tokens and those can be a little bit hard to acquire but I'm going to set this up as if I'm going to deploy to seoa and this way we'll also set it up to work with a local chain so what I'm going to do I'm going to create a couple of functions in here kind of very similar to what we did with funme let's first create create a little Network config public local network config or network configs or whatever you want to call it and then we'll say mapping un 256 56 chain ID to network config public netork figs like this and same as what we did before let's do Constructor sorry I'm kind of I know I'm kind of going a little bit quick here let's create that SEO function here so we'll do function get aoia eth config this will be a public pure which is going to returns a network config memory and we'll say turn Network config well brackets like this and then we'll say entrance fee is going to be what let's entrance fee let's say it's just 0.01 ether or this kind of equal to to doing 1 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 right or this is also like 1 e16 those are all the same so 0.01 ether then say interval we'll give it an interval let's say let's call this every 30 seconds so this is going to be right this going to be 30 seconds just so that we can kind of test it really quickly F coordinator vrf coordinator this is where we actually have to go back to the chain link docs for chain link VF so let's go back to RF let's go in here to erf 2.5 supported networks scroll down ethereum Main net suppo a test net you have coordinator boom let's grab this address here paste that there next is going to be the gas Lane which also is in the documentation 100 G keyh let's do that one boom we'll paste that next the call back gas limit so call back gas limit for us we can just hardcode it to 500,000 gas so that's going to be 500,000 gas that should be plenty of gas for us and then what do we need then we need the subscription ID subscription ID which for us for now we'll just leave ours as zero and you'll figure out why we're going to do something kind of cool here where our scripts will automatically create a subscription ID for us if we don't already have one but what we can do is if we default to this we can now say okay uh network configs of the uh sapoia chain ID uh is going to be so theoa chain ID is 111 5511 equals get sapoia eth config like this okay cool now as we kind of talked about before I hate having magic numbers like this without any label in here so we're going to actually scroll up to the top here we're going to create an abstract contract just called code constants and this is where we're just going to add a whole bunch of constant variables in here and one of them is going to be un 256 public constant sepolia chain ID which is going to be equal to 111 5511 like this and now we can say helper config is uh code constants doesn't really matter this order and script so what we can do now is we can say Network configs ESO Chan ID equals get EO chain ID okay and then almost done here we'll do another we'll do a little function get config by Chain ID we'll do U into 256 chain ID public returns Network config memory and we'll say if network configs of chain ID dot we could say vrf coordinator so if the vrf coordinator is not empty so it does not equal address zero then we're just going to return the network configs of that chain ID however if it is empty oh networks network network config however if it is empty we'll say else if chain ID equals the local chain ID which we're going to Define so we'll create this local chain ID un 256 public constant local chain ID equal 31337 however if it's the local chain ID what are we going to do this is where we're going to get or create Anvil eth config which we haven't set up yet and then finally else we're actually just going to revert with an error that we're going to create for helper config helper config uncore invalid chain ID so this needs to be error H fig and valid chain ID revert like this so this is looking pretty similar to what we did with fundme oh this seems to be double equal here so this is look pretty similar setup I know it's a little boring but um public view well it's not going to be view um so this is pretty similar to what we did before I know it's a little bit monotonous but all good so let's also create this get or create Anvil e so down here function get config this will be a public function this will definitely not be pure because this is where we might have to deploy some mocks public returns Network config config memory and okay cool and then in here we're just going to say we're going to check to see if we s and Active network config see make sure we actually didn't set any extra mocks so we'll say if local network config vrf vrf core donator does not equal address zero then just return the local network config like this and if we haven't set it already we should deploy some mocks so let's go over deploying some of these mocks now and then I can actually uncomment this too put a little semicolon here this will actually be return get or create anal eth config and Okay cool so if we've already set it up we'll just return it um but if we haven't we should set it up right so this is where if we're working with Anvil we should deploy mocks and such all right so the question then is okay Patrick how do we deploy our mocks right if we're working on a local chain we want to test this so that we want to test this with a mock vrf coordinator contract that we know everything's working correctly so how do we actually get one of these mocks well we could 100% create a mock contract oursel but that would kind of stink that might be a lot of work well guess what luckily for us if we go into our lib folder chain Leake brownie contracts contracts SRC v08 vrf where is vrf vrf down to MOX right here in here this there is this vrf coordinator Vore 2 v25 mack. soul and this is what we're actually going to be using so we already have a mock vrf 2.5 and this has all the stuff in it that we need so what we can do we can go ahead and import it so import VF cordinator vp25 mock from at chainlink SL contracts slsrc v0.8 slvrf MOX slvrf coordinator v25 mack. soul and Tada and now we have this in here this is what we can use to deploy a mock vrf coordinator right locally and this is what we can do to very easily work with kind of a mock a fake chain link vrf and so now what we can do so we can actually deploy it so what we can do is we can scroll down we can now go a little vm. start broadcast because we actually want this to deploy to our Anvil and then a little vm. stop broadcast afterwards and we can say vrf coordinator v25 mock V vrf coordinator mock equals new vrf coordinator v25 mock vrf coordinator v25 Mock and let's go see what this actually takes in its construction so it takes a base fee a gas price and a way per unit link so let's talk about these different parameters here so the base fee whenever you work with chain link brf you need to pay a certain amount of chain link a certain amount of Link token the base fee is going to be the flat amount of chain link token that you're always going to have to pay so whenever the chain link node is actually going to be the one calling this contract right because when the chain link vrf is going to call back the chain link VF is going to be the the one to actually spend gas to call this fill random words it has to actually spend gas so we have a little bit of a calculation here of okay how much link per eth are we going to use and then we also have this way per unit of Link which is going to be the link to eth price in way and basically all these are just calculations for the chain link vrf node to actually calculate okay how much it should charge you right if it has to spend a ton of gas and the price of eth is super super high for some reason it's going to charge you more if it doesn't have to spend a lot of gas and the price of eth compared to link is pretty low well it will charge you less so and since this is a and since this is a mock contract we can just kind of mock these values right so up back in our helper config we're actually going to put these up in the code constants and so I'm actually going to make a little area here called vrf mock values so we're going to say uent 96 public mock base fee and we're going to say 0.25 ether like this we'll do a uent 96 public mock gas price link equals 1 E9 and these are just some default values that will probably make sense and then for the linke price we'll just say int 256 public mock way per muu int link equals and then we'll just go go with you know 4 E15 these values don't really matter for our test but you can kind of tweak them if you want to make sure your outputs or something that makes sense so now that we have that we can actually finally go to the bottom and deploy this mock contract so it's first going to take the mock base fee then it's going to take the mock gas price link gas price link then it's going to take the mock way per uint link next okay like this okay cool and now that we have this vrf coordinator mock can we actually get this local network config so if we scroll to the top we have our local network config we could say local oops uh local network config equals Network config let's see if we can populate this so the entrance fee entrance fee we'll just say is 0.01 ether still then we need I'm then I'm actually just going to copy paste this and update these as we see fit interval 30 seconds that's fine vrf coordinator haha okay this is going to now be the address of the vrf coordinator mock that we just deployed the gas Lane this doesn't matter it could be pretty much anything so this one doesn't matter because our mock is just going to have it work no matter what call back gas limit also doesn't matter and subscription ID we might have to fix this but I'll show you how to fix this in a little bit so okay cool and then we just can return this return local network config and boom now we have at least a basic minimal get or create Anvil eth config that we can now pass into our get configs by Chain ID bit here and this is looking pretty good nice and the reason stuff like this is becoming so important is because like I've been saying we live in a multi-chain world it's pretty much highly unlikely you're ever going to deploy a contract to the ethereum main net you're probably going to start off deploying it to a layer 2 or an L2 and there's a good chance that you actually will deploy your smart contracts to multiple different chains so you want to have a robust setup a robust devops or developer operations process that can handle kind of these different chains these different l2s because like I've been saying like we've been seeing these different chains have slight differences and they are slightly tweaked and we want to make sure that we test them appropriately no matter which chain that we're going to be working on all right cool so now that we have our helper config up and just to heads up we might need to do a little bit of refactoring on some of this we can go back to this and actually get this to work here and then pop it into one of our tests so let's go ahead and import that helper config from script slh helper config dos. Soul now we have those both working and in here we can do a little helper config equals config helper config config equals new helper config then we could say helper config helper config do Network config memory or I guess I should call this helper config config so this is the helper config contract and this is the network config so we'll call this config equals helper config doget config so actually I don't think we implemented that so we have get config by Chain ID let's add one more helper function just to make it a little bit easier function get config this will say this will be public returns returns Network config memory and then we'll just return this get config by Chain ID of block. chain ID so when we call get config if we're on a local network we will call get or create Anvil eth config which will then deploy our mocks so kind of these helper functions are just to make our scripts look a little bit nicer so we'll call helper config do config now that that function exists and if we're on a local network so if we are local we're going to deploy MOX get local config and then if we're on something like seoa we will just straight up get the suppo config get pull the config like so so now that we have our config here we can start deploying our raffle we'll do vm. start broadcast like this and little vm. stop broadcast like this and in here we'll say raffle raffle equals new raffle and let's go back to our raffle what do we need in here go to the Constructor Constructor entrance fee interval coordinator gas line subscription call back so we can kind of cheat a little bit here and we can get all of these values from the config right because get config is going to return our Network config which has all of these in it so what we can say then is we can say our config do entrance fee entrance fee we can say config do interval we can say config vrf cord nator config dot what's next gas lane or keyh or whatever you want to call it uh subscription ID config do subscription ID and then finally fig. callback gas limit nice and then the last bit that we need is we just need to return the raffle and the helper config so at the bottom we'll just do return raffle that new raffle contract and that helper config that we just deployed as well and now we can use this in our test okay nice now if you want to be a little bit lazy stuff like this subscription ID you can just go ahead to the UI you can copy paste it into here but like I said we're Engineers we want our processes to be very robust so we're actually going to later on we're going to do some refactoring of this to make this automatically get a subscription ID make sure everything's set up correctly but for now let's just roll with this and we'll see that when we actually go into the test here the test will actually start to break down and that will be the cue to US ah we need to go back and refactor some of our deploy scripts so it's good that we're starting here this is the simplest example but cool so in our test folder let's go ahead we'll create two new folders we'll create one called unit for our unit test and we'll create another one for integration for our integration test and here we'll create a new file we'll call it raffle test T.O or really whatever you want to call it and you already know the drill let's get this pragma snippet going M 08.19 contract raffle test let me zoom in a little bit here raffle test is test like this we're going to import test from Forge STD test. like this then of course we're going to import that deploy raffle from SRC slash excuse me script SL or scripts script script Das deploy raffle dos. so like this we're going to import the raffle contract itself from SRC raffle doso like that and for this one we could do dot dot SL dot dot slash like this to get a relative import right because R.T doou is here so if we go back One Directory we're in unit if we go back a second directory we're in test excuse me because we're St in unit if we go back One Directory we're in test and if we go back another directory we're kind of in the root directory here and then we can go SRC raffle dool so we can do either this relative path or uh this path like this here so either way works so let's go ahead and let's create some of these tests in here so we're going to do function setup because we obviously want to be able to set this up here external or public so we're going to go ahead and do deploy raffle deployer equals new deploy raffle like this and then we're going to get the raffle and the helper config by calling deploy contract or whatever you called it let's create those as state variables here so we'll say raffle public raffle and then we'll do helper config public helper config config oops and we're going to need to import that too import helper config from script slh helper config dos. Sol like this cool and so we're going to do deployer do deploy contract like this and it's going to return those two values so we would just want to save them directly to raffle and helper config so since deploy contract returns a raffle and a helper config we just automatically save it to our raffle variable and our config variable by putting it in the syntax here and then we should probably make some users to interact with our raffle so we'll create like a test user address public player equals make a DDR player like this this will create a this make a DDR this make Adder is a Foundry cheat code which will allow us to just kind of make addresses based off of some string and we'll probably going to want to give them a starting balance so they can actually interact with the lottery interact with the raffle so we'll say you went 256 you went 256 public constant starting player balance equals we'll say like 10 ether we'll give them a ton of money now a quick note here is that in my test files I'm a little bit more laxed with some different conventions like for example like this layout this layout of the contract here I'm really going to be pretty strict about this inside like the contracts that I actually want to deploy I'm going to be a little bit less strict with them in my test it's still good to follow those conventions but but for testing you don't really have to follow it as strictly and then just to make my life a little bit easier in our helper config we have all these variables and I don't really want to have to do config do entrance fee config interval config vrf blah blah blah so I'm actually just going to copy all of these paste it right underneath my helper config like this so we're going to initialize all these variables and then right underneath the deployer contract I'm going to say entrance I'm going to say helper config do Network config memory config equals helper config doget config like this kind of same as what we did before and then just set these with like entrance fee equals config do entrance fee and then we'll say interval equals config do interval we'll say brf coordinator dinator equals config do VF coordinator gas Lane equals config gas Lane call back gas limit equals config do callback gas limit and then subscription ID of course is going to equal config do subscription ID like so so this is all looking pretty good but let's do a quick test a quick sanity test just to make sure that things are looking good right so in our raffle do so we can do a simple test to make sure it at least starts in the correct state right so we should start as open right the lottery should start as open so what we can do is we can in here in our test we can say let me zoom out a little bit function test raffle initializes in open State like this and it could be a public view like so and all we need to do is we just want to assert that that starting raffle state is open so if we go back to the raffle dool how do we get this raffle state is there a way uh looks like we actually don't have a getter function for this so let's go ahead and scroll to the bottom create a little quick getter function we'll call function get raffle State this will be external view it'll returns a raffle state which remember we can kind of identify as a u 256 as well we can typ cast it as a u 256 but we can just say return sore raffle State like this and then in our test then we can simply just go assert raffle do getet raffle State equals this is where we can do some pretty cool syntax here to get this enum to get this type here we can say equals raffle State excuse me we can say raffle do raffle state. openen so this is how we're going to get that open enum right here right and this could be the same as just doing like U into 256 like typ casting this raffle State as a un 256 and then just saying this is going to be zero right this would be one way we could write this test but however doing it like this is going to make it much more readable so this is the preferred way for us to do this and now we can go ahead and do a little sanity test here so now we can pull up our terminal do a quick little Forge build just make sure it builds great and now we can do a Forge test and we only have one test so that's the test that goes right here and it looks like it passes awesome now this is an optional section here I want to show you a tool that I use a lot there is this tool out here by transmission 11 called headers and it's built in Rust and I haven't taught you guys how to work with rust or how to do anything with rust but essentially if you install this tool and you type headers and then some text it'll print out a perfect solidity header for you that it will automatically cop copy to the clipboard so I already have this installed so if I do something like so let's say I want to do uh the enter raffle test next if I do headers enter raffle like this it'll spit this out automatically copy to my clipboard so I can paste it in here automatically now I'm not going to show you how to install this because it's with cargo it's with rust and you haven't learned anything about rust yet but if you want to pause the video and you want to go ahead and install this so that you can use it to make these beautiful headers kind of automatically or automatically if you will uh feel free to do so give this repo a star uh I use it all the time to make these really really nice looking headers in my code so if you want to do that go for it otherwise let's start writing a ton of really awesome tests so now let's go ahead and start writing some tests here if we go to our raffle we really probably want to start with our enter raffle function and one of the first things we should look at is this this little bit here if the message. value isn't enough it should revert so we should test that it actually reverts if people don't pay the entrance fee so we'll say a little bit of a function test raffle reverts when you don't pay enough make this public and we're going to follow and we're going to follow the arrange act assert you don't have to type this out uh you don't type have to type this out every single time but I feel like if you do it can kind of really give you a better feel of the layout of all your tests so in here we're going to do a little bit of a vm. prank we're going to start with that player and we're going to try to enter this raffle without sending any money and remember we learned about expect revert if you want to go back to The Foundry book you can go check out the expect revert in here but what we're going to do is a little bit of a vm. exect revert like this but we can even be more precise than this we don't want to just say hey we're going to revert we want to say we are expect to revert with a very specific code that way we know what we're actually reverting with right maybe we we're reverting but it's because of something unrelated to what we want right and we should do this so if we go back to our raffle doou we see that the revert error that we should get is raffle under raffle uncore send more to enter raffle right if we reverted with something like this we would know uhoh like our something's wrong with our logic we're reverting but like for the wrong reason so we want to make sure we're actually reverting with this now kind of similar to how we got the enum the raffle State up here we can actually get that error right so we did what raffle raffle state. openen we can also do raffle Dot and then I'm going to I'm going to copy this this error send more e to raffle dot paste that in here and then we do do selector now I know we've mentioned selectors before and I know we're kind of using it here for now just ignore it just assume that this worked we will teach you about this selector key and what function selectors are a little bit later in the curriculum and actually excuse me this is act SL assert CU down here we we can just do raffle do enter raffle like this so now we're saying okay we're going to pretend to be the player we're going to expect a revert and then this VM prank only gets applied to this line because this is another cheat code so the player is going to enter the raffle without sending any money and this should revert we can test this out by writing Forge test-- Mt in a previous version I did a lot of- M Foundry updated and so now it's --mt and it is this test that we want run so paste that in here to just run that single test and boom it passes awesome okay cool well what else do we want to test okay well we want to test that the raffle actually updates right the raffle actually adds to this players array when somebody enters raffle right it would be really bad if this raffle didn't record that people are entering the raffle so we'll do a little function test raffle records players when they enter public click and we'll do a little arrange act assert so for arrange we will say vm. prank we'll prank the player again we'll pretend to be the player once more for the ACT here we actually do want to enter the raffle correctly and how do we actually enter the raffle correctly well let's go check here we need to actually send the entrance fee uh we do know it's open because we've already tested that so what we can do is we'll do a little raffle do enter raffle with a value of what we want to send that entrance fee and guess what we have that saved up at the top here so value is going to be the entrance fee and we don't have any parameters for enter raffle so right this just be blank and then we want to make sure the address player recorded equals raffle dot uh do we have a way to actually get the players in this array well where's this players array uh s players do we have way to get the players in here no we don't have a way to get the players in here so since we actually don't have a way to get the players we want to add a function at the bottom to get the players so we'll say function get players or get player un 256 index of player external view returns address return sore players index of player like this and we can use this there are some pretty clever ways you can actually get storage or get State variable values without having to do this however we don't want to really use those super clever things because we probably want to have a way to get players in the array anyways so so that's almost like a good reminder to add these these view functions as we're testing so uh equals equals player we want to make sure that that's the player who got added in here now if we actually run this you'll notice that this will fail right so if we do grab this address or grab this test we'll do Forge test d-mt paste it in this will actually fail and I'll tell you why it'll fail in a second H so this is kind of exciting so can you tell without actually debugging this why this actually failed go ahead and take a look try to figure it out go ahead and pause the video if you want cuz I'm going to run it again and now I'm going to add add- vvv V or however many V's you want to add and this will give us kind of this output now and we get this evm air out of fund H oh my goodness player doesn't have any money of course not we forgot to give them money so they're trying to enter the raffle with the centrance fee and they are broke so we'll go ahead and give this player some money we'll scroll up into our setup and we'll do another cheat code here called vm. deal and we'll say we're going to deal the player that's starting player balance so we said hey we're going to start them off as being super rich and then we didn't give them a starting player balance so vm. deal it says we're going to pay player 10 ether and so they will automatically just get 10 ether for all of these tests now if we go and clear this out we rerun that test it should pass because they now have money and Tada we do now see it's passing all right great now testing events in Foundry is a little bit funky but we also have this cheat code that we can use called expect AIT and it's a little bit funky and you'll see why and you can see here this function takes a bunch of bulls check topic check topic check topic and then check data here and then we also have expect a Min adders a m so there are a couple different ways that we can do this this is the function that we're going to use right there's a couple different of these but if we scroll down we can kind of see an example of how this works let me scroll down here so down here in The Foundry documentation we have this test erc20 emits transfer and what it does is it does vm. expect emit true true false true address my token and then it actually emits an event so the syntax here is a little bit odd but in order to do expect a mint in Foundry we have to call vm. expect Min we say which topics it's going to Emit and we have to say true if it has the topics that are going to be emitted so topics are going to be your indexed events here so right remember you can only have three index events so if you had three of them like address index player address index or index something else address index something else if we had three in here we would have this be true true true and this third Boolean is for any uh additional data right anything that's not an indexed event and then the address of the thing that should emit the events so it's a little odd but the more indexed events you have the more TRS you had right if we had no indexed events and we just had this address player here it would would be false false false true just for data if we had nothing in here at all it would just be false false false false and then the address aditt the event you'll see what I mean as we go through this uh I know it's a little bit confusing right now but we do this expect admit and then we admit the actual event we are expecting that it emits and then if this exact event is emitted in the next call it will return true other F otherwise false so let's go ahead and add this to the test and then we'll show two examples here right so we're going to do the same thing here here we're going to do vm. prank we're going to act here we're going to do vm. expect emit we're going to say true false false false address raffle and we're saying true false false true false false false because if we go back to the raffle the event that we're going to emit here raffle entered address indexed player this player here is an index parameter and it's the first index parameter so we're going to say true there's no additional index parameters and there's also no non-indexed parameters so we're going to say false to the rest we're going to say it's the raffle that's actually going to be emitting this and then what we can do is we want to actually emit that exact event here now what's kind of annoying is we actually have to copy paste our events into the top of our test here and that's just kind of the only way it works so we have to copy paste it we'll do to emit raffle entered player player like this and this is us telling Foundry hey we're expecting to emit an event this is exactly the event that we're expecting to emit here and then we'll actually do the call so we'll do raffle do enter raffle and then they need to send some value so value is going to be entrance fee like this and now if we run this do Forge test d-mt paste that in we'll see that this does indeed pass now for example if I were to change this to like address Z the event that we emitted here is going to be different than the event that gets emitted here so if we try to run this with Forge test-- Mt paste that in-1 2 3 Let's do four of these and we run this now you'll see we got a little error here we'll say reason log does not equal expected log we can see kind of in here that when we called expect emit like this uh we ended up emitting this raffle entered with player this address here and then when we called enter raffle the player address was different so it failed right and then obviously it failed because we admitted our own wrong custom player awesome so events aren't types like enes or structs so we actually have to do this I'm hoping in the future we can actually just import them kind of same as we did with the strs right like down here we did like raffle raffle state. openen we can't do raffle do you know with the parameters in here for some reason uh I'm expecting that to change in the future and voila let's keep going and okay you know what let's actually let's write a test for this after all so let's go ahead let's do one more test here we'll do function test don't allow players to enter while raffle is is calculating public like this and then we'll do arrange act assert like so so for our range we're going to do vm. prank player we want to test that this error is going to trigger and what we can do to make sure this is calculating is we can go ahead and we will actually call perform upkeep right because perform upkeep actually sets this to calculating so we will have to kind of update the time make sure some players have entered blah blah blah so that this check here will at least pass and then we'll call perform raffle excuse me perform upkeep which will set this to calculating and then while this is calculating they shouldn't be able to enter in the raffle right because we have this check here so we want to make sure that happens so first we can go through this list of things we need to check to uh make sure that this perform upkeep will pass cuz right cuz right now we have if upkeep not needed needed it's going to revert so we need to make sure we can have upkeep needed so uh we need to have some players and it needs to have a balance so the first thing we can do is we'll do raffle do enter raffle we'll do value of entrance fee Okay cool so that means that we're going to have a balance we're going to have some players raffle state will start as open and now we're going to need to make sure some time has passed okay uh how do we do that do we just like wait do we just like sit here and like wait do we just like go to bed do we like just take a break go to the gym and then come back and hopefully enough time has passed that this will be updated well this is where we can actually use some more Foundry cheat codes and in particular we can use vm. warp and vm. roll so if we go back to The Foundry book we can look up vm. warp or or vm. roll we can look up vm. warp in here and we can see that this cheat code called warp will set the block. time so this is how we can automatically change the block. timestamp to whatever we want it to be so that's what we're going to first do so we want to make sure that enough time has passed so the block. time stamp minus the last time stamp it's greater than or equal to the interval well what do we set the interval into our hper config here interval is going to be 30 seconds we're going to need to move our locally running blockchain right whenever we run a test Suite we kind of get a fake blockchain running in the background we're going to need to move its block time a bit so what we can do is we can say vm. warp block. timestamp so the current timestamp plus that interval plus one so that it's guaranteed to be one later than how long it needs to be so this is going to be the current block plus 30 seconds plus 1 second boom we should now be past that interval past that deadline for this to work and then I also like to do this kind of as a best practice you don't always have to do this but I like to do this uh we're going to do this vm. roll so roll is another cheat code that you can use in Foundry and this will change the block. number I like to always roll it by the current block. number + one and the reason for this is this will really simulate okay the time has changed and then also it's there's one new block has been added so I like to do both of these to make sure this actually U makes sense so now that we've entered the raffle the time has passed the block has actually incr Ed I can now do raffle do perform upkeep and pass in nothing and hopefully this should pass and if this does pass right it'll call perform upkeep it'll kick off a chain link vrf request here and since this is just our mock like we can kind of ignore everything that happens in here but what will happen is it will set the raffle state to calculating so then now if we try to enter the raffle it should revert right so we can go back we can do another one of those vm. exect reverts we can scroll up okay this is the syntax let me just grab this copy that we'll paste it down here so we'll do vmex revert and this is actually act SL assert here so vm. exect revert raffle do oh it's not going to be send more eth it's going to be what what's the error going to be uh it's going to be raffle not open here if they try to enter so it's going to be raffle not open do selector same there we'll do vm. print rank make sure that we are the player and then we'll do raffle do enter raffle value is going to be the entrance fee like so cool so let's try to give this a WHL Forge test d-mt paste it in and H and we get this error invalid consumer oh no what's what's this that's that's not we expected we expected to get raffled not open and this is why it's important to actually put the correct error in here huh so we get that error well let's let's run this again but let's add a couple of- VV VVS on here and let's let's see what's going on here oh it looks like our perform upkeep is failing okay so let's dive into this why is this perform upkeep failing I'll tell you right now though these are correct so good job adding vm. warp and vm. roll so if we run this again like like we just did with the with the v's in here we see that perform upkeep fails for some reason with this invalid consumer and so in our test here it's actually this line that's bugging out so we need to fix something with perform upkeep why are we not able to call perform upkeep and here's where this is why we do this methodology that I showed you before this is why we do raffle uncore uncore and then the name of the aor this invalid consumer is actually an error that some contract is throwing now it's not immediately obvious what contract is throwing this air because it doesn't have the name of the contract before it right so so whoever wrote this code which reverted with this invalid consumer could have given us a much more helpful error code by actually having the prefix with the name of the contract before this so so like I've been telling you just by you taking this course you're actually better than a lot of the smart contract developers out there today we can see kind of in The Foundry debugger bit up here though we can see ah it's the vrf coordinator so perform upkeep is going to call our vrf coordinator marck which is going to call request random words and it looks like it's in here that we're going to get this inv valid consumer so we could do like a search just for this invalid consumer right we could look up like error invalid consumer we could hit these three dots we could say okay let's look in like the lib and we can see oh okay this error is kind of all over the place there's a whole lot of these but we can kind of tell just by looking at this piece of code right here that it's probably going to be this vrf coordinator V2 mock that is throwing this invalid consumer error so if we go in here and we look up this request function right because what what's the function we're calling in a raffle we're calling um request random words so let's look for this request random words we could actually kind of go through this and debug this code a little bit non-reentrant only valid consumer and we can just look up like revert invalid invalid consumer invalid consumer looks like there's this modifier only valid consumer and this is on the request R reward so this is probably where this is coming from right it's probably reverting here and for some reason we're getting this revert because our consumer is not added whatever that means and this is actually a little bit more information about working with chain link vrf so if you watched the videos with Richard you knew that at some point you actually had to create a subscription and then add a consumer so if you look at the build with vrf 2.5 in the document ation there's a section called create and manage subscriptions so you both have to create your own subscription to work with chain link VF but you also have to add a consumer and then you can do this programmatically or you can do this via the UI or the website that the chain link vrf codebase gives you and the reason that they have this is so that random people or random contracts can't use your subscription you should be the only one who uses your subscription I mean you're paying for it right so we actually need to update our deploy raffle script so that when we deploy our contract here we actually have a valid subscription and we have a valid consumer and we're correctly added to that consumer so that we don't get this weird invalid consumer error anymore so we're going to have to update our deployment process here and this is why it's so important that you do test your deployment process because this would be really annoying if you did this whole test and then you started trying running your lottery and it stopped working and you were like oh my gosh I forgot to add a consumer so we're going to update our script here so we can have this consumer so that everything will just work now we could 100% do this all via the UI we could deploy this to a test net and just manually have to remember to do stuff but that's not great we really want to reduce the amount of manual work we do as much as possible because the more manual steps we have the more we have a possibility of introducing a bug we want to make sure we get everything right so we don't introduce bugs doing that is very bad we want to work as I've said many times we want to work very hard to be very lazy and we want we also want to work very hard so that we can introduce as few bugs as possible so we're going to refactor our deploy raffle so that we add this valid consumer so that we can run this test programmatically and so that we can run this test and have this test work so there's a few things we need to do to refactor this but let's go ahead and start the refactor so in order for us to add a subscription right to add a consumer we can go to the vrf subscription manager create our own subscription and then we would there a giant button would pop up called add consumer and we would get our little subscription from doing that if I did have a active subscription kind of like what you see here we would get this add consumer button we would add a consumer and we paste it in here and boom we'd have a consumer however if we start off as blank we would need to first get a subscription right so like on the UI we would need to you know create subscription by pressing this button over here but we can also do this programmatically so that all our test can work automatically so in our helper config right let's go over to our our helper config we have this subscription ID set to zero so what we can do is we can set up our code to say hey if you see subscription ID of zero then you should programmatically create a new subscription and add a consumer automatically so our all of our tests can work so what we can do then is in our deploy script here before we actually start this broadcast here what we can do is we can say if config do subscript ID equals equal Z then then we should create subscription now we could go ahead and put all the code for creating ascription in here or what we could do is we could create that new interactions file and put it all in there and import them here that'll make our code a little bit more module and then if and then if in the future we want to programmatically create more subscriptions we can just do it right from the command line so I'm going to create a new file called interactions. s.o and we're going to create a new contract in here called create subscription so that we can programmatically create a subscription we're also going to add an add consumer piece in here so let's go ahead and get started let's do this MIT 0.819 contract create subscription is script like this that means we're going to have to import let me zoom in a little bit import script from 4 for STD script. Soul like oops like this now in our Foundry fundme when we created our you know contract fundme fund fundme which the naming there was amazing I know U we had to actually first get the most recently deployed contract and then we had to do some stuff with it and put everything in the run we're going to kind of follow the same process here except for we don't need to get the most recent deployment so we are going to create a function called run function run because when we do our scripting this is what needs to be called however once again we're going to modularize this with creating a new one called function create subscription and I'm going to go even one step further we're going to call this create subscription using config public returns U 256 U public like this and our run function all it's going to do is call create subscription using config now in order for us to actually create the subscription back in our helper config right we have this vrf coordinator address and this vrf coordinator or even the mock they both have a create subscription function if I go back to the UI I'll go ahead and connect here yeah let's go ahead and connect here if I go ahead and click create subscription you know there's a bunch of stuff that will show up I'll just go ahead and hit create subscription in here we can see on vrf chain. link I'm calling this address calling this create subscription function and I know we've done a little bit of work only a little bit of work with cast but I can actually check to make sure that's the function that I'm expecting I can do cast Sig create subscription make sure the hex is the same I get a 21 a23 E4 if I go back over here I see a 21 a 23 E4 aha I'm going to reject it for now but that is going to be the function that we're going to call we're going to call this create subscription function on the vrf coordinator we know that we're calling that create subscription function on the front end we can also call that programmatically in our deploy scripts or I guess more correctly in our interaction scripts now now let me let me pull this back up and and just copy this for a second often times you're actually not going to know what the hex that pops up here metamask stands for even or even does but there are these things called function signature or function selector databases out there and one of them is openchain doxyz XYZ Z where if you go to this website and we go to Signature database if you paste in a function selector and search it has a database of different hashes or hex data and the name of the function associated with it so you can actually see in openchain doxyz this hack is associated with create subscription now these databases only work if somebody actually updates them now Foundry has a really cool way to automatically push them and automatically update them here I'm not going to show you how to do that but if you want to explore some more via The Foundry docs I encourage you to do so and I know I'm not really explaining these function signatures and these function selectors right now but I promise you later on in the curriculum we will do so so exactly the same as how the vrf website was going to call this function we are going to call that function in our script here and to do that in our create subscription using config here we're first going to say okay helper config helper config equals new helper config like this and that means we need to import the helper config from script slh helper config dos. Soul like this and then we're going to need to get from this helper config we're going to need to get this vrf coordinator address so we're going to say helper config do get config and this is going to return the network config for the Active network right because if we go back to helper config we call get config where's get config where did I put it get config it automatically gets the config by Chain ID which does this chunk up here so we'll call get config and on this we could do vrf coordinator like so and this would actually instead of returning this whole config it would just return the vrf coordinator which is really all we want so we could say we do like address vrf coordinator equals hper config config address hper config config vrf coordinates and then what we could do is we could go ahead and create the subscription in here but I actually want to put it in its own function so that it's a little bit easier and more modular for later so I'm going to create another function called create subscription which is going to take an address VF cordinator as an input parameter it'll be a public and these will all return some stuff but uh I'll show you in a little bit so we're going to have this create subscription using config call create subscription with that vrf coordinator and that's going to call this down here and now I want this to do some console logging to kind of help me tell what's going on so we'll import this console and technically you should import console 2 that's the latest and greatest but we could just do console if we want and we could say console.log creating subscription on chain ID and then comma Block uh. Chain ID like this then we'll do a little vm. start broadcast oh thanks get up copilot then we'll say U 256 sub ID equals and if we go into the vrf coordinator V2 mock we could look for create subscription and we could find that it's actually not in here it's instead in this subscription API we can look for create subscription this is the function that it gives us and it's going to return the UN 256 sub ID so in our interaction here we're going to say un 256 sub ID equals we need to grab that import vrf coordinator v25 mock from at chain link actually let's just go back to the helper config where is that I'm going to just copy paste this in here boom very nice chain L contracts SRC v08 vrf MOX V coordinator vrf coordinator v25 mock that's all now subid equals the vrf coordinator v25 mck at address vrf coordinator dot create subscription like this and then bm. stop broad broadcast like this and now we actually do have a sub ID so just running this chunk of code would be equivalent to going to the website and pressing create subscription all right great so then we can do a little console.log your subscription ion ID is and then do comma sub ID like this console.log please update the subscription ID in your helper config dos. Soul because we're going to want to use this sub ID in our test we're going to have this a u 256 and we're also going to want to have it return the address of this coordinator mock as well so we're going to have it return and address too so then we'll just say return subid VF coordinator like this and then I'm going to copy this line paste it up here copy this paste it up here we'll have our create subscription using config also return both of these and this will need to be uh this will be un 256 sub ID comma blank we'll just leave it blank for now we're just going to get the sub ID equals create subscription boom and that looks pretty good to me cool and just for a sanity check we'll do a little Forge build okay nice so now that we have all this create subscription scripts all this automation here we can now take this create subscription contract in our interactions. s.o come back to our deploy raffle we'll import it we'll say import create subscription from script SL interactions . s.o like this and we'll say create subscription create subscription and I know this might be a little bit confusing so we could call it like create um uh we call it like uh subcription contract or or whatever you want to call it I'm just going to call mine create subscription create subscription equals new create subscription just going to copy paste that and then what we can do is we can call in our interactions we can call the crate subscription function using the vrf coordinator and the reason I kind of modularize this like this is so that we could either we could pass in our own VF coordinator or we could just use whatever the default in the config is so so that we're extra explicit I want to use the exact same address that is going to be used in this test here so I'm going to say create subscription do create or what's the name of the function do create subscription I know that's definitely confusing create subscription. create subscription with config vrf coordinator so we're going to use the exact same address that's that we're using for our test suite and for our deployment here and this will go ahead and create a subscription like this okay nice and of course we're going to want to get the subscription from this so we'll do a little callon equals and we could set it we'll say the config subscription or config do subscription ID comma config do vrf coordinator equals this so now we're actually saving so this returns right a un 256 and an address the sub ID and the vrf coordinator so we're now saving our new subscription ID to our config here so we're now saving it like this we're also saving the vrf coordinator and now we will have the config do subscription ID not be zero it'll be whatever the new subscription ID is now we do have to do another step which is actually going to be called fund subscription because we also need to add a consumer but I do just want to show you kind of what the full flow looks like so if I'm on the vf. chain. link I'm on sepolia new so this is basically a new create subscription place I can go ahead and hit create subscription my metamask is going to pop up I can go ahead and check I'm calling create subscription on this vrf coordinator address on seoa I'm going to go ahead and confirm because I have some suppo you do not have to follow along with me here and in fact I recommend that you don't because you're going to have to wait a long time for transactions to go through at some point we're going to update all of our curriculum here with something called virtual test Nets so that nobody ever has to deal with getting fake faucet funds anymore so now that we've actually created a subscription we also want to just sign this to basically sign in and we now have a subscription created if you go ahead and select add funds I'm actually going to select I'll do this later uh I'm going to do I'll do this later for Consumer as well you can see in here that when I'm connected I can actually scroll down and I can see that I have a new subscription here on ethereum sapoia and here's the subscription ID that I was just created so this subscription ID that it gives me here in my subscription piece is going to be the same as as well it's going to be the same as if I like we said if we just called create subscription from our scripting and gave us a subscription ID here so then in order to use the subscription I would need to actually fund this with link so if I go to my wallet let me just check to make sure I have some Link in here I do have some test net link but if you don't you can go to faucets. chain. link and you can pretty much always get some test net link here let's go ahead and connect wallet I'm going to go get some test net link I could also look for eth with some add additional verification but let's go ahead verify I'm human let me get some test net link this will give me 25 test net link on seoa and then I'm going to have to wait a little bit and like I said you do not have to do this with me because you're going to have to wait a whole bunch of transactions but it's good to kind of see what the UI looks like so that when we go to script it out it'll make sense kind of what this looks like if it was on the website and awesome we have the tokens transferred now in the next lesson we're going to talk about these erc20 tokens and these different types of tokens by for now if you get the if you did follow along and you did get the 20 test eth if you open your open if you open up your metamask you won't see it in here erc20 and ERC 677 and different type of smart contract based tokens actually are contracts on blockchains as well and what we need to do is we need to go to docs. chain. link getting started scroll down to link token contracts scroll down to spolia testet and we could copy this address you can also just hit this add to wallet button but we could copy this address roll up to our metamask hit import tokens paste it in there for the seoa test net add custom tokens import tokens and now we can see we have seoa eth and we have Lincoln here so this is just us needing to tell our metamask where to look for these different cryptocurrencies since there are so many it's not going to just be defaulted with any and anybody can create a cryptocurrency so we need to actually import them and tell metamask hey can you look at the balance of this token so now that we have that on our front end here we'll do a little refresh we can see our subscription is active let's go to actions fund subscription let's put in three for now confirm I'm not actually going to run this I'm just doing this to see oh okay well what's the what's the function being called okay it's this transfer and call function that's being called on interestingly enough on the link token contract if we go to the this contract it's actually the link token contract that we're calling transfer and call on not on our VF or or anything like that we're actually transferring tokens to the subscriptions contract and we're calling transfer call on our contract to do so I'm actually not going to call it we're going to we're going to do this programmatically and you'll see that our balance right now is zero but we're going to write a script in solidity to add link to our ID here so kind of like what we were seeing there on the UI and learning about these different tokens we've created a new scription but now we need to do what we need to fund it so you already know we're going to go back to our interactions here and we're going to create a new contract called fund subscription same as what's above this is going to be a script here zoom in just a little bit and you know we're going to need a function run which will be public or external or whatever you want it to be and then we're Al probably going to need a function scription using config and we'll just make this public or excuse me function so we're going to need to create a u into 256 public constant fund amount and for us we'll just set this to be three ether which is going to equal to three link right because link also kind of runs with this 18 decimal places thing now in order for us to fund our subscription we're going to need a couple things we're we're going to need that vrf coordinator V2 we're going to need our subscription ID and then additionally we are actually going to need the link token which we haven't worked with quite yet so I'm actually going to scroll up and I'm going to copy this whole bit right well not this whole bit this bit right here bring it down paste that in here so we are going to need the vrf coordinator address but we're also going to need the subscription ID subscription ID and remember back in our deploy contract now we're actually saving our config do subscription ID we're actually saving the subscription ID to our config object so this here if we're looking for our subscription ID it'll be that new updated subscription ID oh what's it m about oh excuse me this needs to be a u 256 and we're going to need the link token because it's the link token that we're actually making the transaction call to so if we go back to our helper config we're going to need to add a link token so for sapoia this is pretty easy we just do a little comma and we can just say link and then we go back to the chain link docs docs. chain. link let's go look for we can see facets here let's go back to docs. chain. link let's go over to get started we can look for the link token contracts page which is right here we'll scroll down to sapoia and okay we can just grab this or press the copy button here and boom we now have a link token piece in here H we're getting this red line because we got to go up we have to add the address Link in here like so so now we need to go down and we need to fix our local network config as well for our local network we're going to have to deploy our own fake link token now I'm going to teach you about ER c20s and how to work with tokens and what they do a little bit later but for the moment if you just go to the foundary full course f23 if you go to the let's scroll down a little bit where are we Foundry smart contract Lottery let's go into the smart contract Lottery here get to SRC we'll go to test in here we'll go to MOX we'll have this link token. soul you can actually just go ahead and copy this whole thing and this is the codebase that we're going to use so uh don't worry about really what this is doing quite yet you'll learn more about erc20 is a little bit later so just in our test folder we're going to create a new folder called Mox and in here new file we'll call it link token s paste it in now the only other thing is we're actually importing this erc20 from this other package called soulmate tokens. Soul or excuse me do called soulmate so if we look up soulmate GitHub we'll actually come to see this GitHub here as of recording I'm working with V6 of this codebase so we're going to install this exact code base so that this works so I'm going to do a little Forge install transm missions 11/ soulmate I'm going to copy paste it at v6- no-c commit like this and we're going to go ahead and install this cool looks like it was done and then in our Foundry DOL I need to update this so that we know about this soulmate thing so we'll say at soulmate equals uh it's going to be Libs soulmate slsrc like this and now if we go back to our erc20 it looks like it's compiling fine looks like this is compiling fine okay cool and so this is going to be our mock link token contract that we use like I said this is just for testing for us here and if it doesn't have this function we're going to add a little function called mint address 2 it should have this function by the time you get here un 256 value public and we'll just call Mint to comma value and this way we can just mint ourselves link token for our test right it's test it's all good we can do whatever we want with our tests so and in our mock our helper config we're now going to want to deploy this mock link token right and then we're going to use that for our test so we'll go ahead and import link token token from it's going to be test slmx link token. soul and same as what we did for a mock chain link vrf down here so kind of same as what we did for the vrf coordinator mock we'll now say link token link token link token equals New Link token like this and down in our local network we can say this is again in that get or create Anvil e config we can add this oh add a little comma here link and we'll say address link token like this cool so now we're deploying a new mock link token we're getting the link token address in our config here we just do a quick Forge build just to make sure everything is looking peachy hunky dory and we have some warnings which is fine but stuff is compiling hooray and now we can get that address link token equals helper config doget config do link like this and we can finally create this fund subscription where we pass the vrf coordinator the subscription ID and then the link token like this create this new function fund subscription which will take an address vrf coordinator the U 256 subscription ID and then the address of the link token public like this nice okay cool and of course our run function is is just going to call fund subscription using config and in here we're going to actually finally fund that subscription and then of course in here this is where we're going to do a little console. logging we'll say console.log we'll say funding subscription this is where we'll do the subscription ID like this we'll do a little console log using vrf coordinator with the vrf coord address here then a console.log on chain ID with the block. chain ID like this and this is where we have to do a little bit of funk and I know I've been saying that a few times for this section in particular but the vrf coordinator mock has this fun little fun subscription function that you can just directly call however for working with the actual link token it's the link token that we're going to use this transfer and call function to call instead so we're going to just say if block. chain ID equals the local local chain ID and we can actually get this local chain ID by having our fun subscription be a script and code constants and we're going to go ahead and import code constants from the helper config so if block. chain ID is the local chain ID we'll do a little vm. start broadcast so that this will work on Anvil we'll say VF coordinator v25 mock VF coordinator fund subscription and then we'll pass the subscription ID and the fund amount this and bm. stop broadcast and that's all we need to do however else we're going to get a little bit clever here we're going to say vm. broadcast uh and then we need to import the link token in here as well so we'll do import link token from test slmx link token token. Soul like this we'll go back here we'll say link token of the link what do we call it Link Link token oh link token Dot transfer and call so this is some this is a special link token function you'll learn about this much later in the course don't worry too much about it right now but we'll call vrf coordinator fund amount and then we're going to do ai. encode subcription ID so we're going to learn a lot about ABI and coding much later as well so don't worry about this either not understand standing it right quite yet you will learn it later in the course and then a little vm. stop broadcast so now to show you running this as a script I'm actually going to run this and we're actually going to fund that subscription that I just made on the UI here so if we go back to our subscription details I have this ID right here right now it's funded with zero link and you can actually fund these with Native eth as well but we're just going to do exclusively link I'm going to go ahead and copy I'm going to go ahead and copy this ID and and all I have to do is just drop this into my helper config for sapoia we're going to paste that in here I know it's kind of a massive number but this is the beauty of writing these scripts all I have to do is put the subscription ID in here and what I can do now is I can run this fund subscription piece here and since we are not going to be on a local chain we'll be on zolia we'll do this transfer and call bit here and just to make sure stuff works let's do a quick Forge build great like I said I'm going to run this fun subscription as a script I don't recommend you do it quite yet because like I said this will take a while and we really want you to get good at doing everything locally so I'm just going to show you me running it just to show you that if you were to be doing this on a real test net or a real main net this is what you would expect to see and I'm going to show you running this using the-- account thing that we learned in the last section instead of the D- private key cuz remember using your private key and pl Tex is really bad so we really want to avoid that as much as possible so to run the script we first we do need to make a envv and whenever we make aemv we want to make sure it's in ourg ignore so let's just check that real quick sure is okay great and in this EnV though we're just going to add the sepolia PC URL equals and this is where you'd add like HTTP https you know Alchemy do blah blah blah whatever and your suppo RPC URL once you've added that in you can run source. EMV like this and what you can do and what we can do if we haven't already we can do cast wallet import my account-- interactive and this is where you'd enter your private key you'd encrypt it Etc I already have one in here called default which is attached to my private key over here so I'm going to going to use this encrypted private key instead and we're going to do Forge Forge script script SL interactions. s.o colon fund subscription we're going to do-- RPC URL seola RPC URL because we've sourced it from ourv file we're not going to do-- private key we're going to do D- account and then the name of our account minus called default then we're going to do-- broadcast like this and it'll compile oh and we're getting invalid chain ID so and if we go to our helper config let's just make sure we actually have this in here I'm going to zoom out just a little bit 111 55111 oops wrong chain ID there's an extra one in here sorry about that so actually we don't need do chain ID let's just run that again with the correct chain ID this time and it worked successfully and now we just have to enter our password which it offis skates from the terminal which is really nice and boom it's sending this transaction and and we didn't have to have our private key in plain text that feels very good so this is actually going to send some link or however much we defined in our fund subscription so let's go back to our uh interactions. S.A fund amount we set to 3 ether AKA 3 link so great it looks like that has actually gone through so back on the UI I'm going to hit cancel I do a little refresh I can scroll down I can see subscription funded with the transaction hash the amount here and I now have a balance of three link in my seoa subscription awesome so this script is actually working hooray so why are we doing all this well if we go back to our raffle test why are we doing all this it's because this is failing and the reason that it's failing is because we had invalid consumer and so we need to set up our raffle contract as a consumer on the VF so we were just doing all the scripting and all the deployment work that we need to do to get all this set up now some times when you're actually coding this stuff you might say hey uh I'm not really going to go down that path and maybe I'm just going to kind of mock everything and do everything kind of a little bit scrappier in the setup just to make it quicker you can 100% do that however if you are going to have some of these scripts it's best to have those scripts directly in your testing process so that you can test and make sure that your scripts also actually do what you want them to do so this is ideally the way that you always move forward like this okay so anyways this was the place that we were failing we were getting invalid consumer we finally created a subscription we funded the subscription and now we just need to add a consumer right on the UI we have no consumers this subscription has no consumers yet and we could add subscription but we're going to do it programmatically so interactions. s.o we're going to scroll down to the bottom contract add consumer is script like this we're going to have function run external like this for this one though unlike what we were doing before right where we didn't have to grab a raffle contract we are going to need to grab a raffle contract because when we oh let me go reconnect here when we go to hit add consumer here we have to put in a consumer address so we want to get the most recently deployed raffle contract which again we can find in our broadcast section whenever we deploy something so to get that we're going to use that Packaging again and it's been updated and depending on when you watch this it has been updated to make it a little bit easier to work with so we're going to work with the easier version hooray so what we can do is we can go back to this Foundry Foundry devops repo that I created from cyphon to actually easily get and work with the most recent deployments so if we're on Foundry devops we can scroll down into the documentation here uh there's all this stuff blah blah blah we're going to do this Forge install it's just saying hey we need the most up-to-date Forge STD which we are using so we're going to go ahead and copy this page right here just forge install cyphon Foundry devops no commit so let's go ahead paste it in here okay cool so now we have Foundry devops installed we can skip all this what we do need to do is update our founder. to have rep permissions to the broadcast folder so we need to copy this go to our found. found. Tomo and paste this in here so this FS permissions means that we're going to give Foundry read access to the broadcast folder and read access to the reports folder the previous version of Foundry devops had ffi equals true which was kind of the nuclear option which basically gave Foundry shell access to do whatever it wanted to do and we want to avoid that as much as possible so saying okay Foundry you're only allowed to do read on these two folders that's much safer for users to just kind of blindly use so then what we can do is we can copy this kind of top part here go back to our interactions. soul and we can import this devops tool so it's going to be import devops tools from li/ Foundry devops SRC devops tool. soul and now that we have this we can also back down in our ad consumer do function add consumer using config we'll make this public we're going to copy again some of the same setup as what we do up here so I'm just going to grab this bit here helper config equals new helper config then we're going to say the UN 256 sub ID equals helper config helper config dog getconfig do subscription ID then we're going to say address VF coordinator equals helper config doget config vrf coordinator like this and we're going to create a new function function called add consumer which is going to take an address most recently deployed and actually a couple different things we're going to take an address contract to add to vrf address brf coordinator we don't need most recently deployed we just need this one but we do need U 256 sub ID make this public sorry I know this is kind of hard to see let me zoom out a little bit so we're going to have ADD consumer using config we're going to pass the some contract to add to vrf we're going to need to add the vrf coordinator and then we're also going to need to add the subid we can get the most recently deployed by using our run here so we'll say address most recent recently deployed equals devops tools. getet most recent deployment it's the raffle contract that we're looking for on block. chain ID like this and then we're going to do add consumer using config but we do have to pass the in this most recently deployed bit here so that means this needs to have address most recently recently deployed and we can pass that into here like so okay so devops tools that get most recent deployment kind of like what we did previously this is a nice helpful tool just says hey whatever the most recent raffle contract grab that and use that one to add a consumer now for our tests we're probably going to be directly calling one of these functions either add consumer using config or add consumer so now that we have the sub ID VF coordinator and the contract to add to VF we can actually add it here so we can say okay console.log adding consumer to vrf coordinator comma vrf coordinator console.log or it's called just let's just say adding consumer contract and we'll use this one here console. log to vrf core dinator comma VF coordinator like this console.log and we're going to be using onchain ID block. chain ID like so and then finally vm. start start broadcast like this vm. stop broadcast broadcast like this and in here we're going to do vrf coordinator v25 mock VF coordinator Dot add consumer contract to add to oh add to vrf this should be Capital here add to vrf excuse me it needs to be sub ID comma contract add to vrf so if we look in that mock VF coordinator V2 mock there should be an add consumer oh no sorry it's in the subscription API which is inherited by it add consumer which takes a subed and the consumer okay great and and this is going to be calling this function here this should be the exact same as if on the website we were to click add consumer by pasting a consumer address in here so they should work exactly the same okay so we have this okay cool getting exciting we're about to finally get past that issue we can now scroll all the way back up or excuse me go back to our deploy subscription then we're going to fund it it's all about to come together here so we're got to import fund subscription fund subscription and we even tested this one on an actual test net so now we're going to do fund subscription fund subscription equals new fund subscription like this we'll say fund subscription. fund subscription config vrf coordinator right is in our oops in our interactions. s. Soul we have this fund subscription function which take a coordinator subscription ID and Link token so we're going to do coordinator config Dot and then config do link like this now we have to add a consumer oh oh wait uh we oh hold on what's VF coordinator VF coordinator there we go we don't have a consumer yet first we need to deploy the contract and then we're going to need to add a consumer so in our interactions we're going to also need to import the add consumer add consumer what's it called add add consumer add consumer there we go add consumer we're going to import add consumer here and now we're going to do add consumer add consumer equals new add consumer like this and then we're just going to call add consumer . add consumer and what is in this again contract add to vrf coordinator and subid so this is going to be our new raffle contract the raffle contract needs to be our new address here and then we need the vrf coordinator so config vrf coordinator and then finally what's the last one um it's going to be the sub ID so then we're going to do config do subscription ID boom now we don't need to use a prank don't or a broadcast need to broadcast because in our ad consumer we already have two broadcasts start and stop in here so we don't need to do that again okay so now that we've done all of this work right we've updated our deploy script so that now it automatically adds a consumer if we do not already have one this is incredibly exciting back in our raffle test we should see this no longer fail because now it won't give us invalid consumer right we should see an expect revert oops with this raffle not open do selector we should see it revert with this error here back in the raffle we can scroll up if we go to enter raffle and the raffle state is not open it should revert with not open and when we call perform upkeep it sets it it goes hey call perform upkeep boom we are now calculating we are no longer open so when we call this test now it should successfully revert moment of truth let's try it Forge test d-mt paste let's add a couple of these just in case it does fail we're compiling it's got to run all those new scripts that we just added we can see the logs that were created from our console. logs because we added dsv we can see it successfully reverted we can see this revert here raffled not open and we can see our test has indeed passed because we have success ly reverted with this time the correct reversion error am amazing job now this is exceptionally exciting because we just learned to do this whole deployment process right with funding it adding a subscription adding a consumer all of this all in one single function call All in One deployment process this is and then you know well excuse me actually obviously you're going to need to do deploy contract here inside of your run if you were to run this is a script but in any case what's so exciting about this is you are learning really practical really powerful devop skills that like I said a lot of the current environment a lot of the current developers don't actually have so you should feel incredibly proud of yourself at this point at this point I would love you to give yourself a little pat on the back go for a break go take a walk maybe go get some ice cream maybe go to the gym get a pumpin but you should be very excited with yourself for getting this far I know that was a lot to take in feel free to pause kind of fiddle with some of the code that you just wrote try to Tinker with this see if you can get it to do something else but just by us doing all that work and getting this test to pass you should be very proud of yourself if you are a little confused about any of this be sure to go over to cyphon updraft right we want to go back to cyphon updraft go back to the GitHub resources in the GitHub resources be sure to jump into the discussion ask some questions if there's anything that wasn't clear or maybe just take some time to go answer some other people's questions right because now you've got a ton of knowledge and maybe there's somebody else who has come along the way who you want to give a hand to and maybe be a TA to as well so I'm going to tell you now is the time to take a mandatory break I'll see you soon all right welcome back hope you did actually take a break because we're going to continue writing these tests we've just learned a ton and built actually most of the code that we need to build but if we do a bit of a forge coverage here we see what our coverage looks like for our codebase we're going to run all of our tests here and we're going to see okay raffle doou the code base that we actually care about we're only really at around 50% code coverage right so what's coverage again it's how many lines of code are actually tested now you don't have to hit 100% test coverage but that's really what we want to aim for there's going to be times where okay like writing test just to write test is like ah cool I wrote test just to write a whole bunch of tests but we really want to be intelligent about how we're writing tests here us writing tests actually has already uncovered that we needed to improve our devops processes right and that when we actually deployed our contracts there were steps that we might have been missing so we've actually already learned how to improve our codebase just by writing these tests and making sure all the different functionalities work so we want to keep writing tests we want to make sure we get this code coverage up a lot higher than it currently is so that we can have some assurance that our code is actually doing what we want it to be doing if we pull back if we go back to our raffle contract we've written a lot of tests for enter raffle we should probably write some tests for our check upkeep to make sure it actually checks the upkeep at the right time so what we can do is back in our tests if you downloaded the headers project headers check upkeep like this we can do a little Boop paste it in here like this if you didn't download this then you can just create your own little delimiter as you please there's obviously a number of different tests we need to write here we should check to see if enough time has passed if it's actually open if it has balance players blah blah Etc so let's go ahead and Rapid Fire some of these tests out so let's actually make sure that we always have some type of balance and that checkup keep will return false if we don't have balance so we'll do function test check upkeep returns false if it has no balance balance public and we'll do arrange we'll want to do kind of similar to what we did before where we actually do roll the blockchain so at least all of this is valid so I'm actually just going to copy paste this down here increase the block time and the block number but we are not going to enter the raffle right we're not going to call enter raffle here so it should return false so now we're going to do our act which is going to be bull up oops up keep needed comma equals raffle do checkup keep like this and then our assert which is going to be assert not upkeep needed like this or bang upkeep needed right so let's go ahead and test this Forge test d-mt paste that in and that was successful okay great all right what's next we probably want to test that this check upkeep returns false if the raffle is not open okay so we'll do that as well so we'll do a little function function test check up keep returns false if raffle isn't open public so now that we've kind of gone through this whole process of figuring out how to close the raffle and get into that calculating State we can actually just copy most of this up here for the arrange step so we'll prank a player we'll enter the raffle we'll change the block time we'll change the block number we'll call perform upkeep and this should close the raffle so now we can do act this is going to be the same thing bull upkeep needed comma equals raffle do check upkeep with blank data and then for our assert assert we're going to assert bang up keep needed like this and we can test this as well Forge test-- Mt paste it in and great that has passed as well now as we're coding along right just doing kind of that coverage Port it might be a little unclear how much more that we need to do so if we want to get a better idea of what steps we have to take what lines of code we haven't covered yet we can actually do Forge coverage D- report debug like this and this will actually do that same Forge coverage bit except this time it'll give us a coverage report it'll tell us what lines in our test Suite we have not actually used yet so what I like to do though is I like to hit up a couple times here actually pipe this out so this little carrot thing is a pipe thing and I and we'll pipe it out to like a coverage. txt file and so what this will do is once it's finished running we'll wait a little bit wait a little bit for it to do everything is it'll create a new file over here called coverage. txt and it'll have all the output of that terminal command and we can see different sections in here that give us information about what lines are not covered so it talks about script deploy raffle we don't care about that we don't care about helper config we don't care about interactions well maybe we do a little bit but we mostly care about raffle dossou and it gives us different functions and line numbers that we don't have any test for yet so we can see function blank okay that's a little odd but on line 65 let's go in here let's look for line 65 1 2 3 65 okay that's the Constructor ah okay yeah we probably should check to see that all of our setting in the Constructor is actually being set correctly ah okay that's a good point okay what else okay and usually I just kind of like skim for the line numbers okay line 73 where's line 73 uh oh yeah okay I entrance fee equals entrance fee yep we have not checked that this entrance fee is correct okay 74 75 yeah yeah yeah okay got it so function blank this is going to be the Constructor Okay cool so we haven't checked for all these variables in the Constructor okay makes sense uh what else so there's line 80 uh okay cool we have line 129 and line let's look at line 129 let's see what's down there line 129 ah okay if upkeep not needed revert we are not checking we don't have a test that checks this rever yet okay good point what are the lines line 130 okay that's still part of that line 130 line 152 okay what's on line 152 let's scroll down ah okay sure we haven't checked fulfill random words yet and so this will give you a good idea of hey here are the lines that have not been tested yet so we could go through this kind of one by one making this smaller and smaller uh so that we can get that coverage that we need for raffle do Soul so going through this we could write a lot more test right I'm not going to write all the tests here but I encourage you to try to write some more tests and figure out if you can get the test coverage up that's going to be your homework if you will right there's going to be a whole bunch more tests that we need to write that we haven't written yet right so this is going to be your challenge right and you don't need to make a PR to the GitHub repost associated with this course you don't need to do anything this is really for you and see if your coverage goes up when you write this right you're probably going to want to write a test check upkeep returns returns false if enough time has passed you're probably going to want to write a test check up keep returns true when parameters are good and I actually have written these already they are in the giab repo associated with this course if you want to go and check to see what I wrote for them feel free but this is your kind of challenge here to go and write some more of these tests for checkup keep so just for checkup keep we are actually going to walk through some of the per form up keeps together but if you want to go ahead and pause the video take the time to actually challenge yourself and write the test yourself I encourage you to do so and then you can check the get up reill for the answers all right welcome back we're going to write some perform upkeep tests these are going to get a little bit more interesting because we have to do some very specific things here and then we're finally going to do the fulfill random words test which are going to be the most interesting if you have installed the headers perform upkeep if you have install the headers tool go ahead and create that little delimiter otherwise do whatever you please to create a delimiter here and let's write a couple of perform upkeep tests where we will learn some new tooling along the way so one of the things we absolutely want to make sure of is that perform keep is only called if check upkeep is true so we can create a function there function function test perform upkeep can only run if checkup keep keep is true make this public we'll do a little arrange as you know do a vm. prank of the player we'll need to enter the raffle actually I'm just going to copy all this because this is all some important information that we need to do we're going to enter the raffle with an entrance fee update the block time the block number and we're actually not going to call perform upkeep but instead we're going to do is act SL assert and this is where we're going to say raffle perform upkeep like this now with boundary this is a way for us to test if this actually went through right if this function errors excuse me if this function errors this test will actually fail technically there is a slightly better way to do this where we do like raffle doall and we kind of pass like ai. encode data blah blah blah blah blah and then like bull success comma this is some stuff you'll learn much much later and then we do like assert success but for now there's some stuff you haven't learned quite yet so for now we're just going to say raffle do perform upkeep upkeep like this so later on we'll teach you kind of the better way to test these like this but for now just do raffle up performal keep if this fails then this whole test will fail so we can actually test this out Forge test d-mt paste that in and we'll see that this does indeed pass once everything compiles and runs great and if we were to change this for example let's not update the block time right if I save this should fail now perform up keep keep should fail and therefore our test should fail so if we run this now we'll see that our test does indeed fail which is kind of interesting because in this case I'm kind of testing the test okay cool it is indeed failing so great so we'll put that interval back in we'll rerun the test and we'll get a positive output so that our tests are actually working all right cool great all right let's keep going next we're probably going want to test to make sure we actually do this revert here and how we're going to test this is going to be new because this is the first time we have a revert code where the revert is actually very specific right the revert code has all these parameters so we need to test that this raffle upkeep dot needed is reverting with the correct stuff in the revert area here so we're going to do function test perform upkeep reverts if check upkeep is false we'll make this public like so we'll do a little arrange AR range we'll say un 256 current balance equals z we'll say un 256 num players equals zero you'll see why I'm doing this in a second and then we'll do raffle do raffle State R State equals raffle doget raffle state I'm setting these up because these are going to be the parameters that we're going to need to pass to our error here so we can actually just jump right into our Act SL assert and we can do vm. exect revert I'm just going to do this for now but raffle perform upkeep so we've done vm. XC revert a couple times here right up here we just said raffle do you know the name of our custom error do selector same thing with down here however this one has parameters inside so if we go back to The Foundry documentation and we get our expect revert we can scroll down and we can see an example with a custom error type with parameters we have to do this thing called ai. encode with selector once again we will actually learn this much later but for now just kind of blindly follow along what we're going to do in here is we're going to say vm. revert ab. encode with selector we're going to say raffle do raffle upkeep not needed selector and we're we're going to pass the current balance the number of players and the r state so we want to make sure oh and then no semicolon here so we want to make sure we're reverting with the correct code base upkeep not needed did I spell or we're reverting with the right error raffle upep not needed upkeep not needed did I spell raffle wrong raffle that raffle up oh I missed an underscore okay cool upkeep not needed now it's probably better if we were to maybe enter with a player right if we did like vm. prank vm. prank player and then we did like raffle enter raffle value value entrance fee now current balance is going to be current balance equals the current balance plus entrance fee oops entrance fee and then the num players equals 1 now uh and then we would just you know get rid of that but in any case we can go ahead and test this now so Forge test-- Mt paste it in I'll add a couple V's on here as well if you want to see kind of the more debugging output here and great the test went ahead and passed it reverted with upkeep not needed and the correct parameters here so that's very exciting nice so we've learned this more explicit way to do our vm. XC reverts now nice so again here we're just doing the the custom errors selector here and then the three parameters that go with that custom error right because this had the balance player length and then the raffle State and that's exactly what we're expecting for in our assert here now we're going to do something a little bit different here so we're actually going to refactor this perform upkeep just a little bit so I can teach you something kind of cool so in our raffle doou when we call request random words this request random words actually return something called a request ID so I'm actually going to do a little bit of refactoring unit 256 request ID like this and let's actually have this emit an event so this perform up keep we're going to do a little bit of refactoring so that it emits this request ID so if we scroll up to the top here we'll create a new event we'll call it requested raffle winner with a single U into 256 indexed request ID and we're going to have our perform upkeep let me scroll the way down here perform upkeep we're going to say emit request ref winner request ID now a quick quiz for you you know is this redundant redundant if you want to go ahead and figure it out I will let you pause the video now because I'm going to give you the answer in a few seconds is this redundant I'm going to tell the answer in three 2 1 answer is yes and that's because that our vrf coordinator is also emitting this event if we go to the vrf coordinator mock or you can actually go to the vrf coordinator itself and we scroll down to request uh where is it uh request request request request random request random words you can see in here it has this Amit where it emits random words requested and the second parameter here is actually that request ID so us actually emitting the event here is a bit redundant because now we're emitting the request ID and the chain link VF is admitting the request ID so we don't have to do this but I'm going to add this in here just to make some of our tests a little bit easier make learning a little bit easier here so we're going to emit this event here we want to just make sure it's actually working we'll do a quick look Forge little build here just to make sure we didn't mess up any of the events that we wrote and that actually worked now the question I want to ask you this is what if we need to get data from admitted events into our tests and the reason that we're asking this is because guess what we actually are going to need to get that so how do you think we would do that well there is a cheat code for that so let's create a new test we'll call it function test perform upkeep updates raffle State and emits request request ID public like so we'll do a little arrange first dm. player codee's getting a little redundant here I'm going to scroll up a little bit we're going to copy these three because I don't feel like writing it again paste it here enter raffle warp the block excuse me warp the block time roll the block number then we're going to get into act here and we're going to call perform upkeep but what we're going to do is we're going to record all the logs using Foundry and we're actually going to get this request ID by by reading these logs in Foundry and so Foundry has a cheat code called vm. record logs where this will literally do as what you kind of expect it to do it'll record logs so we can see the record logs in The Foundry book here and you can see kind of an event uh you can see kind of an example in the documentation here and we're going to draw some inspiration from the docs over here so we're going to say vm. record logs and we're going to do raffle . perform upkeep upkeep and calling record logs and then calling raffle perform upkeep This vm. Record logs says hey whatever events whatever logs are emitted by this perform upkeep function keep track of those and stick them into an array so then what we can do is we can say vm. log array and we're going to have to import this VM thing import VM from for Forge STD slvm doou so we're going to have to import this uh kind of special VM thing I know it's capital and I know these ones are lowercase this is a super special log here or this is a super special cheat code but we're going to do vm. log array memory entries equals vm. getet recorded logs and what this line is going to do is it's going to say hey all of the logs all of the events that were emitted in perform upkeep all ones that were recorded stick them into this entries array and then what we can do is we can actually walk through this entries array and grab the different values in it so inside of this entries array there's going to be a lot of logs now we can actually even see if we go into the vm. soul and I know this is kind of big we can look for that struct log and we can see kind of what this log struct looks like it's going to have a bytes 32 array of topics it's going to have the bytes data and then the address emitters so remember topics are going to be any indexed parameter in an event and then byes data is going to be the combination of all other events right so if we want to get our request ID in the raffle we would just need to find the event or the log that was emitted and then grab the first topic from it so what we can do and if this is a little confusing this is a great place to kind of pause do some console. logging and seeing what is actually being emitted here but what we can do is we can say byes 32 request ID because everything in these logs is going to get stored as a by 32 request ID equals entries 1. topics one so uh the first log that gets emitted actually is going to be from the vrf itself so that would be like entry zero that would be from the VF coordinator we're going to go for entry one our event is going to come after the vrf coordin and we're using topic one instead of topic zero because the zero with topic is essentially always reserved for something else and you'll learn about that later or you can look more into logs yourself it's not super important but basically we have this request ID and so what we can do now with this request ID now that we've recorded it from the logs here so we can go into our assert mode assert and we could say raffle do raffle State full state raffle State equals raffle.com equals or excuse meert the U into 256 raffle State equals equals 1 so we're making sure we get a request ID and we're making sure we get this request ID when the raffle state is actually converted so this is a pretty Advanced test here let's give it a try so we'll do Forge test d-mt paste it in here -1 2 3 4 and we'll let this run and awesome this does indeed pass here and if we look at kind of the logs that were created here if we see this vm. get recorded logs we can see the whole list of arrays in here this is the first one this is the second one the arrays of these logs right so this this first one in this array this is going to be the log emitted by the chaining vrf contract and this is going to be the log emitted by us right so it has it has one two topics the first topic like I said being reserved the second topic being that request ID no data and then the address of was emitted very exciting now because we're going to be copy pasting this a lot this can actually get really annoying so what we might want to do and what a lot of people will do is they'll actually create a modifier modifier called raffle entered where we'll do exactly this I'm going to copy this paste it in here get rid of the arrange and then instead of doing this in our test here we'll just say this public function now has this raffle entered modifier and that will mean that this modifier actually runs before our test runs so this is actually a really popular convention for ready your tests anytime you have to kind of repeat some type of trivial thing for a whole lot of your tests it's best to modularize it into one little modifier and then just stick it over here and now our test is a lot smaller and looks a lot cleaner cool great job so let's go ahead now I think we've tested perform upkeep pretty well if you want to go and take some time to do this yourself now feel free to do so but let's go ahead let's do a little headers if you installed it fill random words paste this here and let's begin okay all right so now we're going to start writing some really cool badass tests and these are about to get much much much much more interesting so so fulfill random words so this should only be able to be called after per perform upkeep was called so we probably want to write a test that says hey fulfill random words can only be called after perform upkeep was called so we could do a little function test fall fill random words can only be called after after perform upkeep public like so and we'll want to make this a raffle entered we'll want to give this the raffle enter modifier so that we don't have to write all this stuff that we did up here anymore so how can we test that fulfill random words can only be called after this can be called well this is where we can rely once again a little bit on our vrf cordinator V2 mock or just our vrf coordinator because if you do a request random words in here but if you do not have a valid request you should get an invalid request error here so this is the error that we're going to be looking for we're going to see if we can get it so we'll do a little arrange SLA SL assert actually where we're going to say vm. expect revert and we're going to do vrf coordinator v25 mock dot invalid request this is a simpler one do selector there's going to be no parameters here and then we can just say we'll call vrf Cord 25 mock V RF coordinator. full fill random words and we'll see in here so there's fulfill random words override there should also be fulfill function fulfill random words which calls fulfill random words override so we'll call fulfill random words here which takes a request ID and a consumer so we'll say fulfill random words we'll just kind of pick a random one we'll pick zero and then the address of the raffle here and of course we need to import this vrf coordinator V2 mock so I'm going to scroll back up to the top we're going to import that VR qu V2 mock from at chainlink contracts slash uh where do we think we import this in the helper as well yep I'm just going to copy this line I'm going to paste it right here okay cool very nice let's scroll all the way back down and cool this is looking good now now when we're running this test here we're pretending to be the vrf coordinator right we're using the vrf coordinator V2 mock which allows anybody to call fulfill random words because it's a mock right in the actual vrf coordinator not anybody can call this fulfill random words right only the chain link nodes themselves can actually call this function so this is great uh and actually let's go ahead and and test this so we'll do Forge test d-mt paste it in let's do a little zooming in here hopefully this passes Tada okay this passed well that was cool but we kind of picked a request ID here so well that was kind of a random one we picked so we should probably also check request ID one right probably also check request ID 2 and request ID three and we should test that no request ID works at all and we should check request ID 478 M400 77 as you can see it's very infeasible to write a ugly test that looks like this with all these test cases so instead what we can do instead of adding you know 1 2 3 4 5 6 7 8 9 10 is we can write what's called a fuzz test and for most of your testing ideally you do some type of fuzz test or in this case it's known as stateless fuzz testing for most of your testing and in the future you should probably try to default all of your tests to some type of fuzz test now we're going to go much deeper into this much later because there's a lot to unpack with fuzz testing and how it works and what the important pieces are but for now let's kind of give you the basic gist of it so let's delete everything we'll just come back down to this and I've got a number of fuzz testing videos on my YouTube that we're going to watch much much later in this course and especially in the security and auditing course however if you don't understand this part completely that's okay if you just understand kind of the basics high level great instead of us choosing 0 1 2 3 4 5 6 7 8 9 10 whatever what we can do is directly in our test here in this little parameters here we can say uint 256 random request ID and we can take this random request ID and paste it in here now when we run this test let's actually see what happens so the only thing we added was we updated this parameter in here and we added it to our fulfill random words now we clear everything out we do Forge test-- Mt paste it in- vvv now we're going to see a slightly different output it's still going to pass it's still going to look pretty much the same well we're still going to get our console Del logs out but there's actually a very important difference here up at the top here it says test random War can only be blah blah what whatever runs 256 and then some of this stuff here runs 256 what this means is Foundry actually ran this test 256 different times with 256 different random request IDs to try to break this where if you give it a value to run as a f test it'll try to pick values that will break your test it's attempting to break your tests and that's good that's what we wanted to do we wanted to try to break our test and like I said much much later we'll learn more about writing really cool really badass fuzz tests but if we go back over to our Foundry doomo we can go ahead and click command click or copy paste this link to open up this list of different conf figs in The Foundry configs here and if we scroll down far enough or just look for fuzz we can see this fuzz section so I'm just going to copy these two here and in my found. I'll paste fuzz runs equals 256 so this is Foundry going to try 256 different random numbers if I increase this to 1,000 right fuzz runs to 1000 and I rerun this test what do you think we're going to get well we're going to look at this this line again it's going to say runs 1,000 so it tried a thousand different random numbers well what do you think will happen if I put this huge number in here well uh don't do this if you don't know how to quit uh commands by the way or I guess not that huge let's try this huge number in here it's going to take a lot longer to run cuz it's got to try a lot more scenarios and so this is where fuzzing is really really powerful and sometimes people run what's called fuzzing campaigns for a long time they create a ton of fuzz tests and they just let them run in the background or run in the cloud for a long time to try to break their code base because sometimes there are very weird outliers very weird scenarios where a fuzz test catches something crazy so it's great to default it to 256 for now and fuzz testing is probably one of the most important probably one of the most powerful testing methodologies you will learn in your smart contract development journey and we're not going to go over it super deep quite yet but like I said later on in the course we're going to go crazy crazy deep especially at that stable coin section we're going to go super deep if you do get to the security curriculum we go even deeper into fuzz testing over there because fuzz testing is absolutely crucial but you've written your first stateless fuzz test and you'll learn what stateless fuzz tests mean much later and this is very exciting because this is one of the most important Concepts in your entire journey and just by you learning this it's crazy that I even say this but you are already better you know more more than a lot of the current smart contract developers so heck yeah all right so we could probably keep writing more tests but I think at this point you're really getting the gist of what I want you to learn however I do want to write one final giant end to- end test just to kind of test all the functionality right and there's probably a whole bunch more coverage that we could do like I said at the end of this if you want to go try to get the coverage up as some practice for yourself awesome highly encourage you to do so but let's just kind of end to end write a test and then we'll use that as a baseline for an integration test as well you ready I sure am let's get into it so we're going to call a function called test fulfill random words picks a winner resets and sends money this will be a public raffle entered function so we're going to do kind of an end to- end test we're going to say once the chain link vrf calls fill random words it's going to reset the whole array it's going to send the winner the money and yeah we're going to pick a winner so this is kind of like the Pinnacle test here this is really kind of putting all the pieces together and we're going to make this a little bit complicated because we want to really make sure our functionality works here so we're going to do a little arrange a little little setup here so we're going to say un 256 additional entrance entrance equals three so we're going to have four people total four people total actually enter this Lottery additional entrance additional entrance I think I spelled that right and we're going to say un 256 starting index equals 1 and you'll see why I'm doing this in a second so we're going to have four different players actually enter this Lottery and we're going to do that by creating a for Loop for un 256 I equals starting index I is less than starting index plus additional entrance I ++ like this and we're actually going to start with one because we don't really want to start with address zero but we're going to say address new player equals address uent 160 I so this is kind of a cool cheaty way to convert any number into an address so starting index is going to be one this is kind of equivalent to us being like address of one or address of two or address of three etc etc so address new player equals address like this and we need to give them some eth so we could do a vm. deal and give them to me however we're going to use a cheat code another cheat code just called straight up hoax and if we go to the found documentation this sets up a prank from an address that has some ether so what we can do do is we can say hoax new player and then just give them one ether so this sets up a prank and gives them some ether and we can say raffle do enter raffle with value entrance fee like this so we're having three additional players enter the raffle right because where raffle entered the first player has already entered we're adding three more players here just to get a more realistic example of what a lottery is going to look like then just to make sure uh time stamps are actually going to get updated we're going to keep track of the S last timestamp and I don't think we have a getter for that so let's go ahead and create function get last timestamp external view returns U into 256 return sore last timestamp great so we're going to say uint 256 starting timestamp [Music] raffle.org record logs oh uh record logs we did that up here we're actually going to do this exact same methodology so I'm going to copy this I'm going to come down here here I'm going to paste this here so we're going to record the logs we're going to perform the upkeep this is going to kick off the chain link vrf the chain link vrf is going to create a bunch of logs we're going to get that request ID from that list of logs and then what we have to do finally is we're going to pretend to be the if we go back to the raffle we're going to pretend to be the chain link vrf node and call fulfill random words however we're not going to call fulfill random words no no no we're actually going to call coordinator V2 mock it's going to be uh oh never mind I lied it is fulfill random words so we're we're going to call fulfill random words here so we're going to say vrf coordinator v25 mock of the vrf coordinator so this is simulating getting that random number back cordinator fulfill random words a ENT 256 request ID so we're going to typ cast this byes 32 back to a into 256 and then the address of the raffle so this should give the random number to our raffle right because our vrf coordinator mock is going to call our raffle here which is going to call this fulfill random words and all of this is going to run which we haven't tested yet right so now we get to go and make sure that all this actually worked correctly so now that we've done the ACT we can go right into the assert so what do we want to do well we want to make sure the winner is correct so we'll say address recent winner equals raffle doget recent winner we want to say raffle do raffle State raffle State equals create that so let say function get recent winner external view returns address like this and then we'll say return sore recent winner and I know I'm going a little bit quick feel free to pause me if you need to so raffle doget recent winner raffle doget raffle State we'll say un 256 winner balance equals recent winner. balance let's get their balance un 256 ending time stamp equals raffle doget last time is it get last time stamp what do we just call it get last time stamp yep get last timestamp and then we'll do un 256 prize equals raffle entrance fee times additional entrance plus one so since oh excuse me not raffle entrance fee it's just going to be what is it uh entrance fee so since four people have entered the raffle this should be this basically should be four we're taking the entrance fee Time 4 and that's the prize that should have been given to the recent winners we want to make sure that that's actually what happened and so I kind of already cheated and looked ahead and did a little bit of math but I also found the expected winner so what I'm going to do also is I'm going to say addressed winner equals address one like this and we're going to get there starting balance so we're going to say un 256 winner starting balance equals expected winner. balance like this and for our asserts the first thing we're going to do is we're going to assert the recent winner is going to equal the expected winner we're going to assert the U 256 raffle state is now zero it should be back open we're going to assert the winner balance is going to be equal to the starting balance or excuse me the winner starting balance plus the prize and we're going to uh excuse me and we're going to assert the ending timestamp time stamp is greater than the starting time stamp and I'm going to run this and it's going to fail so we're going to do a little Forge test d-mt and I'm intentionally running this to fail because I want you to try to figure out why this is failing for you to do a little little debugging because guess what a lot of your coding is going to be writing tests and then it's going to be debugging tests and you getting really good at doing this is going to be really helpful so if you're getting an error like this great if you're not getting error like this I guess you're locked out because maybe you changed something but if you're getting an error like insufficient balance this is a great time to pause the video and try to figure out hey why am I getting this a why am I getting this bug so if you want to pause the video challenge yourself to figure this out to do a little bit of debugging then come back we will walk through debugging this kind of similar to how we did before so go ahead and pause the video now all right cool well hopefully you try to figure this out yourself but if not that's also okay however you're just cheating yourself and that's kind of lame so let's go ahead though and let's figure out what this issue is so if we again we could just kind of search this search for like a revert in all of our files and we kind of see this all over the place um but if we look in our debugging Trace here we can see it called vrf coordinator V2 mock fulfill random words and it was this function that failed right that's why it's red and we see kind of this revert kind of pointing back up to this call so we know the vrf coordinator V2 mock it failed in here with insufficient balance so if we look up insufficient balance we can see ah there's a couple places where it's calling insufficient balance so basically we're not using native payment so something in here is airing are we are we not funding it I thought we I thought we funded it right we we definitely funded it and this is where maybe we could do like some console. logs on you know previous balance payment you know do we do we fund it enough Etc and we would have to import console into here of course but I'm going to tell you just straight up we set our helper config parameters kind of high which made this a little bit difficult to get the price so we could either drop those down or I'm just going to be a little bit cheater in our fund subscription I'm just going to say fund amount times 100 so we're actually going to fund our local chain smart contract with 300 link and when we rerun this we will see hopefully that this pass and everything else is correct and what do you know it sure is wow that is exciting okay so now that we've done this giant test we can do another Forge coverage here let me zoom in just a little bit and we won't do the whole debugging bit but we'll just get a better idea of how much better our tests are and if we scroll down oh okay we got some green here so we're like 80% of all functions 75% of all branches or like conditionals 81% % of just all statements in our code and then 78% of all lines ah we're starting to look pretty good here so it's still not perfect but it's much better right we could keep testing we could keep adding tests I know I challenged you to write some more tests typically you're aiming for maybe 90% or more but each codebase is going to be a little bit different maybe you have some really sophisticated fuzz tests or form of verification or some you know we haven't talked about form of verification but maybe you've got some other sophisticated stuff they using to test and that's okay but typically you're aiming for 90% or more on coverage but this was still phenomenal we wrote we wrote a massive giant unit test just to kind of see the full flow end to end things are passing so this is a very good sign so our tests aren't done we probably want to do more testing of these as well but the most important thing for me here is that you're getting a better understanding of how to write tests where to write tests and the importance of tests now so this is great so this will work perfectly for our local Anvil test right because we just tested it as such but will it work for our forked tests well pause the video and see if you can figure out that answer so if we run Forge test-- Fork URL and we do sepolia RPC URL let me Zoom it a little bit more more what do you what do you think will happen you think it'll pass you think it'll fail well we're going to try it so I have this as my environment variable and I am already getting a failure setup failed must be sub owner okay well let's just double check that Forge test still works all of our tests okay yep all of our tests run okay so something's wrong with forking tests so why is this failing and remember our Fork tests are so important because we want to make sure that hey if we actually ran this in a real environment would all of our tests pass so we can do this again with A- vvvv and see the output here now that we're going to get some better debugging here and we can see we're getting this test on vrf coordinator at consumer must be sub owner ah so maybe the private key that we're using is actually wrong now we're getting this issue because we are adding consumer and back in our deploy raffle here and maybe for some reason you're not but for some reason the broadcast address is wrong right when we run this on a forked chain right it's just going to use some random private key but when we run this on the actual test net it's going to use the correct test net now we could say okay let's just go into our helper config and we'll scroll all the way down here so right now I have a subscription ID I could just set this to zero and right me setting this to zero will make it so that this code base automatically gives me a subscription and I could rerun this and see if this fails and this one also fails we get erc20 transfer amount exceeds balance cuz cuz we're trying to transfer some link token that the test addresses that we came up with don't have any of them so that that doesn't work either H so how can we write these Fork tests in a way that makes sense also I don't want to have to delete my subscription ID on my sapoia config that also stinks so what can we do here so let's go about fixing this so that this will work both for our Forge tests and for our Fork tests here now of of course if we were just doing our scripts locally we could just go ahead and say hey you know what vm. prank and then you know whoever we wanted to do but we want this set of scripts to also work with a real Network so we're using vm. start broadcast this vm. start broadcast is actually a little bit more powerful than what we're using it for so you can use vmd start broadcast and it'll automatically work with whatever Network it's given so like if I do you know if I do Forge script you know whatever the script D- account blah blah blah blah whatever account or you know or the horrible D- private key blah blah blah blah this private key or this account will be the one that's actually doing the broadcast right that's actually doing the transactions here however what we can do as well is we can actually pass an address who or a private key into this start broadcast and it'll use that as the address to broadcast things what I used to previously teach was sticking this vm. unit private key as an environment variable and grabbing it into the star broadcast but as we know we don't want to do that because that would mean we would stick our private key in here so what we can do instead is just stick the address of the account that we're going to work with into this start broadcast and same as kind of what we saw before if we were to send this now we would just get prompted for a password to decrypt that key and it would work kind of normally so what we can do then is we can make this address that we're using a little bit more modular by going to our help config and creating a new section in here so in our config what we can do is we can scroll up to the top and update our Network config here and we can add an address account and so for each one of our networks for zolia and for our local network or in mainnet or in anything else we can choose a different account that we're expected to work with and that way we can prank or start broadcast that specific address so for get eth polia config this is where maybe you'll put in your private key that you're going to be working with so I'm actually going to go ahead and grab mine and paste it in here and this of course is going to be a burner wallet of mine one with no real funds associated with it and then down here we're going to do account and for this one we're actually going to do a special account here now if I look up base. Soul this is abstract contract common base this is in the Forge STD SRC based. s in here there is this default sender address address internal constant default sender and this address is going to be this one right here this is the default sender that whenever Foundry needs to use some type of address to send some stuff this is the address that it's going to use so we can use this to our advantage in our helper config we can set the local network default account to being this local to being this default sender this way we don't have to do any weird key stuff or or enter any passwords or anything so now if we set this up as the account for our local testnet this Foundry default sender and if you're having a hard time finding this in the codebase you can also go to my GitHub repo as well and grab it from there uh but if we set that up as such and we set up an account that actually has some Link in it that has some test at eth what we can now do is we can now refactor all all of our stuff anytime we did a vm. broadcast in our script here we can update this to use Excuse me in our script and exclude our lib we can update these ah we can update these so that they use this new account right so we're getting our config right here so we can do vm. broadcast config do account so this will now be the account in our helper config so same thing with our helper config vm. broadcast it matters a little bit less here because this is only going to be when we're working with a local network anyway so we can actually skip this one but this one we're probably going to have to do a major refactor create subscription let me just do a little word wrap here is we can have this also take an address account pass the account in here then up here we're going to have this take some type of account that we get and we'll say address account equals helper config config do get config do account like this okay that looks good do we need to update anything else no that looks fine okay great what's next okay this is fund subscription okay if we're on the local chain ID doesn't really matter but what we can do is same thing here we can have this taken address account and we'll say vm. broadcast from the account and then scroll up fund subscription using config this will also take an account that we'll get from address account equals I think you get co-pilot paste that in there cool that's local great that looks good then right here same thing we'll do account we'll have this take an address account we'll have this pass it and address account and then we'll say address account equals helper config doget config do account like this right we'll do a little Forge Forge build just to make sure it's actually working oh and I forgot to add the accounts in here so in our deploy raffle we're going to have to do config do account add that here we're going to have to add it here or else we're going to have to this vm. start broadcast cig. account okay cool let's try a little Forge build now oh we forgot one more so this is also going to have to be config do account for add subscription okay cool anything else do another Forge build all right perfect compiler run successful so let's see if this now cleaned it up for us let's do a Forge test ah everything passes for Forge test okay well what about Forge test -- Fork URL sepolia RPC URL see if it works for sepolia now oh it looks like two of them failed which one's failed test fulfill random words can only be called by perform upkeep and test fill random words picks a winner and sends money how do we fix those well let's see those two tests here it was our last two tests that failed test fulfill random words and test fulfill random words now here's why these are always going to fail on a fork test we are mocking we're pretending to be the chain link V of coordinator and of course that's going to fail the actual chain link coordinator have access controls and only let the chain link nodes call fulfill random words and we're pretending to call random words on both of them so if I were to just run maybe this giant test right Forge test d-mt paste it in-- Fork URL a py RPC URL oh and uh excuse me let's add a bunch of V's as well - vvvv let's see what we get here uh fulfill random words meta multisig wallet so we're getting some error here called meta multisig wallet evm error revert we can see the vrf coordinator 2.5 fulfill random words is actually failing why is it failing well because we're trying to call it with an address that doesn't make sense so what we have to do is we have to create a new modifier in here we're call it modifier skip Fork like this and we're just going to say if block. chain ID does not equal local chain ID then we're going to return otherwise pass and so local chain ID looks like we don't have this so we're going to have to do import code constants from script script slh helper config dos. so like this and our raffle test is code constant test now we should have access to that and we should do and then these fulfill random words should be a skip Fork test so these should not run when we're doing a fork test so now we can rerun this and everything should pass because now we're going to skip those two that don't make sense for us to to Fork let's get rid of the test let's just run all of them as a fork test and everything's passing all right let's go so we could 100% make this even more we're going to run a more strict a more resilient Fork test we're actually going to prank be the vrf nodes and we're going to encrypt the data the same way the chain link vrf does and we're going to try to get the random number the same way at some point you're going to have to call it so I think for what we're doing right now this is okay as you get better and better at doing this stuff you will understand where it makes sense to call it or where it makes sense to have more tests for our code base here this is pretty good and like I said as we continue with the course you'll get much better at writing different types of tests all right so we've written some really badass unit tests which is awesome however you thought you're done writing tests you're not done writing tests there are more tests to write but I'm going to give it to you as a challenge to do right maybe we do integration. T.O or we could call this interactions. T.O where we test kind of all our scripts in here remember there are several different stages to us writing tests we have our unit tests which are kind of the most basic tests that we really just went through in our raffle test. T.O then we can do our Integrations test which is going to be testing all of our deploy scripts and how all of our contracts interact with each other then we could go to the next step if we really wanted to to what we would call a staging test and this is where we deploy to a mock environment a live is environment this could be something like an actual test net a virtual Network that other people are interacting with but basically some type of predeployment virtual net Etc I'm planning on in the future going to be teaching most of this curriculum with something called a virtual Network which hopefully will make this a lot easier because doing things on a test net is really difficult right now especially to get enough test net funds some people even deploy their codebases to a really cheap live Network just to have a better understanding of how their code's going to work there are some blockchain networks like polka dot that actually have an entire blockchain dedicated to running what's called like a staging environment with like realish money so the their staging environment is worth real money and then their production environment is worth even more real money right so there's lots of different ways we can approach these tests and and it's important to think about the different stages and the different trade-offs between each and this isn't even the full scope of all the tests that it's good practice to have so we talked a little bit about fuzz fuzzing and fuzz tests but there's actually even more advanced type of tests like um stateful fuzzing which you will learn much later in the course which is probably one of the most important types of fuzzing that you can do there's stat less fuzzing which we introduced a little bit here and there's even crazier type of tests like formal verification verification we do not teach formal verification in this course however we do have an assembly and formal verification course on cyer updraft that you should definitely check out if you want to learn how to turn your code into mathematical proofs crazy I know that's what form of verification is now this is a great time for you to try to write some integration tests and maybe try to get your your code coverage a lot higher maybe even try out some more interesting Fork tests and if you want to go ahead and read about some of these other types of tests because like I said the stateful fuzzing in my opinion one of the most testing methodologies you can possibly do in the smart contract world but I'm not going to walk you through doing some integration tests if you want to do some interactions. t. Soul or some integration tests highly recommend it I am going to walk you through doing this whole thing on the aoia test n however you do not have to follow along with me if you want to which you absolutely can come to the GitHub resources on cphon updraft you can scroll down and I believe we have a recommended test Nets section recommended test net yep sapoia and we have some testet faucets as well some of them with different requirements like I said depending on when you watch this we might have moved over to Virtual networks but I'm going to walk you through doing this whole thing you do not have to do this with me but it's a good idea to follow along to really see kind of this process end to end so for those of you who are looking to really go above and beyond this is your current code coverage go ahead and try to get this much higher especially with maybe some of your scripting maybe some of the interactions in particular these are all part of the smart contract World well obviously except for this mock down here these are all part of your project and even though these three scripts here aren't necessarily part of your contract they are important to the overall health and the overall processes of your smart contract here so for those of you want to go above Beyond take this time pause try to write some extra tests yourself this will make you a better developer and I'll see you soon all right so now the time a lot of you have been waiting for let's see if this all actually works hey Patrick cool you're making us do all these tests and all this weird stuff show me this lottery show me this lottery in action let's go ahead and I'm going to show you deploying this onto a real test like I said you do not have to follow along with me but I'm going to show you anyways just so you can kind of see the whole process now I could just do you you know Forge script blah blah blah blah blah blah in here but I'm not going to do that why well because I am lazy and I want to work incredibly hard to be incredibly lazy so I'm going to make this thing called a make file which we've briefly talked about make file and I'm going to put all the commands that I want to do and I want to work with inside of this make file so this is going to be some new stuff here so if you want to just copy paste from my GitHub repo to make this make file feel free to do so or you can go ahead encode along with me the code in the make file is just to make it much e easier to write really long scripts and like I said you'll you'll see in a minute so the first we want to do is Dash include so that if you have aemv file with your like sepolia RPC URL for example the make file will automatically pull all those variables into here then we're going to do phony all test deploy and this phony thing basically just tells our make file hey these are targets that we're going to use and don't do any weird thing with these keywords Reserve these keywords to actually run the script that we're going to do here so let's go ahead and write our first Target we'll do a little build here which will be and we'll add a colon semicolon which makes this be basically a Target and we'll just say Forge build now with just this just this little bit of code in our make file I can now run make build and this is basically just running Forge build oh we're getting a an issue source file does not require specify compiler version oh yep let's go back to this sorry let's just do spdx license identify MRT pragma uh solidity 0.8.9 just to so that we don't get those warnings let's run make build again okay cool so Forge build great usually you'll have some type of test Target which will just be Forge test and we can run make test now and that will just do Forge test okay perfect and if you get rid of the semicolon you would just put your thing you put your command on a new line so if I still write make test here it still runs Forge test but most of our commands are going to be pretty small so we can just kind of put them all on the same line here okay what else do we want to do well we probably want to do an install where people if people want to use this smart contract project they can install exactly the dependencies that we need and you might have forgotten them by now because we installed kind of a lot of stuff but don't worry uh I will walk you through so we have a number of things so we want to do Forge install cyphon SL Foundry devops at 0.2.2 and this is really important as well we want to do very specific dependencies so that other people who come across this project they're not using the wrong version of one of these packages but then D- no- commit and what are what else this double Amper sand is like and for bash commands so we would run this and then we would run Forge install Smart contract kit SL chain link brownie contracts at 1.1.1 D- no- commit I'm going to do a little toggle world word wrap here so toggle word wrap in my command pet oops toggle word wrap like this and Forge install Foundry RS Forge SD at v 1.8.2 d no- commit and Forge install Transmissions 11/ soulmate at V6 D- no- commit so I know there's a lot of stuff here but now and this is why it's so good to just have these little make files here because before I would have to copy paste all this or remember how to write all this but now I can just write make install and it will run all those commands for us very nice so anybody who comes along to this repo you can say hey just write just run make install and it'll automatically install all the correct versions and dependencies for you very good all right great now let's finally do a little deploy here uh and I want to point something out in previous editions of this course and you'll definitely still find a lot of project kind of doing it like this I tried to make a lot of this make file modular so you could kind of switch between networks pretty easy and I tried to do some really clever things to do that but I'm going to almost make this less clever but like more clever at the same time just by making it easier so I'm actually going to do deploy sepolia like this and we're just going to hard code this so that if you run deploy make deploy seoa it'll deploy to sapoia before I was being really clever with it and I would do like make deploy D- Network sapoia that kind of was a lot of code and wasn't really the cleanest syntax so we're going to kind of do it the easier way for now easier way to understand easier way to teach and it's a little bit more straightforward as well so what we're going to do is we're going to run to actually deploy our codebase we are going to do this on a new line just because it's kind of a lot of things are right we're going to first do this at sign and do Forge and the reason we're doing this at sign is it's going to off escate obfuscate the output or obate the command so that doesn't show up in the terminal and that's what we want don't worry too much about what that means right now but we're going to do Forge script script deoy raffle dos. Soul deploy raffle -- RPC D URL we're going to do sepolia RPC url-- account we're just going to do default or whatever your account is here I have imported an account and called it default who I've also imported one and called it yellow so whatever your imported your remember we did that cast wallet import bit cast wall import and then the name of your account remember how we did that so I'm going to use default here then we can do das Das broadcast then to automatically verify this as well we would do D- verify and then if we have an ether scan API key we can do ether scan ether scan API key with our ether scan API key like this and then I like to add the- vvv V at the end just so that we can have um even more information so what this should do is it should deploy our raffle to sapoia and then automatically verify so I already have done uh source. EMV with my seoa RPC URL and with my ether scan API key so if you don't have an ether scan API key obviously you can come over to Ether scan pretty easily and this since we're doing spolia you can do ether scan spolia or ether scan mainnet doesn't really matter you can sign in get an ether scan API key and then just stick it in your MV so I've already done that though so in our helper config I'm going to keep keep this subscription ID because I want to use one that we've already created I don't want to have to redeploy or redo anything here and what this should do is we're not going to create a subscription because we've already added one so we're going to skip creating it we're going to skip funding it but we are going to deploy the raffle and then we are going to automatically add that consumer to our subscription basically and what we can finally do is just run make deploy sepolia and it it'll compile o exciting so now that it's kind of simulated the transaction here it's going to say hey uh enter the key Store password so we can decrypt our key to send these transactions and oh it looks like we're decrypting them and we're pending sending these transactions That's so exciting and voila we have successfully deployed the contract and we have successfully set this up so let's go ahead let's grab this contract address let's go to to sepolia sepolia Ether scan here let's paste this address in here we look at the contract it looks like it didn't quite verify correctly that's kind of annoying uh sometimes test NS have a hard time verifying contracts we could verify and publish it manually but I'm not going to bother that's really annoying but all good so okay well we've at least deployed it here can verify it later and now we can go to our vf. chain. link here do a little Refresh on our subscription here we going to connect our wallet we can now see we have a new consumer added ah very nice so we have six link in our balance we now want to go over to automation here and we're going to register a new upkeep we could have done this programmatically as well uh however we did not let's go ahead and let's connect our wallet here and now that we're connected we're going to register a new upkeep we're going to do custom logic next the contract address that is this one here that we haven't verified yet but we will and I'm going to show you the super way to kind of finally verify we're going to paste this in we're going to hit next upkeep name is going to be raffle gasm it looks fine starting balance we'll just say one check data none NOP skip skip skip register our mamass will come up we're going to confirm we are now registering an upkeep this is going to register chain link automation to automatically check our contract oh and then we're going to and then we're going to sign this as well and then close this once that transaction goes through we'll be able to see this on our chain link automation home it looks like upkeep registration request submitted successfully so now we can go home we can now see we have an active upkeep very exciting here and what I can do now is we're going to finish kind of verifying this so we can enter the raffle a little bit easier uh we're going to do Forge verify contract d-el and we're going to do kind of this nuclear option or like the ultimate option I sometimes will call it so there is this command in here called like show standard Json input it's this one right here what we can do is we can run our verify script again show standard Json input Ah that's not what I want to do run this again paste it out to json. Json and now we're going to have this file json. Json if we go to the top of it we uh we can format this document this is what's known as the standard Json and this is what the verifiers will use to actually verify a contract and we can go back to our contract here we can say verify and publish if it doesn't automatically verify we're going to do solidity standard Json input we're using 0.8.9 we're going to use MIT continue uh we're going to upload a file and we're going to upload this json. Json in here so we're kind of speedr running you through this like I said you don't have to follow along and Constructor arguments are already set up for us so all we have to do now is I'm not a robot verify and publish and this pretty much is going to be the way that if for some reason your code doesn't automatically update your code doesn't automatically verify this is how it'll do it so we see successfully generate bite code for ABI we can now click this we can now see the contract is successfully verified okay so if we're on our automation here and excuse me and we're on our let's go to vf. chain. link so if we're on our Automation and we're on our vf. chain. link we have a consumer on our vrf here we have six balance for our vrf we have our automation we have one link for our balance here if we look at our cont contract and we do read contract let's like connect to web 3 here metam mask yep if we call checkup keep with nothing with just anything in here we get bull false why well nobody's entered the lottery of course I'm now going to switch over to write contract and we could of course write a script to enter the lottery as well but I'm just going to cheat and use the ether scan here we can go ahead and hit enter raffle I'm going to do what did we set the payment as I think it was 0.01 ah okay there we go so 0.01 spoa eth looks like this is going to pass we're going to now confirm as this transaction is going through back in our read we have get recent winner which is going to be nobody the owner is going to be this get player at index zero this should error yep it sure did error because our transaction hasn't gone through yet okay looks like it just finished going through now if we hit index zero this is actually returning something now if we hit check upkeep needed oh my God it's returning true now if we go to our Automation and return let's see if the chain link nodes have caught wind of this so raffle is active looks like if we look at pending okay no upkeeps needed pause no no no no any second now the chain link nodes are going to see hey uh it's time the raffle is up and they're going to automatically pick this up and they're going to automatically kick off a chaining VR request if we give this a little refresh here too you have pending trans transactions due to low balance pending request will fail through 20 24 hours plead add funds to your subscription oh whoops uh well okay let's add some funds here so uh I'll give it 15 link this is testet link anyway so I don't care and this is where the UI is can be really helpful right kind of triaging some of these we could have done this programmatically seen it wasn't working and then had to debug it but it's definitely quicker just to hit the ad funds button on the UI sometimes might be a good idea to go and update our scripts to give more link to our smart contracts as well okay funds added now let's do a little refresh here let's see okay we have some balance for our vrf now latest fulfillment was very recent was like basically just now oh but we barely spent any eth or we barely sent any link huh okay well what about our automation here our automation went ahead and kicked off that's very exciting so if we go back to our raffle now if we go down go to the contract here we go to read contract we go down to recent winner give this page a little refresh here connect to web 3 yep yep we go down to get recent winner oh my goodness we have a recent winner and it was us so the chain link automation automatically picked up our Lottery kicked off a transaction to the chain Leake VF to get a random number and it gave us a random number and picked us a random winner and if you go to the transactions tab you can see we entered the raffle and if you go to internal transactions you can see this parent transaction hash where fulfill random words was called by the chain link VF this is so cool now even though I just showed you this I don't want you to ever never never never never never never never test on seoa or a test net or a main net without first testing locally on something like Anvil so you could also have like a deploy Anvil here where you pull up here you do like a little Anvil you get a kind of local blockchain running first and then you deploy to Anvil and you work with all your scripts on your local blockchain this should always be your default way before you even think about doing any test net tests additionally all of your tests should be Immaculate before you even think about doing test net test the test net test if you decide to do it should absolutely be the last stage in anything you're working with the test net or a really cheap main net never ever ever ever have this be your first step you are going to waste a lot of time waiting for transactions to go through you're going to the test Nets are technically a public Resource as well and we don't really want to abuse the public resources absolutely 100% be sure to do this locally before we try it out on a test net now we're just about done with this Banger of a project here but there's two more things I want to show you around debugging so we got stuck on a couple things a few times and we've used console. long before but we could have also imported console from Forge STD uh excuse me from forg stdc console. sole or console 2 right into our contracts themselves and done console. logs in our contracts so for example I could say enter raffle and I could do like console.log hello like this and then maybe console.log message. Val and now if I run like Forge test- vvvv like this and I know there going to be a lot of tests here but and I probably should have just done three these um we see hello and a zero here so we can actually do console. log directly in our contracts themselves and that's a great way to help debug our transactions you want to be careful though because if you do this you want to make sure to remove them before you actually deploy this to production or deploy this to an actual Network cuz if you leave those in it will cost gas and you don't want to have to spend extra gas where you don't have to I also spelled sample wrong there we go now one other tool that we haven't really talked about and we won't talk about until way way way later in the curriculum is this debug tool but I absolutely love it for lowl stuff what you can do is you can do you can take some test and do like Forge Forge test-- debug paste the name of a test in here and and what it will do is it'll drop you into a inline opcode debugger where you can literally go through the low-level bites of a smart contract so I can literally like see all the op codes that are happening all the lowlevel all the crazy stuff that's happening in our contract to get a better idea of exactly what is happening with memory storage call data all that good stuff we will learn about this and we will use this way way way later and if you get to the security and auditing curriculum we will definitely go over this but with that being said we learned a ton so let's do a recap of everything we learned woo sitb back all right we deployed a provably fair raffle a provably fair Lottery this is crazy exciting now you should ask the question does it ever make sense for you to play another Lottery that isn't on the blockchain ever again and the answer is no because no other lottery is going to give you the transparency of true Randomness that the blockchain is we created this Lottery contract at the top we've got a whole bunch of custom gas efficient errors including one that takes many parameters we learned about type declarations like enum that have different values that can also be wrapped as U we made some beautiful events in state variables all of them starting off as PR private and we made Getters for the ones that we wanted at the bottom so nice we have this verbose Constructor so that no matter what chain we want to deploy this contract on we can adjust the deployment parameters so that it works flawlessly additionally it'll work flawlessly if we're forking a test net if we're forking a main net Etc all we have to do to update for a different network is to add a different network config that's it we created a raffle that emits a for to make migration easier and make front end indexing easier we worked with chain link automation to automatically call our smart contracts in effect if I flip back over to our automation upkeep and I do a little refresh we scroll down we can see that it ran once because the perform upkeep was indeed met it hasn't run again because why because we have this check it doesn't have any players it can only run if it has players so the check upkeep checks if it's time for a new Lottery jaw and then perform upkeep actually kicks off the lottery jaw which kicks off a call to a chain link vrf this function call is called by an external party it's called by a group of chain link nodes for us we could call this ourselves but we're lazy we want automation to take care of it we want the decentralized chain link Network to take care of it once it kicks off the chain link vrf will respond and end up calling this fulfill random words which picks our random winner and this function we used we learned about the CI checks effects interactions pattern where we do our checks first we didn't really have any checks here then we do all our effects on the contracts and then finally our external interactions outside of our smart contracts then we have a whole bunch of getter functions this code base was really only 200 lines of code but yet it felt like it took so long because we learned a ton of really Advanced scripting and deployment methodologies so we deployed our contract using our helper config so that no matter what chain we deploy this on it's going to work flawlessly if we work on sapoia or another main net we just add the parameters in here that we want if we work on Anvil we deployed mocks fake contracts for us to interact with as if we were working on a real chain if we don't have a subscription we programmatically created one in our script we scripted in solidity insane then we started our broadcast and actually deployed our raffle ourselves and then finally we added our consumer programmatically to our vrf probably also could have added an upkeep to the chain link automation but we didn't have to do that for our testing because we could just pretend to be chain link automation ourselves we created this interactions bit so we could run commands to add consumers fund subscriptions or create subscriptions right from our command line much easier than having to work with cast we wrote a lot of unit tests however we still left some testing for you if you want to go back and level this up we worked with a mock chain link token we learned some really interesting testing skills such as being able to capture the event outputs to use them later in our test skipping a test based off of the chain ID we doubled down on working with modifiers we expected a revert with this ai. incode selector thing which we're still not sure what it does but we'll learn about it later we did some perform upkeep and all these other tests and then at the end of this you didn't have to do this but I went ahead and did this but I deployed this Lottery on chain onto an actual test net we funded our subscription with we funded our automation subscription with link We funded our vrf subscription with link and we saw the chain link nodes take care of all of this no problem this was a large project and we did a lot of coding here if you made it to this part of the course you should be incredibly proud of yourself and give yourself a massive pat on the back take some time right now to go on a walk do some push-ups do some pull-ups go get some ice cream go grocery shopping take a break post about this on Twitter post this to your GitHub this is an awesome project to post your GitHub by the way post to your GitHub and be excited that you've made it this far if you're in the GitHub repo associated with this course you know that we have a lot of lessons left however getting this far is a phenomenal achievement and like I was saying you have the basics of solidity knowledge down the next couple courses are going to teach you more intricate knowledge about the web3 ecosystem itself so take that break and I'll see you soon all right welcome to Advanced Foundry we're going to learn a lot of really cool stuff in this course we're going to play the best practices just to get started here in case you forget any of the best practices so be sure to watch that first this course is directly after the intro to Foundry course and it's probably one of the most important pieces to becoming an advanced smart contract developer period so let's do this all right and now we're at the section of the course where we're going to start talking about ERC 20s and tokens so you can find the code associated with what we're going through in the GitHub repo of course associated with this course now before we actually even go into building one of these I know we've actually worked with them a little bit with the link token but let's actually understand what an erc20 is what an EIP is what an ERC is and I actually have a video for my previous course which goes over this so let's go ahead and watch that before we can understand what an erc20 is or even what one of these tokens are we first need to understand what is an ERC and then also what is an EIP in ethereum and Avalanche and binance and polygon all these blockchains have what's called Improvement proposals and for ethereum they're called ethereum Improvement proposals or eips and what people do is they come up with these ideas to improve ethereum or improve these layer ones like polygon madic Avalanche Etc and on some GitHub or some open source repository they'll add these new eips they'll add these new Improvement ideas to make the these protocols better now these improvements can really be anything they can be anything from a core blockchain update to some standard that is going to be a best practice for the entire Community to adopt once an EIP gets enough Insight they also create an ERC which stands for ethereum request for comments so EIP ethereum Improvement proposals ERC ethereum request for comments and again these can be like be PE you know etc for all these different blockchains both the Improvement proposals and the requests for comments all have these different tags now they're numbered chronologically so something like an ERC 20 is going to be the 20th ERC SL EIP the erc's and the eips share that same number and there are websites like e.e. org that keep track of all these new ethereum Improvement proposals and you can actually see them real time go through the process of being adopted by the community now one of these eips or erc's is going to be the erc20 or the token standard for smart contracts this is an improvement proposal that talks about how to actually create tokens and create these smart contract tokens I made a video about this recently so in the GitHub repo associated with this course we're going to have a subl lesson and we're going to watch a quick video that explains more about these different tokens now first let's define even what are ER c20s so er c20s are tokens that are deployed on a chain using What's called the erc20 token standard you can read more about it in the rc20 token standard here Link in the description as well but basically it's a smart contract that actually represents a token so it's token but it's a smart contract it's both it's really cool tether chain link uni token and die are all examples of ERC 20s technically chain link is in ERC 677 as there are upgrades to the erc20 that some tokens take that are still backwards compatible with ER c20s and so basically you can think of them as ec2s with a little additional functionality now why would I even care to want to make an erc20 well you can do a lot of really cool stuff with it you can make governance token you can secure an underlying Network you can create some type of synthetic asset or really anything else in any case how do we build one of these ear c20s how do we build one of these tokens well all we have to do is build a smart contract that follows the token standard all we have to do is build a smart contract that has these functions it has a name function a symbol function decimals function Etc all these functions we need to be able to transfer it we need to be able to get the balance of it Etc and again if you want to check out some of the improvements that are still erc20 compatible like the ERC 677 or the ERC 777 you definitely go check those out and build one of those instead all right let's go ahead and get started here this is going to be one of our fastest lessons we're going to be building a repo or repository or a project that's going to have our own token in it our own erc20 and to get started we're going to go ahead and run the same command we've been running this whole course Forge nit oops excuse me we're going to run make di mkd Foundry erc20 f23 clear CD Foundry erc20 f23 code period or file open to open this up in a new vs code here like this then we're going to open up the terminal and run forit we're going to initialize a blank repository here now one thing I haven't actually talked about yet is this GitHub workflows this is something called your cicd pipeline and it's a way to automatically test your code in GitHub not really going to go over it but it is a popular tool that a lot of projects use so that whenever they make a change to their code the test Suite automatically runs and if the test Suite fails the code doesn't get pushed but that's beside the point anyways we have our basic setup here we're going to go ahead and delete the three of these again goodbye just so we can start from scratch now let's go ahead and create our token we're going to create our own token here and I'm going to show you a hard way to do it first and then I'm going to show you a much easier way so first let's go in here and let's create a token so we're going to do new file we're going to call it manual token . Soul we're going to do the same thing we've always been doing spdx license tab that out thanks copilot pragma solidity thanks co-pilot let's use 18 contract manual token like this now like we were saying earlier in order for us to actually Implement in erc20 all we have to do is follow the eipc token standard and if we go to the eips we can go to 20 we can scroll down and all we have to do is add all these methods that they say we need to add okay let's go down and the first method we need is a name okay so let's create a name function name public view return string Okay cool so let's go in here we'll do function name public view return string this is actually going to be a string memory and then we'll just say return manual token this will be the name of our token okay cool that's it and this can actually be pure instead of view pure got added later but okay cool we have a name symbol is optional so I'm going to skip it decimals are optional I'm going to skip it okay total Supply we need a total Supply okay great so let's do function total Supply public we'll make this pure return0 256 let's say return 100 ether so we'll say this token needs to be 100 ether big now again since slly doesn't work with decimals we probably should have a decimals function to tell users that this big number right because 100 ether is actually going to be it's going to be 1 2 3 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 we probably should have a decimals function so let's actually create a decimals function we'll copy this paste it in here function decimals public we make this pure returns 18 so we're going to tell everybody that the total Supply is actually going to be 18 oh return 18 the total Supply 100 ether has 18 decimals so we know that this big number really is just 100 okay great what next do we need okay we need a transfer we need a balance of function okay let's copy the balance of function let's paste it in here zoom out a little bit and let's turn on toggle word rep okay function balance of address owner public view returns their balance so how do we get their balance well we probably should have a mapping somewhere to map people's address to their balances so let's go ahead and do that the top we're going to do a mapping of address to U into 256 called balances or this should be sore balances and we'll make this private balances and we'll say return sore balances of the owner and now you can see just from adding this little piece here someone's balance is really just some mapping in this token contract right that's it like somebody has just assigned you know if I have 10 tokens in this mapping just going to be my address is assigned to 10 tokens right that's it so holding tokens of an erc20 just means you have some balance in some mapping in the contract that's really it right so we can keep going there's a transfer function right we could actually do this out and everything oh and yeah we could probably do instead of a function stuff like this we probably could just do string public name equals manual token right because if we do a string public like this it's the same as creating a public function like this so we could 100% do this so either one is pretty much the same there's some gas tradeoffs but I'm not going to go into those now we could then create a transfer function we do function transfer we would say addressor 2 you went to 256 amount so will be a public function and we would say something like first we would get the U into 256 previous balances previous balance equals balance of from plus balance of two it's be previous balances actually if we're going to say from is going to be message. sender so previous balances of both of them and then balance of is actually a public oops I'm sorry this should be like this we're going to get the previous balances we'll say balance of from we're going to do this minus equal meaning we're going to subtract this amount from them and then the balance of two is going to plus equal that amount and then we're going to do require we're an assert require uh balance of from plus balance of two equals previous balances or something like that right oh instead of from it's going to be excuse me message. sender message. sender right so it's gonna be something like that and then bounce of oops this should be parentheses this more parentheses oh I just did all the wrong parenthesis oh we actually can't do this so hold on S underscore balances there we go this is how we should do it there we go so we're going to assign those mappings now we can keep just ripping through the rest of these functions and adding them ourselves and we could 100% totally do that or we could do what most people do and just use an already deployed already audited already ready to go contract so one of the most popular Frameworks out there is this open Zeppelin contracts project so if we go to the open Zeppelin documentation we go to products go to contracts start coding they actually have a ton of contracts that we can actually use and just copy paste into our code they also have this really cool wizard which allows you to make contracts really easily yourself right if you wanted to make a token in erc20 some governance some other Custom Contract they have a wizard that automatically allows us to create these much easier so instead of me making me randomly me implementing the token myself what I'm going to do is I'm going to say we're going to make a new token called our token. soul and in here same as always spdx license identifier MIT pragma solidity like that contract our token like this and we're going to install open Zeppelin contracts and the way that we do that is let's go to their GitHub open Zeppelin so I'm going to copy this bit open Zeppelin slop Zeppelin contracts when we install open Zeppelin to make sure we're working on the exact same version of open Zeppelin that we're working with for this video here we're do Forge install open Zeppelin slash open zeppin Das contracts at V 5.0.2 and same thing as always if we go to the GitHub resources here and we go to the actual token contract here we can go into the gab repo you can look at the make file to make sure that you're working with the versions that we want to be working with uh for this video here so be sure to check out the install Target in the make file to make sure you're working on the correct versions here opens up one SL opens up contracts oops and I got to do D- no commit all right cool it has been installed if you accidentally install the wrong version you'll have to run this remove command that is also in the make file in the GitHub repo now in my lib I have this op up when contracts contracts and if we scroll down in here to token we can see in this erc20 folder they have this erc20 doou which is already implemented for us huzzah another one that we actually worked with before was soulmate Transmissions 11 soulmate this is another fantastic repo I recommend checking out if you're looking for another fantastic fantastic package with a lot of contracts already built for you but now that we have this contract we can just go ahead and import it and inherit it so first we're going to need to go to our founder. though do some remappings we say REM mappings equals at open Zeppelin slash oops open Zeppelin equals lib slopen Zeppelin contracts and now in our token we can just do import atop Zeppelin contracts toen erc20 erc20 soul and we can just have our token inherit everything from this erc20 Soul which already has everything implemented so we just say our token is erc20 and now this erc20 doou has a Constructor right where it takes a name and a symbol and remember if an inherited contract has a Constructor we need to use that in our Constructor so we could say Constructor Constructor we'll do a u 256 initial Supply and we need to pass the erc20 Constructor and we got to give it a name let's call our token let's give it OT as a symbol and then what I like to usually do is most of these come with a mint function an internal virtual mint function and I just like to Mint the original sender that initial Supply so mint message. sender the initial Supply cool we can test this out with a forge build of course see if all of our stuff is working and it's indeed working great so now we'd want to write some tests and we'd want to write some scripts to deploy this as you know we probably want to work on our script first so let's go ahead deploy our token. s and this isn't going to need a helper config right because our token is going to be exactly the same no matter what chain we deploy it on right there's no special contracts that we need to interact with oh and this should be our token. s. there's no special contracts we need to interact with there's nothing really particular we need to do that requires a config so we're just going to ignore that step just going to make our code a lot smaller but let's go ahead and make some deployment scripts so 18 contract deploy our token is script so let's import script script from forg STD script. Soul let's create our function run it's going to be external like this we're going to need to import our token from do SRC our token. like this and then our run we're going to need to do vm. start broadcast this new our token and we'll give it some initial Supply so let's do un 256 public constant initial Supply equals 1,000 ether so we'll deploy our R token with that initial Supply because our token takes an initial Supply and then vm. stop broadcast boom like that all right cool we could make this more robust by changing the deployer key kind of like what we saw before using the environment variable but for this one we're just going to make it real basic here boom this is our script and now we can do a little cheesiness and we can either copy from our last project or copy from the git repo associated with this course we'll make a little make file we'll go to Foundry erc20 f23 we'll go to this make file and we'll just kind of copy some stuff so let's just copy the whole thing actually yeah you know what yeah copy the whole make file no reason to not paste it in here oh actually don't need this verify thing and I should just be able to run make deploy oh we're getting an error so we'll run make Anvil cre a new one make deploy P run successfully script run and we were successfully able to deploy to our envil chain okay great so what about some tests let's write some tests now for a lot of these more basic contracts especially like this our token we can actually use AI to get jump started right and I want you guys to use AI to get jump started and use a to help you learn I don't want you to use it to substitute learning oh and oh my goodness I almost didn't do a named import that would have been embarrassing I want you guys to use AI to help you learn not to substitute learning because if you substitute the learning with the AI the 10% or the 5% of the time the the AI gets it wrong you're going to have no idea how to fix it it's really important that you still learn all these Concepts because AI is still going to get a lot of things wrong but AI is usually pretty good at writing tests so let's start writing some tests and we're not going to write all of the tests we're actually just going to write a couple and then we're going to see if our AI can autocomplete it for us so let's do our token test. t. let's make some really basic test stuff here spdx you know the drill ragma solidity contract our token test is test which means we're going to need to import test from forg STD test capital. Soul okay we're going to need a function setup which will be public we're going to need our deployer here like this we're going to import deploy our token from dot dot slash script slash playy our token. s.o like that and our setup oh we probably want our script to return our token right so we're going to say our token OT equals new our token return OT returns turn Okay cool so now at the top we're going to want to import our token as well from do slsrc our token. soul at the top we're going to want to do an hour token public OT yeah our token now we're going to do we'll make a deployer as well deploy our token public deployer say our token oops no sorry deployer equals new deploy our token our token equals deployer run thanks get up copilot and that's pretty much all we're going to need but let's also make some addresses so that we can interact with people so we'll make an address Bob equals make ADR Bob and then address Alice equals make a drr Alice so we have a bob we have an ALICE we'll have the two of them play around with blowing and working with tokens the owner of our token should be the deployer so let's do bm. prank address deployer and then let's do let's transfer some tokens to Bob to get started so we'll say our token. transfer Bob and then let's do a little un 256 public constant starting balance equals 100 ether so we'll give Bob 100 ether and we'll do a little test do function test Bob balance public assert equal starting balance it's going to equal to our token. balance of oh all right let's test this test- m test Bob balance oops Forge test transfer amount exceeds balance the actual owner is message that sender not the deployer sorry so now let's do this again and hoay okay that looks cool great so that's one test let's write a couple more tests and then let's try to see if AI can do it for us so so let's even just write just like test allowances so we'll say function test allow and says public now something important about ER c20s is that they have this function called transfer from and this is a really important function we saw it a little bit in the last section but if I want my contract to keep track of how many tokens it has from you it needs to be the one to actually transfer the tokens from you to itself in order for it to take the tokens from you you need to allow it to do that right if we just allowed anybody to take tokens from anybody that would be really bad so these erc20 tokens if we go to the back to the standard they have this thing called in the transfer function you can actually read about it here the transfer from method is used to withdraw workflow allowing contracts to transfer token on your behalf this can be used for example to allow contract to transfer tokens on your behalf and or charge fees for sub currencies the function should throw an issue unless from has deliberately authorized the sender of the message via some mechanism and this is this allowances thing and you'll see on most uis on most applications you need to approve the contract to pull your tokens first and sites like etherscan.io have a beta tokens approval section where you can actually connect your contract connect your address connect connect and you could see oh let's switch to eth mainnet and you can see all the approvals that you have I don't have any on eth mainnet on this address again because this is my dummy address but it's usually a good practice to see what these approvals are and then revoke them especially if you don't trust the contract because if you approve a contract to do transfer from on whatever they want then they could just steal all your money right it's a good idea if you're making your own token to make sure allowances work well so we're going to write a real quick test on this so we'll say un 256 initial allowance we're going to say test allowance Works terrible test name but whatever it's just a dummy test allowance equals just say a th all right now we're going to say Alice proves Bob to spend tokens on her behalf let's close this so we're going to do vm. prank excuse me Bob Bob approves Alice spin tokens so we'll say vm. prank Bob and we're going to run our token approve Alice initial allowance and if we go to our token if we could command click or control click into the erc20 and we look up approve there's this approve function which has this inner function approve where if we command click or control click on that we update this allowances mapping and if we go to our transfer from function in here let's just look around for it here it is we see that it calls this spend allowance function if which if we look at that one it requires that the current allowance is greater than whatever amount that you're approving whatever amount they're spending so you have to explicitly approve other people to use your tokens and you don't actually have to approve anything sometimes right you don't have to approve anybody to use your tokens and that's probably the way you ideally want it but sometimes you do if a contract wants to keep track of how many tokens that you've sent it for example so we're going to prank Bob we're going to approve Alice to use our tokens and what we can do then is we're going to vm. prank Alice and now she is going to take our tokens from Bob because Bob approved her to do so so now we're going to do our token. transfer from and we're pretending to be Alice here transfer from Bob we're going to say from Bob to Alice and then we're going to create some transfer amount do like un 256 transfer amount equals let's do half of the allowance that transfer amount we have to do this transfer from function if we were to do just transfer transfer if you do just transfer whoever is calling this transfer function automatically gets set as the from so if you call transfer it automatically sets the from as whoever's calling so that's the difference so transfer automatically sets the from as whoever is sending the message transfer from you can set anybody from um but it'll only go through if they are approved that doesn't make sense ask questions in the GitHub repo now we can do a little assert equal our token. balance of Alice is going to be that transfer amount right because she took it from Bob and then oops yep and then assert equal our token. balance of Bob is going to be that starting amount starting balance minus the transfer amount trans there we go let's spell this right and let's run this test Forge test- M paste it in you can tell that I've written Forge test DM a billion times and it does de pass okay right so if we do Forge coverage we're going to get hey you got barely anything covered yep sure we have barely anything covered so I actually wrote and we want to write some more tests for this now tests are something that AI is actually very good at doing and let's go ahead and actually practice sending chat gbt or any AI a prompt to actually generate some tests for us if you want in The Foundry erc20 f23 we've got a little prompt for you to work with if you want to just copy paste it so I'm going to copy mine bring it over here paste it in but I'll tell you what it says it says here's my solidity erc20 token and we literally paste it in the token that we just created and here are our first couple of tests written in so we wrote those couple of tests in here can you write the rest of the tests please include tests for allowances transfers and anything else that might be important and let's see what it gives us and we get an output looks something like this so we can go ahead and grab this and stick it under a test and see what happens so I'm going to go ahead and copy it and I'm going to paste it and I'm going to highly recommend you don't just blindly copy paste code from chat TBT that is a very quick way to accidentally get wrecked if the AI gives you a bad answer I've already read through this so we're going to be good to go but you'll notice it it already did a couple of weird things to us so it removed the import deploy our token from our deploy script and so I have to add that back in setup looks okay it also removed Bob and Alice it did some other weird tests so I'm actually going to not blindly copy paste it I'm actually going to undo that copy paste and what we're going to do is instead we're going to be a little bit more intelligent with how we work with AI so I'm just going to take the stuff that I want out of here test allowance I like our test allowance test transfer okay we'll grab that test balance after transfer okay test transfer from sure let's grab those and see if those are good tests test transfer automatical 100 gives us a dummy receiver R token. transfer receiver amount 3 equals R token. balance of receiver is going to be amount that's a good test test balance after transfer it's going doing another transfer and testing our balance okay so that's pretty good and then test transfer from it's doing some approve it's doing an approve and a transfer from on itself so that's like redundant this isn't a great test but whatever let's see how it did Forge test and we have some issues because of course we do so we get test balance after transfer this one fails why does this one fail let's do Forge test- M do that specific test we'll do with some- VVS in here and we can see transfer amount exceeds balance why does this fail because we're not vm. pranking the message. sender so we got to do that vm. prank message. sender and we're going to have to do that for everybody test transfer from bm. prank vm. prank although this is definitely redundant okay no that actually works we'll VM prank the message sender we'll proove address this and we'll do that that one looks good this one's going to need a VM du prank okay let's try this again Forge test couple of these still failed test balance after transfer failed ah it's cuz we're getting the address of this we need to get the message. sender so it should be the balance of message. sender instead but you can see as I refactor this that AI can be helpful it gave us the scaffolding to a lot of this but we're still having to go back and redo some stuff and this is why it's so important for us to actually understand what's going on still get so much wrong we got an insufficient allowance down here so our token approving address this amount our token to transfer from address this to receiver we would need to transfer from message. sender now that should be most of it Forge test and great now all of our test passes and they actually pass and they're actually doing some coverage right it's not perfect so if we run Forge coverage it's definitely not perfect in fact it barely did anything but it did more tests for the erc20 but we could go back to chat gbt and say hey great job can you write some more tests give it some more prompts Etc but you can see that at least it can be very helpful in getting you started getting you going right tests if you haven't before and of course if you want to actually deploy this to a real Network you would do what you would put your EnV your private key or you use third web deployer something and you deploy to a network so that's it for this lesson I know this was a quick one congratulations I know this one felt a lot quicker and easier than the last one because now we're getting more advanced now learning actually becomes easier now that we have a solid foundation beneath us so take a break get some coffee get some ice cream and I'll see you in the next one all right welcome back to the next lesson in this course you're getting closer to being able to go out in the world and actually be a solity developer and know what you're talking about this is incredibly exciting got a couple more lessons coming up we have our nfts then we're going to go into defy well all of this is defi upgradable contracts governance and then a brief introduction into security and then we can send you on your way to go start being a successful smart contract engineer in the space so for our nft project let me do a quick overview of the code base that we're going to be going over and what we're actually going to be building so here's the code base in my VSS code here and what we're going to be doing is we're going to be creating nfts of these dogs and we're going to be creating Dynamic nfts that actually can change and have their values change and we're going to learn everything about what an nft is why they're special and what they do and when we're finally done here when we go up to our metam mask we'll actually be able to even import our nfts and see our nfts right in our metamask now we're going to make two kinds of nfts we're going to make first off a basic nft which is just going to be this little dog this little pug stored in ipfs and then we're going to make a more advanced nft where the entire nft is actually stored 100% on chain truly decentralized and we'll learn a little bit more about the difference between those very soon Additionally the SVG on chain will change depending on some state that we give it this is going to be our mood nft so it's going to change based off of our mood at the moment so these are the two types of nfts we're going to see and we're going to be able to populate them into our metamask which right now it's completely empty then we go to a platform like openc and actually start selling our nfts or interacting with our nfts or doing whatever we want there so and then we're also going to be finally teaching you all about what this ABI en code with selector that we saw earlier and and that weird function selector thing that we kept hearing about we're going to finally learn what those do so strap in let's get going and let's first learn about what an nft even is so I made a video about nfts a while back for those you who have never heard of an nft let's jump in and learn what those are we're going to watch a portion of the previous python edition of this course where I explain nfts from a high level and then of course we're going to get into the ultimate nft tutorial so let's learn about nfts look nfts are hot right now nfts also known as ERC 721s are a token stand standard that was created on the ethereum platform nft stands for non-fungible token and is a token standard similar to the erc20 again erc20 is like link a maker all those goodies that are found on the ethereum Chain an nft or a non-fungible token is a token that is nonf fungible this means that they are starkly unique from each other and one token isn't interchangeable with any other token of its class a good way to think about it is $1 is interchangeable with any other dollar $1 is going to have the same value of another dollar those are fungible tokens that's like er c20s one link is always going to be equivalent to one other link by contrast is going to be nfts those of you nerds out there would know like a pokemon would be a good example of an nft your one Pokemon is going to have different stats different move sets and isn't interchangeable with any other Pokemon or maybe a more relatable one is like a trading card a unique piece of art or the like so that's what these nfts are they are nonf fund non-interchangeable tokens that for the moment are best represented or thought about as digital pieces of art that are Incorruptible and have a permanent history of who's owned them who's deployed them Etc now like I said nfts are just a token standard so you can actually make them do much more than just be art you can give them stats you can make them battle you can do really unique things with them you can do pretty much whatever you want with them but right now the easiest way to think about it and the most popular way to think about it is by calling them a Ot Ot it's OT or some type of collectible or just anything that's unique so like I said they're just tokens that are deployed on a smart contract platform and you can view them on different nft platforms like openc or rable and these are the nft marketplaces that let people buy and sell them you obviously can do that without these marketplaces because it's a decentralized but they help and give a good user interface now like many of you out there my initial thought to nfts was okay this sounds pretty dumb but I think that that was dumb I think art does have a lot of value and I think that artists are not always paid fairly for what they do and this is actually a huge issue right now in the modern day world where an artist can make some type of art people just copy paste it you know everywhere and uh and they never get attribution for what they made so having a really easy decentralized royalty mechanism or some type of mechanism where these artists can get accurately comped for what they're doing I think is really important I love music I love movies those are pieces of art that I digest and I really like and I think it's fair for them to get comped appropriately cuz they are providing value to my life I think nfts are a great way to solve this issue as kind of having these decentralized audit trails and and royalty trailers that we can set up and and see really transparently without having to go through some centralized service so that's the basic gist of it let's talk some more about the standards the ERC 721 standard or the nft standard this is the basis of it all there is another standard that's semi fungible tokens the 1155 we're not going to talk about that here but you can check it out the main differences between a 721 and an erc20 on erc20 is they have a really simple mapping between an address and how much that address holds 721s have unique token IDs each token ID has a unique owner and in addition they have what's called a token URI which we'll talk about in a minute each token is unique each token ID represents a unique asset so since these assets are unique and we want to be able to visualize them and show what they actually look like we need to define those attributes of the object if it's a piece of art we need a way to define what that art looks like if it's some type of character in a game we need a way to define that character's stats in the nft this is where metadata and token Uris come in so if you know anything about ethereum you know that sometimes gas prices can get pretty high especially when it comes to storing a lot of space it can get really really expensive so one of your first questions might be well are they storing these images and and these R pieces on chain and the answer is sometimes back when they were coming up with nfts and artists were deploying stuff the e and the artists were like yeah art let's do that art I'm just going to deploy this one megabyte image onto the ethereum chain and oh God it's so much gas expensive how do I hit the delete button how do I it's not um it's not delet and they realized that if they put all this art on chain it was going to be incredibly expensive so to get around this what they did is they put in the standard What's called the token URI this is a universally unique indicator of what that asset or what that token looks like and what the attributes of that token are and you can use something like a centralized API or ipfs to actually get that token URI typical token URI has to return something in this format like this where it has the name the image location the description and then any attributes below there is often this talk of onchain metadata versus offchain metadata because it is so much easier and cheaper to store all your metadata offchain a lot of people will use something like ipfs that is decentralized but does take a little bit of centrality to keep persisting but they can also use their own centralized API however obviously if that goes down then you lose your image you lose everything associated with your nft because of this most nft marketplaces actually can't and won't read off onchain attributes or onchain metadata because they're so used to looking for the token URI obviously if you do offchain metadata you can't do anything really cool or really interesting or have any games with your nfts for example if you wanted to create an onchain Pokemon game all your attributes would need to be on chain in order for your Pokemon to interact with each other because if it was offchain then that becomes a lot harder to cryptographically prove so if you're new with nfts and you're like wait this is kind of a lot of information I'll make it easy for you if you're looking to render an image of an nft add your image to ipfs add a metadata file pointing to that image file on ipfs and then grab that token URI and put it and set it as your nft the chain link D and D article does a great job of walking you through this and showing you how to do this so be sure to read that if you're looking to learn how to do that we're not going to cover that in this video but we will be deploying our first nft with some onchain attributes again having your attributes on Shain is really going to allow you to build really creative nfts that build games or have interesting properties and and really makes the authenticity of your nft guaranteed because those attributes are always going to be on chain all right great so now that we know what an nft is let's begin to work on the full code and remember and again for those of you who want to follow along you can come on down to the course and find all the git code associated with this lesson and like I said earlier we're going to be deploying our first nfts and learning some incredibly Advanced pieces of solidity as well and some lowle functionality so let's begin so same as always mkd Foundry nft f23 let's open that up code boundary nft f23 or file open folder boom blank vs code here we go pull that terminal back up let's close the Explorer there Forge nit brand new blank folder all right cool boom boom boom let's remove these three goodbye goodbye counter. get ignore okay EMV is in here we're going to add broadcast as well okay great now let's start to create this nft like we said in the video it's really just a token standard just like the erc20 the nonf fungible token standard so same as the rc20 what we could do is we could walk through all of the these functions and Implement them ourselves or we could just use once again our favorite package open Zeppelin so if we go to the opens up on contracts we go to contracts we scroll down they have a token folder with an earc 721 in here and erc721 doou with most of the functionality that we need already in here so let's go ahead and use this instead of having to rewrite all these functions out so in here we're going to go ahead SRC new file basic nf. soul and you know the drill spdx license identifier MIT pragma solidity 0.88 contract basic nft like this so let's go ahead let's install this open zeppin contracts so if we scroll up we're going to install open Zeppelin SL opens up contracts Forge install opens up/ opens uper contracts D- no- commit great and now that we have that we're going to go to our Foundry doomo we'll do a little bit of remappings equals at open Zeppelin SL SLC contracts equals lib slopen Zeppelin and I'm going to do a toggle word wrap open Zeppelin D contracts SLC contracts like that okay cool so now we should be able to use open zpp H in here so we'll do a little import at oh even autop populates a little bit opens up on SL contracts token ERC 721 erc721 doou that and then we can say our basic nft is erc721 we will get a little red underscore here saying no arguments pass to the base Constructor if we command or control click into this or just go to this folder up here we scroll down to the Constructor we can see it takes a name and a symbol so because of that we're going to have to copy this create a Constructor boom and then also use the Constructor of the nft basic class be or actually we're going to call this dog instead of basic nft this is going to be doggy boom like this okay cool so what do we need to do now that we have this are we done well no not quite right we didn't Define what this is actually going to look like we didn't Define how to get this there's a there's a bunch of things we didn't quite finish doing yet so let's add our own token counter just so that it's very easy for us to tell which number is which and if we go back to this erc20 token standard there is a balance of function but remember these are unique even if I have 10 nfts of a collection those 10 nfts aren't necessarily all worth the same so there's this owner of function where we pass a token ID when we launch this doggy erc20 contract it actually represents an entire collection of doggies and each doggy in this doggy basic nft collection is going to get its own unique token ID so unique nft is a common of the contract address which basically represents the collection and then the token ID so for us we're just going to have a token counter represent each token ID right so we're going to say un 256 private sore token counter opens Zepp and also has a built in plugin for this but we're just going to roll with our own and right when we deploy this contract we're going to set s token counter to zero right because this is going to be a storage variable and we're going to update it a lot every time we minted a new dog we're going to update this token counter right okay cool so now let's learn how to actually mint ourselves one of these puppies so we're going to say function mint nft public like this and this is going to be the function we're going to do to do so now if we scroll down to the bottom of the ERC EIP 721 section we will come across one of the most important functions in the EIP 721 which is this token URI what's crazy about this is this was originally considered an optional parameter so a token U stands for a token Universal resource indicator excuse me uniform resource identifier and a URL on the other hand like what we see up here in the browser is a uniform resource locator we can kind of see the difference between the two right here a URL provides the location of the resource a URI identifies the resource by name and the specified location or URL you can basically think of this as a URL but the difference between a URI and a URL are slightly different but this token URI actually is an endpoint some type of API call hosted somewhere that's going to return the metadata for the nft and it's going to return an object that looks just like this it'll have a title A type some properties Etc and it's this that defines what the nft looks like so for us to create this nft each token counter each token URI is going to need to have this URI that points to what it should look like okay and if that's a little bit confusing don't worry we're going to explain it as always so why don't we do this first we're actually going to skip this mint function and just go right down to function token U so the ERC 721 has has a in open Zeppelin has a token U function that looks like this so we're going to override this since it's got the virtual keyword so we can override this and write our own token URI function whenever you want to look at what an nft looks like it's this function that they're calling so we can actually see any if we go to open C you can really go to any popular nft I'll go to pudgy Penguins for example we'll select any pudgy penguin I'm just going to pick the one on top we can go down we can go to the details contract address for this we can see the token ID is 1378 go to pudgey Penguins we'll go to the contract we'll go to read contract connect to web 3 sure sure scroll all the way down to token U and I'll put in that token URI I'll hit query and then we get a response back that shows an endpoint that should return that metadata and if we copy that we paste into the browser we indeed see we get some raw data that looks like this with all the traits of this nft and then we also get this image section which has this PNG where if we put that in the browser we do indeed get what the image what the penguin actually looks like so this is hosted on ipfs we'll learn what ipfs is in a little bit okay great so let's do this token URI bit so the token URI needs to have a u 256 token ID past and this is going to be a public view we need to override the Base Class implementation and it needs to return a string memory right because it needs to return if we go back to the Pudge penguin it needs to return a string like this now in V1 in with our basic nft we're also going to use ipfs and then in our second nft it's actually going to return a URI that's completely hosted on chain crazy I know stay tuned string memory okay so what we could do in here if we wanted to just have all of these be exactly the same we could say like return and I could even copy this if I wanted to return and just boom paste it in like that and now all of our dogs are going to have this pudgy penguin nft token URI right we don't want that we want to have our own metadata so for your convenience I already have a couple of images that we can borrow so if you come to the GI Hub repo associated with this lesson go down to images we go to dog nft you can feel free to pick the puppy that you want to use for your project the Pug the shba Inu maybe the St Bernard they're all so adorable it doesn't matter I'm just going to pick the Pug because that's the first one I'm going to save this image I saved it to my downloads I'm going to come to my files in here I'm going to create a new folder IMG which stands for image and I'm going to drag and drop this image in here or just paste it in there whatever you want to do now that we have this image in here we can use this we can use this to get our token U for our basic nft and there's a couple of different ways that we can use it but first we need to understand what ipfs is and how it actually works now let me explain a little bit about how ipfs works it's this distributed decentralized data structure that's not exactly a blockchain but it's it's similar to a blockchain there's no mining though but there is pinning data you can add data to this so let me explain how this actually works and you can read how this works on the site there's going to be a link to this in the GitHub repo associated with this course but let me give you my basic take on it so we have our code or or our file or whatever it is right we have some piece of data now as we know when you really have anything you can hash that thing you can hash that data right and you can get a a unique output so and that's actually the first thing that ipfs does it hashes our data to get a unique hash that only points to that data yes a massive code file a ton of text yes you can encode all of that into a single hash function your ipfs node does this hashing for you and every single ipfs node on the planet has the exact same hashing function kind of like a blockchain right they all kind of run this same spec the same specification so we can hash our data on our ipfs node and get this unique output what we can do then is we can then pin that data or pin that code or pin that file or pin that whatever to our node we have some data we get a unique hash of it all it does is Host this data and have these hashes that's it our node is connected to a network of other ipfs nodes so there's a massive network of people running ipfs nodes they're incredibly lightweight way lighter weight than any other blockchain node and they all talk to each other so if I ask the network hey I want to get this half all these nodes would talk to each other and eventually they'd reach up at our node saying oh I found a node that has that hash here is the file associated with it now you might be thinking okay well that's kind of centralized because we have the data on one node here right well you're right well here's the thing what other nodes can do is they can say oh that data looks really cool I want to have that persist what they can do is they can pin your hash they can pin your data and they'll get a copy of your data on their node and you can keep doing this and so you easily allow an entire network to easily replicate any code or any data in a decentralized sense and they're incredibly easy to spin up and they're incredibly easy to work with something about ipfs that makes it drastically different than a blockchain is they can't do smart contracts there's no execution it can really only store it's just decentralized storage that ipfs can do now the issue here is that in order for our data to really be decentralized another node does need to pin our data right because if we're the only ipfs node that's got this hashed it's kind of centralized on our node if our node goes down that data is gone and the network won't be able to access that data anymore so we'll talk about strategies in the future about having other people pin your data but for now this is a way we can host data we can send code and have it be in a decentralized context so unlike a blockchain where every single node in a blockchain is going to have a copy of the entire blockchain ipfs nodes get to optionally choose which data they want to pin and they can't do any execution so you could have an ipfs node half a megabyte and you could have an ipfs node that's several terabytes it's up to the node operators how much data and what data they want to pin now that we know about ipfs let's actually deploy our wonderful application to ipfs so that anybody can use it and anybody can connect to it so long as our node is up are you ready okay get excited here we're first going to do this kind of the manual way because I'm going to show you how to install ipfs and work with ipfs hit get started there's a number of ways to install and work with ipfs you can get it with a desktop application get a command line and then we can also add ipfs to our browser if you're using something like Brave or I think Firefox 2 some of this ipfs router is automatically built in but but if you're using something like Chrome you might have to add a little companion because what we want to do is we can actually use those little hashes as URLs for websites right and so we want to be able to put that URL in our browser and connect to that node or that piece of code so what we're going to do is we're going to have you install the ipfs desktop so you're going to hit that and when you do that you should be able to open up ipfs now if you install it you might get this little guy this little box here in your upper section otherwise you might be able to open it up with with ipfs desktop and see it as a a regular desktop app once you install it you might see ipfs is running you can restart stop you can do all this stuff we're going to go to the file section and we're going to get a little popup that looks like this now I've got a ton of stuff in here because I've been using ipfs for some time in here right now you might have no data so let's just go ahead and import some file and maybe for now we'll just import you know our next. config.js right it doesn't matter just import something and now in here we have this next. config.js or whatever file you imported so what we can do with this is we can actually copy the CID and we can view this in our browser so if we do ipfs do do slash and we paste it in we hit enter we can give our browser access to actually rendering ipfs URLs if you're using Brave you can just do use a brave local ipfs node or let's go ahead and download this ipfs companion so we'll hit get ipfs companion there's a Firefox install for Chrome Brave blah blah blah I'm so I'm going to go to the Chrome Store to get it for brave we're just going to hit add to Brave ADD extension but once you download it you'll get something that looks like this even in our little browser companion we can see like import we can see stuff about our node if we click our node we'll see a very similar setup but now that we have the companion in our browser we can copy that C ID that hash now Brave we can just do use Brave local ipfs node and will'll automatically get dropped into the file now if ipfs companion doesn't work for you and you can't see the URL inside of something like Google Chrome or some other browser what you can do is you can use something called the ipfs gateway Now using a Gateway you're not actually directly requesting the data through ipfs you're requesting the data through another server which is requesting it through ipfs but if you are having some trouble accessing these files you can use the Gateway so what you'll do is you'll do https SL ipfs.io slfs SL and then paste the hash code there and you'll be able to see your file now if you do it like this you won't even need ipfs companion at all now that we've learned more about ipfs and the token URI we can actually go to a Marketplace like openc and actually see this for ourselves openc is a Marketplace for selling nfts and if we scroll down we could go to really any nft like for example the pudgy Penguins here we could scroll down really pick any nft and look at it here and we go to its onchain details let we click this we can see the source code of this and if we scroll to read contracts let's connect to web 3 yeah sure yep we scroll all the way down and we click token URI of which ID was this 4785 grab that paste it in here we'll get this back and if we copy that paste it up here we can see this metadata object similar to what we were looking at before it's got some attributes it's got description and then importantly it has this name piece here if I copy this and paste it we can see what the image of the nft actually looks like now important note they're using ttps ipfs.io which is okay because they're still using this ipfs they're still using ipfs but if the ipfs.io website goes down this would render nothing so ideally when you're using ipfs you use this syntax where you do ipfs col slash and then the hash because this starting your URI with this will point to the ipfs network as opposed to using this will point to the ipfs website so this is a centralized website if you start with http PS ipfs.io This is pointing to the ipfs network which is a distributed decentralized Network so they're definitely different here the reason a lot of people do this though is because not a lot of browsers actually support ipfs so this is HTTP and anyone can view it in their browser but we could also use the ipfs.io of this so I can even just grab this hash here I could do ipfs colon slash paste the hash in here and since I'm using Brave I can actually see this penguin folder in here and I can see all the different pieces that go in this folder and then I would do penguin 4785 let's 4785 boom and I can see this right off of ipfs now this only works for me because I'm using Brave with a builtin local ipfs node if you're using Chrome or Firefox or something like that you can grab ipfs companion add to Brave or you can just go to the ipfs site ipfs here install ipfs desktop and then I could pull up my ipfs UI and what I could do is I could once again grab this ipfs hash copy it paste it into my ipfs UI and once again I'd see the penguin folder see there's 3 gigabytes in there we could scroll through the folder and look through the files again so you don't have to download the ipfs extension if you don't want to however it is a nice thing to have in your browser because a lot of projects do use ipfs and it's much easier to render them if you're using that ipfs companion if you're using Chrome or something or just use Brave browser because Brave browser comes with a built-in ipfs node and the other thing is once you get your own image what you could do is either in your own ipfs node in your browser or you could then upload this image to your ipfs node and get the hash and use that as the image URI for your own nft but if you want to make this a little easier on yourself for now for now we can just go to Foundry nft 23 let's go to script I know we haven't written this yet but we go to interactions. s.o we copy this ipfs hash we copy this ipfs URI paste it into the browser and if you do have the ipfs node working then you'll be able to actually see it like so this is going to be the metadata for the pug that we're going to use when you're uploading to ipfs you'd have to upload both this image and this file which on the image section has the U of the image so you'd upload the image first get the image URI of the image and then upload a file that looks like this with the image youi like in here so that we can see this little puppy but for us if you want to do all that feel free to try it out feel feel free to give it a whirl but for now we're just going to use this anyways okay back to our NFD we could just literally paste the token URI in here so that every one of our dogs would be exactly the same but let's make ours a little bit more creative let's allow people to actually choose their own token URI choose their own what each one of their tokens will look like so we'll allow them to pass in a string memory token U and then what we'll do is we'll say we'll have a mapping at the top here a mapping of un 256 mapped to string call do private sore token id2 URI where this mapping we'll get a token ID and we'll get out a token URI so we'll say sore token ID to URI sore token counter equals token U and then we're going to have to do sore token counter Plus+ like that we're going have to add one to it and then we're going to want to Mint an nft we're going to want to set the balance of this and everything in the open Zeppelin erc721 there is a saf Min function that we can actually call so we're going to call this saf Min function safe mint message. sender sore token counter so this safe mint function makes their balance plus one it sets up their token counter and a few other things so we'll have the saf Min and then down here instead of just returning some string we'll say return sore token ID to URI token ID like this okay cool so now we have this real basic nft although it's even a little bit more advanced right because anybody can mint an nft and make it look like whatever they want right and if you do mint this nft this is a great opportunity for you to play around with minting nfts that look different all right nice so now that we have this basic nft let's go ahead and write a little deploy script so we'll do deploy basic n.s. Soul you already know the drill here as well zoom in a little bit spdx license identifier ragma solidity contract deploy basic nft is script import script from Forge STD script we're going to have our function run external returns and we've done this enough we're probably going to use this for our testing as well so we'll have it return a basic nft so we're going to want to import that as well import basic nft [Music] from. SRC basic nf. soul and in here we'll do vm. start broadcast this we'll do basic nft basic nft equals new basic nft like this vm. stop broadcast return basic nft okay that looks pretty good let's do a quick Forge compile nice compiling successfully and you already know what comes next it's time for some tests but look at how fast we're going here so basic nft test.ts Soul once again same business business spdx license identifier MRT pragma solidity 0.818 contract basic nft test is test means we're going to have to import test from forg STD test. so like this in here we're going to need our function setup this is going to be public we'll make a deployer we'll do a deploy basic nft deployer say public deployer and then we'll also have a basic nft public basic nft up at the top we're going to do import deploy basic nft from slsrc script SL deploy basic nf. s.o import basic nft from SRC basic nf. what I do here deploy NF deploy basic n.s. oh not here there we go all right cool so now we're going to say deployer equals new deploy basic nft basic nft equals deployer do run looks good and let's write a test so we're not going to write all of the tests here but I do highly encourage you to pause the video after we write a couple tests here and you continue and write some of your own tests so let's start here and let's just make sure that the name is correct so the name here we have is doggy and dog let's go ahead and write a test to make sure this name is correct so we'll say function test name is correct this will be a public and I know this is going to be a view function so I'm going to do View and now here's where we run into our first issue so string memory expected name is what it's going to be doggy right that's the expected name and the string memory actual name is going to equal what basic nf. name right the open Zeppelin package that we imported if we click into it and we click into this we scroll down there's this function name down here which just Returns the name right this is a public view so we know know it has this name function that we can call so in our test we could do basic nf. name but if we do assert well assert equals or assert and do the equals stuff actually let's do assert we can't do expected name equals equals actual name if we do it we get this little red squiggly line that says built-in binary operator equals equals cannot be applied to types string memory and string memory and why not well remember how we said strings are special type right strings are an array of bytes they're a bytes array right and with bytes arrays we actually can't compare arrays to arrays we can only we can only compare primitive types or Elementary types like a un 256 a bull an address bytes 32 Etc right we can't compare array of bytes which means we can't compare strings since we can't compare arrays so how do we make sure these strings are the same thing well since it's an array we could do like a for Loop and loop through the array and then compare the elements of the array right if it's an array of bytes let's say it's an array byes 32 right byes 32s we can compare so why don't we just Loop through and do that well we could but to be honest that's kind of too much work for us we we want an easier way to actually compare these things now what we could do is we could do this thing called ai. code pack the entire Ray and take the hash of that remember what a hash is a hash is a function that returns a fixed sized unique string that identifies that object so if we hash these arrays that would be an easier way to actually compare the two of them we would just compare the hashes instead of looping through the array which is going to be a lot more coding and it's going to be a lot more ver both so this is something again where your whatever AI buddy you're working with will probably get this right we ask them how can we compare two strings in solidity or strings I should Spell correctly chat TBT and hopefully most AIS are actually able to get this for you hey strings are more complex types they're essentially Dynamic arrays yep and therefore can't be compared directly with equals equals so if we scroll down they're doing something similar they're converting the strings to bytes and getting the hashes of that that works too we're going to convert them to bytes using ABI and code pack now this is where I will often use a tool like chisel which comes built in with Foundry to help me get a good idea of what I'm doing makes sense right so what I can do is I can say string memory cat equals cat say string memory dog equals dog if I put type in cat I get this crazy weird output that looks like this but this is kind of the hex of this cat if you will right what I can do is I could say bytes memory encoded cat equals ai. encod packed cat and now I have encoded cat which is of type Dynamic bytes and now we have a bytes object we can actually Hash A byes object so we could say byes 32 cat hash equals could check 256 encoded cat and now we have a cat hash which is just a simple byes 32 so we can convert our strings to bytes and convert the bytes to a byes 32 and we just compare the hashes of both of those so we'll hit contrl C twice to exit clear the terminal and let's use that methodology here and I know I haven't explained this ABI do and code hacked yet but I will very soon in this lesson I promise so for now just kind of think it's magic all right but I promise I'm going to explain it very soon so what we can do is we can do assert K 256 of the ai. encode packed of the expected name is going to equal hit cheack 256 of the ai. encoded a code encode packed actual name and I'm going to open up the command pallet do toggle word wrap here like this and this is how we can actually compare the two strings by encoding them so now if I pull up the terminal Forge test- m test name is correct or just Forge test boom we get this indeed passes so this is how we can tell these two names are the same if this was something like toggy and we ran this now you're going to see that it's going to fail fails okay so let's bring it back to Doggy awesome so we have a way to actually test if these strings are the same great let's write two more tests so we'll do function test can mint and have a balance make this public let's create some user so back up at the top we'll do address public user user Make addr user like this we'll make a user down here we'll prank them bm. prank user we'll do basic nf. mint nft and this is where we're going to need to add some token URI and this is where I'm going to recommend we come over to the GitHub repo associated with this course and let's for now just grab an ipfs hash to use so we're going to say string memory actually let's just do this at the top string memory public constant pug equals paste it in here ohop sorry not memory obviously this is a storage variable and then if you want to I recommend you trying to upload your own metadata file to ipfs remember it needs to be in this Json format with a list of attributes and then the image is going to be its own file uploaded to ipfs and then you're going to take that and put it in the image section here definitely recommend you guys trying out but we have this pug we're going to use this down here mint nft pug and then we can do a little do a little assert we can say assert first off basic nft do balance of user is going to be equal to equal one and we can also do a little assert we can make sure that the token URI of this nft is this pug right so we can say assert and this is where we do the Kack 256 again ai. encode packed pug is going to be equal to a check oh it's just K I don't think it's CK 256 ai. encode fact basic nf. token U zero cool all right let's try this one let's just do Forge test let's run both tests and we did it okay awesome now we're probably going to want a way to Mint this token programmatically we could of course use cast but maybe we want to do an interactions. s.o and here you already know the drill we're going to do spdx license identifier it pragma solidity contract we'll call it mint basic nft is script import script from Forge STD SL script. soul in here we're going to have a function external oops function run external which is going to Mint our nft and we always want to be working with the most recently deployed nft so we're going to we're going to use this Foundry devops package we're going to go ahead and install this copy the URL Forge install chain Excel foundary devops D- no commit clear it out and in here we're going to say address most recently deployed equals oh we're going to have to grab this devops tool so we're say import devops tools from boundary devops SRC devops tool. soul and this is actually lib right here now we're going to say equals this this most recently deployed is going to be the devops tool. getet most recent deployment and we're looking for the basic nft I'm a block. chain ID oops this and I'm going to toggle the word w here as well and then we're going to have in mint nft on contract function where we're going to pass in the most recently deployed and I'm going to make a function mint nft on contract address contract address this is going to be a public function bm. start broadcast and then we'll take this address we'll say basic nft contract address mint nft and I'm actually going to grab this pug string from my test paste it into the interactions up at the top pug M nft pug beam. stop broadcast all right cool and I probably need to import this basic nft so import basic nft from do dosr cbasic nf. Soul all right cool so we have a way to deploy this a way to Mint this and all those goodies now there's a couple of ways we could actually see this for real right so having it in our test here is cool but I want to see it like in my metamask right right now if I go to n FS I don't see it in here so I am going to deploy this to a test net but another way we could work with this is we could deploy this to Anvil we could deploy this to our own Anvil and we could switch over to Anvil right oh obviously my Anvil isn't up right now we could switch over to Anvil and we could see it in in on the Anvil chain if you don't want to have to wait for the test net if you don't want to spend the gas I recommend that you do that but for now I'm going to go ahead and deploy it to a test net you do not have to follow along with me here but if you want to you can now once again though I'm going to make a make file just so I don't have to write out those super super long scripts here and I'm going to save the trouble if you just come to the get repo associated with this lesson you can just copy my make file instead of having to rewrite all this stuff yourself copying stuff is usually pretty good there's going to be a couple of these that don't exist yet so actually if you want to just copy everything down to the deploy go ahead and do that going to paste everything in there here it's got most of what we've already talked about we've got our deploy script which this is what we're going to run to deploy our basic nft and then let's also add a mint in here and I don't have this but we'll I will add this and this will be Forge script script SL interactions. s.o mint basic nft Network arcs and of course we should write some tests before shipping this on a test net but I just want to show you guys what this nft looks like so we're going to do make deploy args oh and actually make sure to add ourm I'm going to add my seoa key in here and my private key since I'm going to be working with my make file I don't even have to run source. EnV since the make file includes the EnV but now I can just run scroll down in my make file let's run make deploy args equal-- work poia and we're going to go ahead and deploy this we're deploying our basic nft to this contract address okay great we're going to have to wait a little bit for it to be verified all right cool after it's up we could even go see this on sepolia test net contract is verified okay very nice we could go ahead and write contract from ether scan but we're going to do it the cool programmatic way so now that we have this we're going to have our broadcast folder which is going to have our latest run in here with our created basic nft and because it's in here that's how our devops tool actually works it grabs the most recent from that folder we do need to turn ffi equals true in here ffi equals in order to run this command so what we can do now and remember anytime you set F ofi to be true you want to just double check that the package that you have is actually going to do what you want it to do so if we look in this lib Foundry devops we go to SRC we can see the actual bash script that's going to be running if I guess if you're familiar with bash you could read through this and figure this out you drop it into you could also copy paste this into something like chat gbt and say what does this code do p it in chbt and most AIS are usually pretty good at bash so it gets it right this bash script is is designed to search through Json files and a specified directory and find the latest created contract address for a given contract name on a specified blockchain sure is what it's supposed to do so and just one more thing on this devops thing so this is kind of my temporary solution to not seeing a better devops tool in the I'm going to have in here as well up at the top similar to recommended test net I'm going to have a recommended devops package so right now the one that I'm using is the one that I made but I'm going to have a recommended devops package because a couple other people are working on improvements to this so f ofi equals true now that we have all this we're going to run make deploy or excuse me make mint args equals D- Network work setola this and now we're going to grab that most recently deployed basic nft and we're going to call the mint function on it now while this is minting what we can do so we can come up to our metamask here we'll go to this contract address that we just deployed we'll copy this and once this finishes going through once this transaction finishes going through we can copy this address go to our metamask go to to nfts oh let's actually switch to spolia go to nfts we'll select import nfts and we can paste the address and then our token ID should be zero because we should be the first ones to have created this and we'll hit add and it'll wait a little bit and then we'll be able to see our nft right in our metamask we see our cute little doggy and we can do whatever we want with it you can see it's smart enough to grab this token U we can see the image here and we can see the contract address on chain we could send it we can do whatever we want with it right so we can see the nft right in our metamask and this is what we would see on a Marketplace like openc as well fantastic all right we deployed an nft we conceded our metamask this is great now there's a couple of things that we still need to go over number one what's the issue with this nft why might ipfs not be the best place to have your image stored it's better than using https and then a website but why might this not even be as good and then additionally what the heck is this ai. incode packed we've used this ABI and code function selector and code this and code that what is this well one at a time let's first answer the question why might this still not be the best place to host this data so if we host our image on a website right like you saw some of the pudy Penguins were https you saw a couple my images use https again like I said if those websites go down if you go to view that nft you're going to get nothing back you're going to get a broken jpeg link making your nft essentially well worthless right so ipfs is much better because anybody can pin this and keep that image up forever so let's actually begin to work on a solution where we can actually host our nft on a more decentralized more censorship resistant more permissionless more immutable way the issue as I was saying with ipfs is that if I'm the only ipfs node that has this data pinned and my node goes offline for example if my ipfs node is just on my computer right here and I turn my computer off nobody can have access to that file which means that if we went to my metamask or to openc we would see a broken jpeg image here right we wouldn't see anything the reason ipfs is better than centralized server is because other people can pin this right if I put this nft up and other people like this nft collection or this nft they can pin it to their own nodes but this method is so popular because it is incredibly cheap to do right it's really easy to spin up an ipfs node and pin your data to that node this method that I'm about to show you is a little bit more expensive but it's way more decentralized because all of your metadata is actually going to be on chain now here's one thing here's one thing you can do so that when you pin data to an ipfs node it actually stays up there for good what you can do is you can come to different services like pin a. cloud and actually have them pin your metadata for you so what I could do is I come here let's start building sign up I'm a builder and once we're logged in here just like an ipfs node we can hit add files choose a file and then just drop your file in here and when you do that you'll be able to get hash of each one of your projects like this one and this way you know you have somebody else at least pinning your data and whenever I'm using a project that uses some type of file in ipfs I always deploy the file to my own ipfs node and then I'll also pin it to some like pinata as well what we can do is we can use something called an SVG now I've got a tutorial on this using hard hat with your SG being 100% on chain if you want to go check that out it's going to be very similar to what we're doing here and we've got an example of a totally onchain SVG which this looks pretty ugly I know but this was a a project where I had chain the vrf create random lines to make a provably random SVG on chain so we're going to use this strategy where we're going to basically encode our image as an SVG type and this image is stored 100% on chain now this image is gross and doesn't really look like anything the images that we're going to do are going to be in this image folder Dynamic nft it's going to be like this happy SVG and that sad SVG right so a little bit more interesting so let's first understand what an SVG even is so so if we go to w3schools.com we can go to this SVG tutorial so SVG stands for scalar vector graphics and we can actually scroll down and we can see an example right in this SVG example right so this is it so it looks it's just kind of this tag where it has very specific parameters for defining what an image looks like and the reason that svgs are so cool is because no matter how big or small you make them they're always going to have the exact same quality because they are scalable you know how like if you take an image like this one let me view this you know if we take this image right and I make it super super big make it super big the bigger I make it the worse the quality gets with an SVG you don't ever have to deal with that because you define exactly what it'll look like no matter what size and what we could do is we can actually make our own SVG sort of like this right and if you're in W3 schools if you hit try for yourself you can see my first SVG over here and I could change this I could say the fill is now blue we run and it now turns blue I can say the stroke is black right and it turns black so there's a ton of different parameters and functions that we can do to make an SVG look a certain way right so if we're back in our vs code we can even go up to IMG new file example.svg code some SVG in here so we'll do SVG XML ands equals and this is just sub vering stuff HTTP www.w3.org 2000 SVG give it a width of 500 height of 500 these need to be in strings we'll have a closing SVG tag and here we'll make some text say Phil equals black hi you decoded this back text like this real minimal SVG like this and then if we go to extensions we can look up SVG and there's a couple of different SVG viewers and SVG previewers I forget which one's the best one let's go with this one for now and now we can do is go back to our SVG open up our Command pallet type in SVG preview SVG I'm going to install this SVG preview going to go ahead and hit install now we can come back to our SVG open up SVG preview open preview to the side and it looks blank so let's fix that we'll say x = 0 y = 15 x0 Y is 15 fill is black text okay that looks good preview the SVG and boom we can see this a little high your browser decoded this on the side now this is just the SVG and this storing all this on chain is not a URI right our nft needs a URI right it needs this string this is not a URI this is an SVG but what we can do is we can actually convert this into a URI that our browser can understand and we're going to pass all the data we need in the URL of our browser this going to sound really bizarre right but what we're going to do is we're going to CD into to that image folder and we're going to run a command called base 64 now not all computers have this you can check by doing base 64 d-el if you don't have this don't worry you can just copy paste what I'm going to be doing we can actually base 64 encode the out everything in here and what I can say is I can do base 64- I which means we're going to input a file and we're going to pass in this example.svg we'll see we get this weird thing as an output so now if we take this weird thing and I'm going to actually create a little little read me to make some notes here so this weird output is the base 64 encoded example. SVG we just created now at the start of this we can add a beginning piece to tell our browser that this is an SVG so I'm going to say data colon image/ SVG plus XML base 64 comma like this and if I copy this whole thing oops sorry this isn't should be a semicolon here if I copy this whole thing and I paste it into any browser we're going to get this hi your browser decoded this so basically what we did was we encoded this SVG file and put this data image SVG plus XML colon Bas 64 so our browser knew how to decode it and then just passed the entire image through our browser URL and boom so we can also do this with images so if I go back to the repo associated with this lesson go to images Dynamic nft we go to happy SVG happy. SVG we go down to code instead of preview and see the exact code here right so we create this view box oops we create some circles we create this path which is how we just kind of draw lines and I can copy this whole thing paste it into my image so I'm going to say oops image I'm going to do happy SVG happy. SVG paste it in here I pull up the preview I see the preview is a happy now what I can do is I can do base 64- I happy. SVG we get this output and copy this output let me go over to the read me paste it I'm going to add this beginning piece to it and then copy this whole thing back to my browser paste it in and boom we passed all of this data to generate this SVG right in the URL and this is looks like yes it does a token URI right so now instead of using an ipfs hash for our token U we can actually 100% onchain use this SVG thing and because this SVG is basically code on Shan we can update it and interact with it to make it do whatever we want it right for example if our H happy SVG we could say okay if if somebody has 10 tokens right they get 10 circles or something like that right we could do whatever we want with this so let's learn how to make one of these svgs on chain and we'll make it so that our nft is actually Dynamic so that our nft can change it can evolve it could grow whatever we want to do with it and then at the end we'll finally learn what this ABI en code packed stuff is right and this is going to be incredibly important for those you looking to go the extra mile looking to go really far and looking to become really Advanced smart contract developers so let's build our mood SVG nft which can change its mood change the image of the nft and it's 100% stored onchain so let's show you what we're going to be building we're going to be building this nft called a mood nft a mood nft and in here we're going to have a function called flip mood and what this is going to do is if we're happy it's going to make us sad and if we're sad it's going to make us happy and it's going to flip between these two images between the happy and sad right if I go to images Dynamic nft we have this happy SVG if we're happy our nft will show happy and if we're sad will show sad right we're going to have this 100% Beyond chain we're going to learn more also about how to work with this metadata and everything and we're going to do this end to end so let's create this mood nft so let's go to SRC new file mood nf. soul and you know the drill spdx license identifier MIT ragma oops ragma solidity 0.8 8 low carat contract mood nft like this this is going to be an nft so we're going to copy some of the stuff from the basic nft we're going to copy this import paste it in here and all right we're going to say this nft is an nft make a Constructor erc721 this is going to be called mood nft n MN for mood nft this and we're going to WR in the Constructor we're going to pass the happy mood and the sad mood svgs so an image right here we have our happy SVG great if you guys want to create your own s SVG go for it but I recommend you just come here go to code and let's copy this new file sad.svg place it in here like this I don't know why I have this this first line I'm going to delete that preview it Yep looks good so we have a sad face and a happy face nice okay cool and then yeah actually if we pull up our happy phase right if we preview this again and I to change the circle from like 61 to like 20 I'm like literally moving the eyes as we go you can make whatever monstrosity you want feel free to do that but we're going to take those svgs as input parameters so we're going to say string memory sad SVG string memory happy SVG all right cool and you'll see why we do that in a second let's create a token counter so we'll do U into 26 private sore token counter we'll set the token counter in the Constructor to zero and let's save these as well so we'll do string private sore sad SVG string private sore happy SVG we say say Sad SVG equals the sad SVG oops equals sad SVG and happy SVG equals happy SVG Okay cool so now we're going to make it so that anybody can Mint one of these so we'll say function mint nft this will be public anybody can mint their own mood nft we'll do a little safe mint function where we'll give the message. sender the sore token counter so they get their token ID we're going to say s token counter Plus+ we'll add one to it and that looks pretty good and now we'll want to Define what this nft actually looks like so this is with the token U function of course which takes a u56 token ID it'll be a public view override and it's going to returns a string memory like this now how do we actually get our nft to show this stuff this SVG nft well we're going to pass the SVG text in here right but what we could do instead of that is we could just pass in the encoded image already right we could just encode these images ourselves so if I for example and we kind of already did right if we open up our read me I'm just going to delete everything let's do happy SVG what we can do is we could pull this up clear we could do base 64- I happy SVG copy this hit enter we need to prepend with data image/ SVG plus XML semicolon base 64 comma paste that in if I copy this I can just double check by pasting in the browser yep okay that looks good so that's going to be our happy SVG we can do the same thing with our sad SVG base 64- i s SVG do the same thing we're going to copy this output it gave us which is a lot bigger paste it in here and we're just going to prepend it with this as well boom copy the whole thing paste it in here and cool set SVG as well nice so we have those already so why don't instead of us passing in the text of the SG and the nft instead of passing in these we just pass in the already encoded version right it'll save us a step we can base 64 encode these on chain and I'll show you how to do that in a second but it'll probably save us some gas if they're already encoded so instead let's say Sad SVG image URI happy SVG image URI let's have these be the Imports instead and what's important that it's just the image UR we're passing we're not passing the token URI right why not because while the token URI we go back to our our pug test the token URI is going to look like this where it's not the actual image it's this Json object it's this metadata object the actual image U is here the actual token U is here okay so this is the token URI this is the image U token URI image URI this is what the nft looks like this describes everything about the nft this is the token U so this you I'll read me this giant thing well or this thing is the image URI it is not the token U it's the image URI so back in our mood nft we're getting that image URI so let's make this more specific let's call sad SVG image URI happy SV image U so sad happy so we're going to pass this already encoded data to our nft nice so how do we actually store this this object on chain well we can actually encode Json objects the same way we encoded svgs using that base 64 stuff and we can actually do it on chain using open Zeppelin's base 64 package open Zeppelin has some utilities where one of them is a base 64 base 64 utils allows you to transform byes 32 data into a base 64 string representation so that's what we're going to do now we're first going to make our metadata Json object and then we're going to use open Zeppelin to convert this Json object into a Json token U so let's learn how to do that so we already have open Zeppelin installed oh my goodness I'm such a newb I'm so sorry named import from here we go okay cool now let's let's go ahead and let's import we're going to import this base 64 file from at open Zeppelin we've already got the remappings and everything contracts SL utils SLB 64. so you it's in the package I promise and we can use this base 64 thing to actually encode stuff so let's scroll down to our token URI and let's first let's just write out this as if it were just a giant string right let's just create this metadata object so first boom name let's get rid of that what's our name going to be and let's make this just a giant string so let's say string memory token metadata equals name and we're going to need to combine this string with the name of our nft project here do a little comma boom boom we could do this oh and then comma here here but we could do ai. encode packed to concatenate this whole string together or we learned another way to combine strings we do string.c concat like this boom so we can concatenate this and what this will print out is name mood nft right because we're combining the name in the mood nft so that looks pretty good however we need the rest of the stuff so we need a name descript description image and then attributes right so we got a name in here let's keep going what else do we need well we should do so we shouldn't finish it here let's even just delete this we should do a comma space and I'm going to toggle word wrap again just so that it's on description and then we can just add whatever we want in here let's say an nft that reflects the owners the owner move right we'll do a comma attributes now attributes are going to be in this list style here so we're say attributes little list here another bracket we're going to say trait type say just kind of a silly attribute here moodiness value 100 and then close it off close off the list okay cool looks good image and now this is finally where we put our image URI Right image URI and then we'll say comma and then we'll finally close off the text here so this is going to be the metadata of our token since we're parameterizing it a little bit it it will look like this once this the two of these populate right our image U though we need to derive based off of the mood of each person which we haven't defined yet so we should make a little mapping of like token ID to mood so we can do that up here we'll say mapping U into 256 to to mood and let's even create an enum mood of happy sad and this way if we wanted to add more moods later we could add more moods later so mood this will be a private sore token ID to mood and when an nft gets minted let's just default them we'll say the mood is going to be of s token counter is be mood. happppppy so we're going to default them to being happy so to get the image URI up at the top here we could do a little if statement we could say if Sor token ID to mood of the token ID equals mood. happppppy let's do this let's create this blank string memory image U we'll say image U equals sore happppy SVG image U and we'll say else image U equals sore sad image U so now we have a way to add the image whether their person is happy or sad right to the Token metadata here of course we're probably going to want a way to flip our our mood and we will add that later so this is looking pretty good but this is just the token metadata right this isn't this isn't the whole thing this isn't the whole shebang because this is just a string we need this token URI to return a string that looks like like this a string we can post in the browser this string ah you can't really post this in the browser URL right so what we need to do is with this token metadata string we do string.c concat or string. concat is nice but we actually need to convert it to bytes we need to do ai. encod packed like this and it needs to not be is string ai. encode backed and we need to make it a bytes like this we actually could do string. concat but just do ai. encode packed because we need to convert this to bytes in order to use the open Zeppelin Bas 64 encoder if you look at the open Zepp in Bas 64 it says it allows you to transform byes data into Strings and you can see actually in the examples here of the open Zeppelin docs it also uses an nft as its example so we need to convert ab. encode PCT to bytes and then we can do base 64. encode this whole thing like that and now now that we're base 64 encoding it that's equivalent to us getting this giant piece when we did from the command line we still need this beginning piece so we can get that by just adding concatenating this beginning part so this is where we're going to need this beginning part now since this is a adjacent object it's not a data image SVG XML we're going to need to create a function let's create a function called underscore base U it's going to be internal pure override because the ERC 721 also has a base U function that we're just going to override it's going to returns string memory we're working with Json objects we'll say return data application SL Json semicolon base 64 like this so this is going to be the base URI of our metadata return we're going to concatenate this with this by doing api. code pack or string. concatenate ai. encode packed this and then we're going to wrap this whole thing up as a string like this and then return it okay that's kind of a big thing here so we still want to be able to flip the mood and everything but let's write a test just to see if this is working correct first we created this string we concatenated together using ABI Cod packed we turned it into a bytes object then we encoded that bytes object we combined that with a base URL and then we turn that whole thing into a string and return that so let's do a quick sanity test here so we're we're going to create a new file mood nft test. T.O and we're not even going to write a deploy script yet we're going to write a deploy script but we're going to skip it for now and we're going to do and we're going to just make sure that this token URI function is working correctly right it should default to the Happy SVG so we'll do spdx license identifier ragma solidity carat 0.818 contract mood nft test is test import test from Forge STD test. Soul function setup public and we're going to of course need to import our mood nft from srcm nf. we'll say mood nft mood nft up at the top and then we'll even just deploy this ourselves we'll say mood nft equals new mood nft and our mood nft takes what takes the sad SVG URI and the happy SVG URI so we could do string public constant happy SVG happy SVG Ur equals go back to a read me because we already created these we'll copy this little string here like that then we'll do the same thing string public constant sad SVG URI equals same thing we already created this one copy this paste it in here semicolon so what goes first the happy or the sad sad goes first okay why did we put the sad first sad first happy SG Okay cool so now we have our mood nft now we'll do function View or function test view token URI like this we make this a public view or no just public actually and what we'll do is we'll do mood nf. mint nft so now we should have look at our mint function we should now have token URI and token zero and then we can just do a console.log mood nf. token URI of zero right and of course we're going to need to import console from test. Soul so we can do that console. log okay cool pull this up go down to The Foundry nft f23 directory PWD cool we're in the right one Forge test- m- VV so we can see the console. logs transfer to non erc721 receiver implementer so this is already an interesting error that we're getting so when we call Mint nft in our our test we're actually minting it to this test contract right and this test contract doesn't have a receive function and open Zeppelin baked in some code so that people wouldn't accidentally send nfts to contracts that can't transfer them or do anything with them so instead we're just going to do vm. prank we'll create a user we'll do address user equals make ADR user we'll prank the user so that it'll go to a user it'll go to an address as opposed to a contract so we can actually see this error we go to the ERC 721 contract we look for that error and we see on the safe transfer from there's this check on erc721 received and if we click into this function it does a whole bunch of checks in here basically checks to see if there's a function selector called onc 721 received right and again the reason for this is to make sure that if you're sending this nft to a contract address it's expecting to get an nft so it could possibly remove them right or or transfer them or whatever right so for now we'll just prank a user we'll rerun our test pull this up and okay we get this as our log so this is going to be our token URI we can see the data application Json base 64 and we're assuming this is the encoded Json object so if we grab this paste it into our browser now okay that looks pretty good that looks like ajacent object then if we grab this paste this into our browser we see the happy SVG nft so this is how we can know that our token U function is actually working correctly right because we can see that it's printed out and what we could do if we wanted to is we could start up our Anvil chain right make Anvil and deploy to Anvil then mint an nft on anvil switch over to Anvil and try to see it in our metamask as well so if you want to do that highly recommend you give that a try our nft is looking pretty good here we got our token URI to work we just need to be able to flip it right we need to be able to change its mood we also need to write a deploy script as well let's write the flip mood function and then we'll work on the deploy script so down here we'll create a new function called flip mood where we're just going to change the mood of the nft so un 256 token ID it's going to be public now first we're going to say we only want the nft owner to be able to change the mood right so first we're going to have to make sure that it's the actual owner that's calling this and the erc721 from open Zeppelin actually comes with a function called underscore is a approved or owner so we can say okay if they're not approved or owner before we're sending this message of the token ID then we're going to go ahead and revert right so if they're not approved or owner we're going to revert and we're going to make a new error at the top errors say error mood nft uncore uncore can't flip mood if not owner this copy this come down here and we will revert with that and then all we're going to do is we're going to say if sore token ID to state or to to mood of the token ID is equal to mood. happppy then we're going to change their mood to sad equals mood. sad else we're going to copy this l again else we're going to change them to happy all right cool so now we have a function that can actually flip their mood as well great everything's looking pretty good here let's go ahead and create a deploy script so new file deploy mood n.s. all right so let's go ahead and deploy this mood nft or write the script to deploy it anyways so you know the drill spdx license identifier MRT pragma solidity oops like so contract deploy mood nft dot or contract deploy mood nft is script going to import script from forg STD script. Soul like that contract contract this needs a semicolon okay nice we of course need a function run external already know this is going to need to returns a mood nft which let's import that now import our mood nft from dot do srcm nft do Soul bada bing bada boom we are cooking all right now our mood nft how do we deploy this bad Larry well let's go to it what does it take as input it takes a sad SVG image URI and a happy SVG image URI now we could hardcode those in here right right like we did in our little little kind of test over here we could definitely hardcode these but I'm going to teach you some fancy smcy way is that no matter what is in here no matter what text you put in here it'll automatically encode this for you right so you can make this SVG whatever your heart desires and this will automatically encode it for you so I'm going to create a little function down here first of all called function SVG to image UI and we're going to pass it a string memory SVG public your returns string memory mem let's zoom out just a little bit and we're going to have this function do this base 64- I blah blah blah thing for us that way we don't have to do that step and it'll automatically base 64 encode it for us when we deploy this so we're just going to make our lives a little bit easier here so for example right we're going to pass in something that looks like like this right as text so SVG with blah blah blah something like this I'm just going to copy part of this boom something like this dot dot dot dot something like that we're going to be able to pass this in and we're going to get as a return data let's go back to that test or yeah that works too going to return something like this boom bo boom it's going to return something like this we're going to pass this in return something like this we're going to do it all from our solidity scripting so what we're going to do is we're going to say string memory base URL is going to equal that data image/ SVG plus XML base 64 comma right because this is always going to be the prefix which is is easy enough to do but how do we do post fix how do we encode that SVG stuff on chain well this is where we're going to use that open Zeppelin base 64 package again it can already do this for us so we're going to go ahead and import base 64 from at open Zeppelin SL contracts utils base 64. Soul like that looks good and down here we're going to do something very similar to what we did in our mood nft where we encoded it with the op up on package we're going to go ahead and do string memory SVG base 64 encoded equals base 64. encode byes yeah and it looks like get up co-pilot is being correct here string ai. encod packed SVG so what we're doing is we're doing Abi and code packed the SVG so we're taking this massive input and we're packing it together as a byes objects we're converting it to a string and then converting it to a byes and then encoding it I know that's a little confusing but that's what's going on here so that way we can actually base 64 encod it and then we just combine this encoded string with the base URL and we can just say return string ai. encode packed or string.c concat base URL L comma SVG base 64 64 and coded we probably should use string dot concat instead of this ABI do and code packed but I'm just so used to this ABI do and code packed and I'm not really sure which one's more gas efficient maybe I should do some benchmarking later on or maybe you can tell me which one's more gas efficient yourself so we have this function now where we can actually take an input of the SVG and convert it to this but we should probably test to make sure it actually works right why not let's do a little test deploy mood nft T.T or test. T.O I'm actually going to copy a lot of the setup from our mood nft stuff over here I'm just going to paste it in like this deploy this is going to be deploy mood nft test is test we don't need this mood nft yet we do need deploy mood nft from deploy mft script here. s.o I know went kind of quick there but this is where it's getting from and we're going to do function setup course public and we're going to need one of these deploy mood nfts deployer we'll even make this public why not and we're going to say employer equals new deploy mood nft like this and now s it out function test convert SVG to URI public and now with our deployer we're going to call this SVG to image U we're going to pass it in SVG so we can just to test here we can take one of our svgs for example this one right we can put everything on the same line and this is going to be the high your browser to code this right I can run base 64- I we're going to go to/ image example. SVG and it'll give me this output right and then if I copy this we'll go back to the read me we scroll down paste this in here I'm going to say like example and then I'm just going to grab this prefix paste it here I copy this stick it in my browser boom higher browser to coded this Okay cool so this U is correct so what we can do in our test here I know we have a lot of stuff open we can say string memory expected U equals and just paste that super long string in here that's going to be the expected URI and then we're going to say string memory SVG equals and we'll go to the example.svg everything is on one line here we're going to copy this whole thing come back here and use a single quote paste it in because we're using double quotes in here so we'll use a single quote and what will we'll do is we'll do employer dot what's the name of the function SVG to image your ey SVG like this and we'll say string memory created SVG equals deployer excuse me created or actual URI and now we'll just assert that and we got to compare these strings so how do we compare strings again that's right we'll do a little check 256 ai. encode hacked act U equals KCK 256 ai. encode packed the expected URI like that wonky function and then this is probably going to be a view yep okay so we're going to do a view function here great and now let's test this Forge test DM paste it in so it looks like our way of encoding an SVG in solidity is matching our command line way of doing it and remember if your command line doesn't have Bas 64 that's okay there's some online decoders as well you can use or just follow along with me like I said it's all good okay phenomenal so tested that works great let's keep going zoom in a little bit little zoomed out here so now let's actually read in these files these SVG files into our solidity now you can only do this in Foundry right because you can't actually read in scripts in solidity smart contracts you can only do this in Foundry and we can do this with another Foundry cheat code go in the search bar here there's a read file cheat code file signature there's this read file here and we can use this to read an entire file and we can read an SVG now in order to do that we're going to need to go to our Foundry dotl in our project and we're going to need to add this FS permissions permissions equals access equals read path equals SL images cool so now we can read from different paths and that's the only access that we're going to give and this actually brings up a good point in our actions. soul we're using this devops tool which requires ffi to be true I'd much rather this devops tool use this this read permissioning instead of just saying hey do whatever you want in the Shell it's much safer to just say hey you're only allowed to read what's in this shell so if somebody wants to refactor this devops tool to instead of having F ffi be true to only allow the fs permissions to be true that would be great the repo is open source I highly recommend you contribute maybe even come to it you scroll down and you'll see something at the top hey it's congratulations it's been revamped to not use ffi as true it now uses the read permissions you read really don't want to have ffi equals true in your founder. tomal if you don't have to so in fact anytime you're working with code outside of my tutorials try to make this false okay try to make this false any and everywhere you can okay deployed mood nft great so now what we can do is we can use this read file cheat code and read in our svgs so we'll do string memory sad SVG equals bm. read file SL image slash is it just an image here yep image slash sad.svg why do I keep doing the sad ones first string memory happy SVG equals vm. read file image Slappy SVG we would probably want to write test for this too but if I want to just kind of quickly sanity check it we'll add the console in here do a little console log sad SVG pull up our script we'll do Forge script script SL deploy mood nft dos. so we'll hit enter should run this on its own fake Anvil chain path is not allowed to be accessed for read operations oh that's because not images this should just be image it's clear let's read this now Aha and cool that looks correct enough yep that looks correct enough okay awesome so it's reading in this path perfect so now what do we do well we finally do vm. start broadcast mood nft mood nft equals new mood nft and we're going to pass in the mood so the mood nft needs what it needs those image Uris as input so we're going to say SVG to image URI of which one goes first I think we keep doing sad first yep sad first sad SVG oops it should be a comma copy that SVG to image URI happy SVG like this semicolon and we'll do a little vm. stop broadcast like this and then we'll return our mood nft now we can use it in our tests nice okay all right so now that we have this up and running this actually shows a little bit of some of the difference between integration tests and unit tests so this is kind of more of a unit test right we're deploying kind of our own way here just saying hey mood nft is this nude mood nft whereas we could use our script and that would be more of an integration test so if we even want to do that right this is a better example of us saying okay new folder unit and we're going to put both of these in here well actually this one is using the deployer right so that was kind of more of a staging test or that's kind of more of a Integrations test so Integrations we're going to put both of these over here mood nft test. s oopsy mode this is also going to go oh no sorry this is going to go in units since we're not using since we're just deploying like this and we screwed up some of our Imports let's fix the Imports in here and in here and in here all right cool but now we could do another we could do a new file mood nft tegration gration test. T.O and I actually just going to copy this whole test paste it in here change the name Moon nft integration test and instead of deploying like this we're going to use the deployer so we're going to import deploy mood nft from do script deploy mood nft dos. copy this and instead here we're going to say deploy mood nft deployer like this and we're going to say deployer equals new deploy mood nft and we're going to say deployer do run this is going to equal our mood nft Bo and this function test view token URI integration should work pretty much the same so now if we run Forge test DM paste it in sure enough it works exactly the same here awesome okay so one thing that we have definitely not tested and I'm just going to do in this integration test because I way prefer and I want you guys to get used to also testing your deploy scripts I've seen way too many product not do this and then get wrecked so I'm going to we're going to do most of our stuff in here we'll do function test flip token to sad we're going to test flipping it from happy to sad remember it starts with happy I'm going do a vm. prank our user mood nf. mint nft like this we're going to do vm. prank user again I should do start prank instead of two pranks but whatever mood nf. flip mood zero and then we're going to assert this is now a sad nft so we're going to assert K 256 ai. incode hacked of the mood nf. toen zero equals pack 256 ai. encode packed sad what is it called sad SVG URI boom Oh and then semicolon about kak wrong again I've seen this word so many times and I've heard it pronounced correctly and I still I don't know if it's kak or kak I think it's kachak kak I don't know Forge test DM paste it in failed let's do some Dash VVS see what's up oh that's not enough V's four v's okay assertion violated Mo token U is going to be this H and so this is actually where I prefer assert equal rather than assert if we do assert equal we can put a comma here and it'll print out both of the results for both of these so I'm going to do a comma we're going to do assert equal we try this again P this up and we'll see oh maybe it didn't print out both oh yeah it did print out both so yep so print out the left Val and the right Val so looks like these are different for some reason so do we not well this is where we can do a little console. logging let's do console. logging mood. token U of zero so let's see what this token URI is so let's run this again now with the console.log and practicing debugging is really important so that's why we're going to actually do this together- VV so we can see this console. log let pull this up a little bit here we'll see logs so this is that token URI that we're actually seeing so this should be sad we copy this paste it we see we get the metadata let's copy the image paste that okay we do indeed get sad so what's wrong with this sad SVG and this is the sad SVG oh I'm being silly okay so this is the sad SVG U URI sad SVG image URI okay so that's where it's good to be explicit image IM U image so these are obviously not going to be the same because one is an image URI and one is not but so we want this token U to equal not the sad SVG image U right we don't care about that we want it to equal our sad SVG U which I'm just going to paste in here string public constant sad SVG U equals and we already tested this actually I know we're running around kind of like a lot we tested this in here expected U is this the happy one let's see let's paste this in the browser oh that's just the your browser decoded this I'm going to cheat a little bit actually just going to copy this and do sad SVG U and just paste it in here copy this paste it here run this again cheating a little bit here but that SVG URI looked right to me and now we're going to go ahead and pass okay cool awesome so let's talk about what we what we just did because I know we've done a lot so I kind of sped through integration unit test stuff over here but this was a really good example of some of the differences between a unit test and an ation test so in this unit test we only tested one specific function on our deploy mood nft additionally we only tested one specific function on mood nft although we didn't put an assert here but you get the picture our Integrations test we combined the deployer with the mood NF or excuse me the basic nft on both of these we did that right so these are a much better showing of what an integration test would look like right and now if we run Forge test we get everything to run everything looks good and if we test this on a fork everything should look good too Forge test-- Fork URL aolia RPC URL remember to run source. if you haven't already and that passes as well nice good okay so we have all that we have a script where we can deploy both of these we can flip the mood of our nft as well we don't want to have to write all that Forge script stuff so we're going to come in the make file we're going to add a line in here mint mood nft at Forge script scripts SL interactions. s. Soul mint mood nft do we actually have that I don't think we have that interactions mint basic only have mint basic we don't have mint mood oh okay we should have a script for minting the mood we should also have a script for flipping the mood now I'm going to skip those because there's no real more information it's just practice I highly recommend you try to actually Implement these yourselves right try to implement a script for minting the mood nft a script for flipping the mood nft as well and you can do with cast or Forge scripts whatever you want to do here okay so we have a way to deploy both of these we have some tests so real basic tests so your other action item here is going to be you guessed it get that coverage up we do Forge coverage what do you think we're going to get sure oh whoa okay basic nft looks good mood nft looks okay it definitely should be tested more but some of these scripts don't look so great we should definitely be testing our scripts more so you guys ready to see this for real see this in our metam masks and everything for you all I'm going to recommend you actually do this on an anvil chain instead of on a test nut if you want to deploy to a test nut you're free to do so but remember test nuts are slow they're annoying and we should be able to do all of this with Anvil so in our make file if you copy pasted it with me do a toggle word WP there should be an anvil Target there sure is so we're going to do this Anvil Target here make Vil we spawn up a chain let's create a new one let create a new shell and now we're going to run make Deploy on our mood nft oh we should do that deploy mood this one we do have a script for Forge script script slash deploy mood what is it called deploy mood nft deploy mood nft mood n.s. we're going to be calling deploy mft Network args great and so now if we just run make deploy mood it should deploy oh an error here no such file or directory I'm getting this error here I think it's because I don't have deploy mood and phony yep I sure don't let's add deploy mood in here so now it knows that that's a Target let's try this again no still getting that error ah it's script whoops s. soul there we go so now we can go ahead and deploy this we deployed the Moon nft to here and we could write a make file actually I am going to write a make file to Mint one but I'm just going to use cast so I'm going to recommend you guys do this on the Anvil chain let's go ahead and get our Anvil chain set up let's go to our menam mask let's go ahead and do add Network and we're just going to go ahead and reset our Anvil chain way we can do that is by using this make and build Target here now that we have a Target go ahead and like just edit this a little bit 377 boom you change the currency to like go or something save now that our andle is up we should reset the chain great it looks like we do indeed have an address in here our account four if you don't have an account four we can just import one from one of these private keys right just import a private key so now that we have an anvil chain a fresh new Anvil chain let's also go to accounts settings just to make sure Advance we'll do clear activity tab great now that we have this here we can do a make deploy mood which should deploy to our Anvil chain oh looks like we're oops we need this let's try this again make deploy mood okay cool we now have a contract address mood nft what we can do is then copy this and use some cast so we'll say cast send and the contract address we'll call Mint nft like this this will mint Us in nft oh we need to actually pass in a private key-- private key which we're going to use the private key from this account which I already have mine here- RPC URL is going to be our Anvil RPC URL we can also find in the make file copy this paste it here kill me do Account Details export private key put in our password copy the password do this cast send with a private key that actually has some money in it paste it in and cool we now have a transaction and what we can finally do is we can grab this contract address on Anvil go to import nfts paste it in add the token ID hit add and we have a mood nft in here now let's flip it so now we can do we hit up we'll do the same command but we'll change the function that we're going to call to what what's the Flip Flip function called it's called flip mood call Flip mood on token zero this is how you do that you put flip mood you into 256 is the input it takes with token zero all the rest is the same looks like it's in here and what we have to do for metamask to get this reflected though is we need to copy this address again we're going to go ahead and click on this mood nft hit the little quotes here remove nft and then we got to read it import nfts paste it in token ID is still zero hit add and now it's sad and we did it we created an nft 100% onchain we deployed it to our own local network on Anvil we showed it in our metamask and it is showing up correctly and we could 100% deploy this to a test net if we wanted to we deploy this to a main net if we wanted to and we have just done amazing work learning about fgs to make sure our nfts are 100% on chain and not centralized by using like a website or anything like that okay so all of you who are here learning about this when you go make your nfts remember to try to keep these as decentralized as possible when you're storing that nft metadata now I will point out there are a couple decentralized Storage Solutions out there where you can store your nft metadata R weave is one of them and filecoin is another one these are two of the most popular ones there's a great site called nf. storage which will help you actually deploy your nft metadata onto FAL coin onto this decentralized storage solution so you don't have to just do svgs on chain you can also do actual images on decentralized Storage Solutions if you want to learn more about fcoin I've got a video on it on my YouTube just a quick 8 minute video to explain filecoin a little bit more and if you go into this video in the description there's a Blog that teaches more about decentralized storage and some of the different solutions out there it's a really interesting space and I'm expecting in the future decentralized storage to become more and more prevalent all right this is phenomenal you have deployed an nft possibly to a test net hopefully at least to your own local Anvil net we've learned a ton about ipfs svgs we've learned a little bit about decentralized Storage Solutions the only thing we haven't covered is what the heck is this ai. in code pack stuff you we've been using it this entire course and I don't know what it does well guess what it's time for us to explain that to you let's jump back into remix and we'll explain it remember all the code that we're going to be working with can be found in SRC subl lesson in here so and you can find all the images that we're about to show you in here as well so from a really really high level this is basically how you concatenate strings right this is how you combine strings together and we're going to jump over the remix to actually explore this ai. encod packed and this ABI encoding stuff a little bit more now now the section that we're about to go through is definitely Advanced and we're going to be going over some really low-level stuff and how solidity Works behind the scenes how the binary works and this thing called op codes and all this crazy lowlevel tricky difficult things to understand if you want to move past this section there are timestamps in the GitHub repo to help you move past this however I do encourage you to at least try to absorb most of this material if you don't understand it the first time 100% okay this is more advanced anyways for most of your basic projects you won't really need this information it's only later on once you get more advanced that knowing all this is really going to make you a phenomenal solidity developer and when you approach this section when you approach this subl lesson on evm op codes and coding and calling just know that if you don't 100% understand it the first time that is okay if you want to watch this section A couple times fantastic so if you want to jump over to remix and follow along let's do it now in our contract section let's go ahead and create a new file we're going to call it encoding do soul and remember all the code that we're going to be going with in here is going to be in this subl lesson folder of the hardhead nft FCC and all the code we're going to be working with is going to be in this encoding doou and then in a little bit we're going to work on this call anything.so so we're in this encoding doole and let's just make our basic code here so we'll say spdx license identifier MIT fragma solidity carrot 0.8.7 like that we do contract encoding boom compile or command s or control s great things are looking good now remember the whole purpose for this is to First understand what's going on here and more about this ai. encode packed stuff so let's first just write a function that shows us wrapping ABI do incode packed with some strings and wrapping around a string is going to return a string so we could do function combin strings or concatenate strings this will be a public pure since we're not going to be reading any storage we'll say returns string memory and we'll say return string ai. encod packed hi Mom comma let's put space in here miss you like so so we need another parentheses here okay great now let's go ahead and deploy this we'll stay on a JavaScript VM we'll deploy encoding coding. so and we'll come down here we'll click combine strings and we get that whole string output hi Mom miss you so what we're doing here is we're encoding hi Mom missu together into its bytes form because ai. incode PCT returns a byes object and we are typ casting it by wrapping it in this string string thing to be a string and solity says okay yeah bytes to a string that's fine that totally works and this ai. encode packed one of these globally available methods and units and actually in solidity there's a whole bunch of these there's this solidity cheat sheet and there's going to be a link to this in the GitHub repo as well that has a whole bunch of operators and it has a whole bunch of these Global variables and methods you can see if we look in here we look for ABI do and cod packed we see ABI do and code packed right here we scroll down we see some more that we're familiar with as well like for example message. sender sender of the message message. Val there's a whole bunch of other globally available methods and variables that we can use when we're coding our stuff now I will say though in 0.812 plus you can actually do string. concat you know string a comma string B if you want to instead of doing this ABI on code packed but I still wanted to show you the ai. encode pack because it's a great segue into all this ABI stuff that we're about to go over but let's focus on this encode packed thing so what is actually going on here well before we dive deeper into this encode packed let's understand a little bit more about what happens when we send a transaction so when we compile our code and again all these pictures are going to be in the GitHub repo remember back to ethers JS we had those two files we got aabi file and a bin or binary back in our ether simple storage when we ran yarn compile the two main files that we got were this simple storage. ABI which was this you know this ABI thing that we've become familiar with and then the simple storage.bin which is the binary which is a whole bunch of just numbers and letters and stuff we didn't understand and you can see that in remix too like if we were to compile this you go to compilation details you get a whole bunch of stuff in here right you can see the ABI in here which this is kind of like a different way of viewing that API we also get this B code bit and it's this object that has the same stuff that has like those random numbers and letters but this is actually the binary this is actually what's getting put on the blockchain it's this binary it's this lowlevel stuff now when we actually send these contracts to the blockchain we're sending like I said we're sending this binary thing that's exactly what we're sending to the blockchain and remember how again back in our ethers project we saw what is a transaction right a transaction has a nuns it has a gas price gas limit two value data we kind of skimped over the vrs a little bit because that's kind of that mathy component of the transaction signature but again back in our ethers project we did this as well right in our deploy script ended up sending a transaction ourselves using just ethers we passed a nuns a gas price gas limit two value data was this massive thing to deploy our contract and then also the chain ID we didn't work with the vrs because ethers does that for us but there's also this vrs component that we we don't bother to look at when we send a transaction that actually creates a contract the two is going to be empty we're not going to send this contract deployment to any address but the data of this is going to have the contract initialization code and contract bite code right so when we compile it we we get all this code like how do you initialize the contract and then what the contract actually looks like so if you look at any of the contracts that you deployed for example I'm going to look at our raffle that we deployed if you go to the transactions of your contract we can see create raffle right let's go to that transaction if we go down and click to see more in ether scan we can see this input data thing and once again it's got all this random garbled numbers and letters this is that binary data of the contract initialization code and the contract bite code right what we send in our transaction is this data thing we send this this weird bunch of JBL nonsense now we're going to head back to remix and I'm just going to leave this as comments in here in the encoding doso and the get up rep there is a ton of comments in here explaining exactly what I'm explaining so if you want to follow along there you can as well but now in order for the blockchain to understand okay what do these numbers and letters even mean you need a special reader ethereum or the blockchain needs to be able to read all this stuff it needs to be able to map all these random numbers and letters to what they actually do how does ethereum or polygon or Avalanche know that all this nonsense is basically telling it to make a contract you kind of think of it as saying like take off your coat the only reason that we as human beings understand what take off your coat means is that we understand English we're all reading English for solidity and for blockchains instead of English they read these numbers and letters kind of like words just instead of take off your coat it's like deploy contract and the contract does X XYZ and all this random stuff so this bite code represents the low-level computer instructions to make our contract happen and all these numbers and letters represent kind of an alphabet just like how take off your coat is an alphabet and when you combine them like this it makes something that to us makes sense you can kind of think of the alphabet for these as what's called op codes if you go to create a new tab if you go to evm codes we'll get to this place where it just has a list of all these instructions on the left side you can see this thing called op code and then you can see name so this op code section is saying hey if you see a 0 in this bite code that 0 0 represents this op code stop which does what which halts execution if you see a 01 you're going to do some addition stuff a 02 is multiply there are all these op codes that are kind of like the alphabet or the language of this binary stuff right and they go go all the way down to to FF self-destruct these op codes also have and that's what this is reading right so if we look at our transaction here and your yours might be a little bit different 061 says okay the first thing we want you to do is the 061 op code and if we go to evm op codes we look up for 61 it's saying push two place two byte item on the stack that's exactly how it's reading this any language that can compile down to this op code stuff down to this specific set of of eum op codes or evm op codes is what's known as the evm the ethereum virtual machine so being able to read these op codes is sometimes abstractly called the evm the ethereum virtual machine the evm basically represents all the instructions a computer must be able to read for it to interact with ethereum or ethereum like applications and this is why so many blockchains all work with solidity because solidity compiles down to this bite code here and polygon Avalanche arbitrum ethereum they all compil down to the exact same type of binary and they all have the exact same readers now why are we telling you all this stuff you might be saying hey Patrick this is cool and all but it looks like ABI code packed all that does is concatenate strings ABI on COD pack can do actually way more and if we look at these Global variables ABI do and code packed is like what the third one down the list because it's a non-standard way to encode stuff to this binary stuff that we just talked about we can actually encode pretty much anything we want to being in this binary format basically and let's take a look at at encoding something so let's create a function called encode number and this will be a public pure function since we're not going to read any state and we'll say returns a byes memory we're going to have this function return a bytes object we're going to have it return the what this number is going to look like but in binary so we'll say bytes memory number equals ABI doin code 1 and then return number so we're going to encode number down to its ABI or its binary format so I know a lot of the times when we say oh what's the ABI what's the ABI right previously we say oh the ABI is is this thing right it's it's it's all these inputs and outputs this is kind of the human readable version of the ABI but again the ABI is the application binary interface we want to encode our numbers down to it's basically it's it's binary this ai. encode is going to be a little different than like the ABI that you see when you're looking at compilation details this is technically like the ABI it technically is how to interact with this contract however it's not the actual binary version of it so we're saying okay encode this number one down to its binary version so that our contracts can interact with it in a way that they understand so we're just saying okay cool that number one let's make you machine readable and if we go we compile this and we deploy this right let's delete that that old contract we deploy this we now have combined strings and encode number we click it we get this big hex thing this is how the computer is going to understand the number one now we can encode pretty much anything actually we could encode a string so we'll say function encode string we'll make this a public pure as well it'll return a bytes memory because we want to give it that binary stuff or that byes stuff we'll say bytes memory Su string equals ai. encode sum string and then return some string now let's compile that we'll delete our old contract deploy that and code string we get this big big big object here and this is the binary now you'll notice something here there's a ton of zeros and those zeros take up space right that's a lot of space for the computer to take up even though they're not really doing anything they're just kind of taking up space so solidity also comes with this ai. encode packed which performs packed encoding of the given arguments and you can read more about it in the solidity docs if you want and this is called the non-standard pack mode and it does the same encoding with some stipulations types shorter than 32 bytes are concatenated directly without padding or or sign extension Dynamic types are encoded in place and without the length aray elements are padded but still encoded in place you can kind of think of encode packed is sort of like a compressor right it's the encode function but it compresses stuff if we wanted to encode some string but we wanted to save space and we didn't need the perfect low-level binary of it we could do function encode string packed make this a public pure and have it return a bytes memory we could say bytes memory some string equals ai. encod packed once again some string and so we're doing encode packed instead of incode and we'll return some string here we'll compile this and we'll see the difference right compile we'll delete our old one we'll deploy this now we have encode string which again that's what encode string is going to give us and we have encode string packed which returns us this much much smaller bytes object here so you see the size difference if we're trying to save gas encode string packed is going to be a way for us to save a lot more gas now ai. encode packed is actually really similar to something that we've done before which is type casting if we did function in code string byes public pure returns bytes memory bytes memory sumring equals byes some string turn some string these two are going to look nearly identical right so if we compile we'll delete our old contract we'll deploy this and code string bytes which gives us this and encode string packed using the ABI code packed they give us the exact same output whereas encode string still gives us this big piece so the two of these get the same result but behind the scenes they're doing something a little bit different and I'm not going to go over exactly what that is but uh I've left a link inside of the code here if you want to learn more which is exactly what we're doing in our nft right we're doing ABI do code packed we're combining two strings by putting them together we're encoding them to their bytes implementation to their packed bytes implementation and then we're just typ casting them back from bytes to string and that's how we concatenate them now at this point you might be thinking okay cool great Patrick I'm all set I understand this I'm happy to go back to my project and if you want to do that absolutely go for it and skip over this section but some other views might be going okay Patrick this is seems pretty cool but I'm sure this encode packed and this encode function aren't just here to concatenate strings they probably have some other function what what do they actually do well if that's what you're asking I'm glad you ask and I'm glad you're curious cuz we're going to find out now not only can you encode stuff like strings and numbers and really anything but you can decode stuff so I could say function decode string public here return turns string memory string memory some string equals ai. decode this is going to take a couple parameters so if we look in the docs here ai. decode it takes as a first argument the encoded data and then it takes a tuple you can kind of think of it as a list but not quite a list a set of types to decode this into and it Returns the number of parameters that you gave it so we might want to say this string memory some string let's give it as input this encod string function the result of this encode string function right which again is going to be this big thing so this is kind of equivalent to sticking this massive thing in here but we're just not going to stick the massive thing in there because that's really big so we're going to say let's decode the result of encode string and let's decode it into a string because we need to tell solidity hey we're going to decode this but it doesn't know what to decode it into it it's like okay cool I can decode this but like what what do you want me to do with it and we say oh oh this is a string so decode it into a string and then we can do return someing now once again we deploy that old or we delete the last contract we deploy this new one so encode string encode string where is encode string encode string returns this massive thing as a human being we're like God I I can't read that computers can read that but we can't really read that so we say okay let's decode that back into its string form we hit decode string and we get back some string and now we can actually multi- in code and multi- in decode right we can encode as much stuff as we want so I can say function multi encode public pure returns bytes memory we're going to encode a couple things we'll say bytes memory sustr equals ai. encode Su string comma it's bigger so we're going to encode two strings here we're going to encode some string and it's bigger so we have two strings we're going to encode and we'll return Su string even though it's you know byes and then we can actually multi- decode so we'll say function multi decode this will be a public pure returns we'll say it returns two strings string memory and string memory and instead of doing string memory Su string equals Abid code we'll say string memory some string comma string memory some other string so we're going to get two returns equals ai. decode let's decode this multi- encode result which is the doubly encoded strings into a string and another string and then we'll return both of these or some string there we go then we'll return some string and then some other string I need a semicolon here so now when we deploy this let's close this out deploy this new one right we now have this multi-end code which gives us this even bigger bytes object right because this is two strings encoded and now if we hit multi- decode take a second what do you think it's going to put out output let's go ahead and hit it now it's going to give us two strings right it's going to give these two strings some string it's bigger so we can tell solidity to encode a bunch of stuff and then we can even decode it by telling it okay this big object here it's two strings combined and then we decode it now you can even multi- encode with that encode packed thing right we could do function multi encode packed public pure returns bytes memory and then bytes memory sust string equals ai. code packed sumring comma it's bigger and then return sumring we could do this right but this is going to give us the packed version of these two strings so the decoding actually isn't going to work on this because this is packed encoding so if we tried to do I'm going to say this doesn't work we tried to do function multi decode packed public pure returns string memory string memory suing equals ai. decode multi and code code packed and then in a string kind of exactly what we did above to if we do return some string what do you think is going to happen well let's uh let's try it delete the old contract deploy a new one we'll do multi- decode packed multi encode multi decod packed and we actually just get an error solidity basically goes um yeah this looks like it's packed I don't know how to decode that but instead what we can do is we can do function mole T string cast packed make this a public pure returns string memory string memory Su string equals string multi and code packed return some string this one will work right because again this packed encoding is kind of similar to just type casting so we'll compile we'll redeploy multistring cast packed we get some string it's bigger right and we don't have a space here but we should have put a space in there now that we've learned more about this ai. encode and decoding and we know that okay this is what the computer this is what ethereum this is what the evm or any evm compatible chain is looking for it's looking for this bik code it's looking for this this binary stuff and we just learned a little bit more about how to encode different variables into the binary into that data bit well what do we do now now since we know that our transactions are just going to be compiled down to this binary stuff what we can do then is we could actually populate this data value of our transactions ourselves with the binary the code is going to use so here's our transaction for a contract deployment the data field of the contract deployment is going to be all that binary code of the contract for a function call the data piece is going to be what to send to the address what data what function to call on the two address let's look at another one of our transactions on ether scan right on one of our contracts you don't have to I'm going to look at enter raffle from a previous section and if we select down we look at input data it says function enter raffle method ID but if we look at the original this is what's getting sent in the data field it's this binary it's this hex it's this weird low-level bytes thing this is how the ethereum blockchain or the or whatever EB chain you're working with knows which function to call it translates this into a function and we can do the exact same thing and call these functions ourselves so what we can actually do with this crazy new found data and coding stuff what we can actually do is send the data field of a transaction ourself in a transaction call remember back in this ethers throwback where this data thing was the contract creation code well in instead we could populate this data thing with our function call code the exact function that we want to call in the binary in the hex Edition now you might be thinking oh well why would I do that I can always just use the the interface the Avi all that stuff well maybe you don't have that maybe all you have is the function name maybe all you have is the parameters you want to send or maybe you want to make your code be able to send arbitrary functions or make arbitrary calls or do random really advanced stuff right that's where sending our function calls directly by populating this data field is going to be incredibly important so remember I said you're always going to need the ABI and the contract address to send a function now when I said you always need the ABI originally we were kind of talking about this thing this big this big thing which is cool which is the ABI but this is like the human readable API you can also do it with the not human readable API and additionally you don't need all this stuff you can really use just the name of a function and then the input types to send a function call so the question is then okay how do we send how do we send transactions that call functions with just the data field populated and then the next question is how do we populate the data field what do we populate the data field with to to make one of these function calls and then how do we send these transactions solidity actually has some more low level keywords namely static call and call we actually we've used call in the past before does this code look at all familiar to you well it should cuz this is we used a similar setup in our fulfill random words for our Lottery right we sent money doing this recent winner. call right recent winner was the address of the recent winner and we did call and then we had this weird stuff in this brackets here and then nothing in the parenthesis so we did actually essentially we used this call keyword previously but we didn't really tell you what it did so call is how we can call functions to change the state of the blockchain static call is basically how at a low level we call our view or pure functions right static call is going to be like okay don't change the state of the blockchain with this one just give us the return value so this is kind of similar to like a view or pure function at at low level there's also a send word but like basically forget about it we're just going to be working with call and static call and you know later on we'll learn about another one called at call but don't worry about that for now recent winner. call like this in these little squiggly brackets we said okay we updated the value directly of our transaction in solidity so which again if we had these transaction fields and we just directly updated value in these little brackets right we can also directly update gas limited and gas price in these little brackets if we wanted to as well and in here these parentheses is where we're going to stick our data since all we wanted to do with our withdrawal function previously was send money we said okay send money change the value that we're going to send but don't pass any data keep that data bit empty which is why again remember how we hit this button before right and we had call data be empty that's essentially running this command with call data be empty with this section be empty and then just updating the value that we sent with the transaction and so it's this section that we can use to populate data to actually call specific functions I'm going to put a whole bunch more comments here so in our squiggly brackets we're able to pass specific fields of a transaction like value and in our parentheses we're able to pass data in order to call a specific function but in here there's no function to call since we were just sending ethereum if we want to call a function or send any data we can do this in the parentheses oh and I think I spelled that wrong now we've learned a ton here so let's do a quick refresher of what we just learned and then we're going to actually learn how we can call any function just by using this syntax here what we learned from really high level if want to combine strings we can do ai. incode packed and then typ cast it to a string and in newer versions of solidity you can do you can do string.c concat you know hi Mom comma miss you in newer versions of solidity this works as well but not an older versions of slyy then we learned a lot about some low-level stuff we learned okay when we compile our contracts we get an API file and this weird binary thing that numbers and letters stuff that gets when we deploy a contract that gets sent in the data field of our contract creation transaction so for contract Creations the data is populated with that binary code for function calls is going to Define which functions to call and with what parameters and this is what we're going to go over next now we learned that we can actually encode stuff into this binary into this lowlevel code and any program any process that can read this low-level stuff and execute accordingly read this evm stuff read the specific binary that ethereum has specified or the evm has specified is considered evm compatible we can encode numbers we can encode strings we can encode pretty much anything we want to encode to save space we do encode packed we can decode stuff that we've encoded but we can't decode stuff that we encode packed we can multi- encode stuff and then multi decode stuff and then finally we can use this call function and add data in here to make any call that we want to any smart contract and this is what we're going to learn next all right so now is a great time to take a break because we just learned some really difficult Concepts and like I said if you don't get it the first time that is okay all right welcome back now that we've learned about this encoding stuff let's learn how we can populate this parentheses this data fi field so we can call any function and we can do essentially what the blockchain is going to do at the low level we can work with just that binary we can work with just that bytes we can work with that hex to interact with our smart contracts so let's create a new file and we're going to call it call anything. soul I start off with spdx license identifier MIT and let's talk about this now in order to call now in order to call a function using only the data field of the call we need to encode the function name and the par that we want to add right cuz when we call a function we call the function name and we call the parameters so we need to encode these down to the binary level so that the evm or these ethereum based smart contracts the solidity stuff can understand what's actually going on in order to do this we're going to need to work with two concepts to encode the function name so that the evm or solidity can understand it we actually have to grab something called the function selector now the function selector is going to be the first four bytes of the function signature and the function signature is just going to be a string which defines the function name and parameter now what does this actually mean well if we have a transfer function this right here is known as the function signature so the function name is going to be transfer and it's going to take an address and a u 256 as its inputs if we encode this transfer function and then we take the first four bytes of it we get this which refers to the function selector so that's how solidity knows so in the bite code in the binary code this function selector is how sidity knows oh they're talking about the transfer function they want me to call the transfer function and this is one of the first things that we need to use call to call any function that we want we need to get the function selector and we can get it a number of different ways but one of the ways is by encoding the function signature and grabbing the first four bytes so we'll create this contract we'll do pragma solidity 0.8.7 say contract call anything and we'll give this two storage variables give this two storage variables in address public sore some amount or some address and then U 256 public sore amount and then we'll create a function called transfer function transfer now normally in here we would actually do like transfer for like an erc20 transfer but we're just going to do address some address and then un 256 amount amount here we'll make this a public function and then all we'll do is we'll set s Su address equals Su address and then s amount equals amount so here's going to be the function that we're going to work with and the function selector for that function is this the function signature is this so it takes an address sum address amount that gets boiled down to the function selector and the function signature and of course in our bite code there's going to be some code saying okay here's what this function does blah blah blah so we can actually even write a function to get that function selector so we can say function get selector and I'm going to say get selector one cuz I'm going to show you a few ways to get the function selector we'll make this a public pure and we'll have this return a byte 4 selector we could say selector equals byes 4 and then we hash with K check 2 56 of the bytes of that signature which is transfer and it takes an address and a uent 256 right if we compile this then we run it oh let's get rid of our old contract deploy make sure we're on call anything if you have the other one up and here now we have a couple of things if we hit get selector one we get this Ox a905 blah blah blah right and that's the same as the example I just gave so this right here tells solidity tells our smart contract that okay when we make a call to this contract if you see this in the function data this is referring to our transfer function with an address and a u 256 as input parameters so we see address un 256 our function knows to execute this data here great and then of course s amount and S address are zeros now while we're here we can also see okay what happens if we call the transfer function right it takes an address and an amount so let's just give it its own address for an address and we'll do 777 for an amount if we hit transfer we have the the log up right we'll get a little check mark here saying success now if we hit s amount we'll get 777 and then the address will be the same right so that's us directly calling transfer when we directly call transfer we we're basically saying hey grab this function selector and then do some other stuff which we'll we'll tell you the other stuff in a minute now we have the function selector okay great what else do we need we also now need the parameters we want to add so we're going to need to encode those parameters with our function selector so what we're going to do is we're going to say function get data to call transfer and in here we're just going to have this get data to call transfer we're going to have it take these input parameters and we're going to encode these to work with our function selector so we're going to say address some address 256 amount public pure returns bites memory and then we can return use one of those ABI encodings from the cheat sheet now so far we've just been doing ABI encode for a lot of our encoding so since we have the function selector we can actually do ai. encode with selector this ABI encodes the given arguments starting from the second and prepend the given 4 byte selector when we do encode with selector we're just sticking our selector onto the data that we're going to give it so we're going to do return ai. encode with selector and we're going to pass it the result of get selector one and then we're going to give it some address and amount so what this is going to do it's going to give us all the data that we need to put in that data field of our transaction to send to this contract to let this contract know hey go use the transfer function pass in some address and then an amount and then if we compile this we run it let's delete our old contract we'll deploy it we now get a new function called get data to call and transfer we'll just pass you know we'll just pass this contract's address and then we'll also do 777 again and so this thing right here is what we're going to put into the data field of our transaction in order for us to call transfer from anywhere so this is the bytes this is the binary encoded data of hey call The Transfer function with this address that we specified with you know 777 amount so what we can do once we have all this we can actually call our transfer function without even having to directly call it so what we can do is we can say function call transfer function directly or I guess with binary might be a better title but you get the gist we say address Su address U and 256 amount we'll make this a public function and we'll have a returns a byes four and a bull you'll see why in a minute and we'll do that same call thing that we did to send our raffle money so what we'll do is before we did recent winner. call right we're going to do some address and then for us we're going to do address this. call and then we're saying this contract's address which we could put any address here address. call and we're going to call the encoded data that points us to the transfer function with some parameters so we're going to do address this. call and we could just do get data to call Trans transfer some address amount right we could do it like this or we could do it kind of the raw way we could do ABI do encode with selector get selector one comma Su address oops comma amount and actually there's no semicolon there sorry so those are going to be the same and this do call thing right it's going to return exactly what we saw before it's going to return a bull success so whether or not the transaction was successful and then bytes memory return data which is going to be you know whatever the call returns so right and this is where we put like require success right but for us we're just going to do return byes 4 byes four of return data and then success so we're just going to return the first four bytes of whatever data we get returned and then we're going to return whether this was successful or not so this function is going to have us directly call The Transfer function by passing these parameters without us having to do like contract. transfer or or transfer whatever right and you can do this across multiple contracts across different contracts just by changing the address that you call on so let's go ahead and compile this we'll run this now we'll delete our old contract we'll deploy call anything now if we if we were so right now s amount and smm address are both zero now if we do call transfer function directly and we'll pass in this one's address and then we'll do 777 now if we pull up the logs we hit this we're going to get this transaction response here but if we scroll down we'll able to see the decoded output which is a byes four of just a bunch of zeros right because our transfer doesn't actually return anything so it's just going to be a whole bunch of zeros and then our Boolean true which means it was successful so since it was successful these two should have changed based off of that so let's go ahead and try them out and we do indeed see that they're changed so we have just directly called this transfer function without having to call the transfer function itself we can also do encode with signature instead of selector so if we go to our cheat sheet there's also this encode with signature down here which takes the string memory signature and it's equivalent to doing ai. encode with selector bytes 4 kak bytes you know signature it's it's equivalent to doing exactly what we did up here but it does this step for us so we could copy this whole thing paste it down here right and we could do instead of encode with selector we could do encode with signature the function signature and then we'll copy our function signature from up here paste it in here compile we ran into compilation error oh these are the same uh call transfer function directly Sig call it that compile delete our old contract deploy now these two are both zeros again now if we copy the contract address we do call contract call transfer function directly Sig we paste that in here we do 777 we call it then we check these we can see that that does the exact same thing so this is ai. encode with signature this is ai. encode selector encode with signature just turns this into the selector for us that's all up here we just we encoded the selector ourselves now there are a whole bunch of different ways to get the selectors and I'm not we're not going to code these out ourselves I'm just going to say a bunch of different ways to get selector and who knows why why you might want to use one of these other reasons right there's there's a ton of reasons why you might want to get the selector a different way and here's some now in this video we're not going to explain or go over all these different all these different function selector getting methods but if you go through them in the GitHub repo associated with this course they all have a ton of commas to explain what they're doing what we are going to show you though is actually how two contracts can interact with each other without actually having all the code for each contract so we're going to make a second contract that has all this binary this bytes information to call the transfer function on a different contract and we're going to show you how that can work this is just another contract that I made called call function without contract actually down here we're going to call the transfer function just by using the address and the function selector signature and stuff we're going to update these storage variables in our call anything contract from another contract just by doing this binary calling if you will right so let's compile let's go to deploy we can actually leave this up right we can leave this up is let's deploy our call function without contract we'll pass it as an input parameter the call anything contract address we'll deploy it now in here I can call the transfer function directly by you know maybe I'll switch it to this this contract address this new contract address and it will give it a new number of one two three right and we'll click call transfer function and then we go back up here we see that this has indeed been updated now doing this call stuff is considered lowlevel and it's a best practice to try to avoid it when you can so if you can import an interface it's much better to do it like that because you're going to have the compiler on your side you're going to be able to check to see if your types are matching and all this other stuff so usually doing these low-l calls some security auditor Checkers might say hey like this Spooks me out a little bit you you doing this lowle stuff but with that being said you have just learned a ton about lower level solidity this is some really advanced stuff and like I said if this was hard if you're kind of confused here don't worry you can always come back to this section and try it again when you're a little bit more advanced if you want to try to understand it all now awesome absolutely we've left some links in the GitHub repo associated with this lesson that I definitely recommend you check out one of the ones you should definitely check out it's going to be this deconstructing solidity by open Zeppelin it really breaks down exactly what's going on behind the scenes of a contract if you want to learn more about op codes about lowlevel stuff definitely give this a read it is a phenomenal read essentially it breaks down a little bit more than what we went over here a couple other videos as well and I've left a whole bunch of links in here too now we can finally go back to what we were talking about with metamask and that decoding the transaction data and all this weird stuff if we come to a contract address and this is we this is a contract that wraps native eth and turns it into an erc20 token but if we come to a contract right we hit write contract let's connect to web 3 sure you don't have to actually do this just feel free to follow along with me we're got to open up our mams let's go to zolia here going to connect here okay cool and we want to call transfer from right and let's just add some stuff in here let's do Source address and you know this this is probably won't go through because I don't have any weth right now but let's just hit right right this transactions metam mass is probably be like hey this is going to fail whatever yeah sure whatever but when we get a menam mass transaction that pops up if we scroll over to the hex we scroll down we can now actually start to understand what is going on here and this is what we always want to make sure is actually correct when we're working with our menam mask and when we're dealing with all this so what we can do is we can actually copy this whole thing and pull up our terminal here I'm just going to make this nice and big here what we can do is we can do cast D help we hit cast help and we scroll all the way up there's a command in here called call data to code to code ABI encoded input data so if we do cast D- call data decode like this we can see we need to pass in a Sig and the call data so luckily for this transaction our metamask was smart enough to know that we're calling the transfer from function but sometimes it's actually not going to be smart enough to figure this out so that's where we are going to need to match what we expect this to be calling to to what it's actually calling right so first off we are expecting this to be calling the transfer from function so I can grab this function selector which we just learned come back here I can do cast Sig and I'll pass pass pass in here transfer from the whole function signature which What It Takes a address address and a unit 256 so we'll do address address 256 and we'll see that this is what the function selector should be so I can say okay great the two of these match this is indeed calling the function selector that I want it to call okay awesome if it doesn't match what can happen sometimes again we can go to something like the Sam CZ Sun signature database or open chainx yz/ signatures paste this in hit search and we can see that there's actually two different functions that have the same signature one is transfer from and one is gas prite bit ether with an INT 128 so what's interesting here is you can't have a function with the same function selector so if I actually went into remix e.org let's actually create a new contract called conflicting doou right and we'll do a little little zoom in here spdx license identifier MIT contract conflict I made a function called transfer from with an address U 250 or address High U 256 low U 256 sub public like this and then I also have a function function with this one gas prite bit ether paste it in here gas prite bit ether into 128 Su public and I try to compile this guess what's going to happen compile oh what pragma solidity 0. 8.18 this should be an address to and now I try to compile we scroll down it'll say function signature hash Collision for gas price bit ether you can't have a contract solidity where two functions have the same function selector so in any case we could be calling one of these two functions on our this is where it's important to actually go through the contract code and say h okay there could be a couple different function selectors here let's make sure it's the one that we expect right so in any case so this is calling this transfer from function if this contract has a gas bit gas price bit ether it might be calling that but in any case we know so we could go through the code right we go through transfer from okay great there's a transfer from function that is indeed what we want to call function selector is working perfect okay so now that we've verified the function selector we should also verify the rest of this stuff so now that we know what the function selector is and we know what the function signature is we can take this whole hex here and go back into our terminal and use that call Dat decode so we can say cast -- call data decode we can see what it what we need we need the Sig and the call data so it'll hit up the Sig is going to be transfer from and it takes an address an address and a ENT 256 right we can just double check that address address address un 256 sure does and we can paste in that call data and hit enter and we can see what this call data stuff is using for input parameters to that function so it's our address our address and then 1000 and then if that's what we expected so let me reject this for now go back to right and that and if that's what we wanted to call on this function we would go ahead and put this through this is especially important when we're using front ends like for example if I wanted to use Unis swap right let's go ahead and connect here to metamask yep connect looks good go away go to let's say if I was underneath Main I wanted to swap eth for so so I'm on a test net here so obviously nothing's showing up but when I hit swap if I was on a real network with real money what I want to do then is do that same process of going through and checking to make sure that the transaction that it's sending is actually the one that I want it to be sending right so if we want to be absolutely sure of what our transactions are doing we can first check the address we can take these exact steps to say I know exactly what transaction I know exactly what function my transaction is calling so we check the address to make sure that the contract is what we expect it to be and then we can read the function of that contract that we want we check the function selector that we're using so that it is so that we know that it is indeed the function that we're calling and then we decode the call data to check the parameters that we're sending so this is how we can actually make sure our wallets are doing what we expect them to do and you think hey Patrick why doesn't our wallet just do this by default and I agree it should at the moment there's projects being worked on one of them is fire where they get some of the transactions right but more wallets are being created right now that actually decode these call datas by default and I hope more of them show up so it's easier to be safe we've seen people send transactions not checking every detail of the transaction and sure enough it was a malicious transaction right so you want to make sure you check the details of your transaction especially when you're sending and working with a lot of money guess what we just learned a ton this lesson and you learned ways to be safer with your wallets which is even more exciting so let's do a quick recap of all the things we learned because I know we learned a whole heck of a lot so first off we learned about what an nft even is right and we created our own basic nft which had all the main functions that we needed the token URI which pointed the metadata we had a mint nft function and all of that we stored our nft on ipfs we learned about the difference between ipf storing on ipfs which is going to be a little bit cheaper versus storing on versus storing our metadata on chain which is going to be a little bit more expensive but it's going to be a more decentralized version of our we also briefly touched on filecoin and R weave which are two decentralized storage platforms that we could alternatively use instead of ipfs or instead of actually even storing on eth Main and just point to our filecoin or R weave implementation we didn't show you how to do that but those are definitely resources for you to check out we learned a couple more cheat codes in our scripts we can actually read from files and we were able to base 64 in code our files to a data URI we learned about base 64 encoding as well which something cool in itself we learned how to call anything even if we don't have the interface all we need is the function signature we learned what this ABI on code with selector finally is we learned about function signatures function selectors we learned all about the different types of encoding and the different things that you can do to actually encode your data and what is really going on when we send transactions and then finally we learned exactly what's going on under the hood when we have a transaction so we can even start viewing some transactions on our block Explorer scroll down to more details and we can even see what input data people have sent with their transactions so if I go to one of my accounts and I select one of my previous transactions for example the enter raffle from a previous lesson I go click to see more and we can see the method ID or the function selector here enter raffle is going to be this and I can view this as the original which shows the input data is just this and I can go ahead maybe I could go to the Sam CC Sun database hit enter it looks like this sure enough this function selector is for enter raffle and we learned how to decode hex data so we can actually make sure the transactions that we send in metamask are secure now is a perfect time to take a break take some rest go get some ice cream go get some coffee tweet at me on Twitter because you're so excited that you learned all these super Advanced methodologies just by you getting this far I'm being 100% honest you are better you have learned some skills that even some top solidity devs don't even know so you are growing incredibly quickly and we're not even done we've got a few more lessons left we're going to get to the most advanced section next which is going to be this Foundry defi stable coin I'm probably going to combine these into one or two lessons instead of three then upgrades and then governance and then introduction to security but you are on your way to becoming a phenomenal smart contract developer so take that break you need it you deserve it and I'll see you in the next one all right welcome back welcome to the defi section of this course we scroll all the way down here Foundry defi we can see the code that we're going to work with for this course now I got to say ahead of time defi is an absolutely massive topic quite frankly that deserves an entire video of itself so we're just going to give you a brief rundown of what defi is what you can do with it and some of the most popular apps out there so first to get started we can use this site called defi llama to get a snapshot of what's going on in the defi world right now the total value locked in defy some of the dominant apps and what the dominant Protocols are doing for me we can look at some some of these top five for now too L is a liquid staking platform which not going to go into right now maker Dow is a CDP or a collateralized debt position protocol for making stable coins which is what we're going to be building a is a borrowing lending protocol like an open- Source decentralized Bank curve Finance is a decentralized exchange more specifically for working with the stable coins and then Unis swap is a general purpose exchange for swapping tokens and different types of assets so me if you understand some of these top ones as you go down the list you can get more and more intricate or more and more specific different types of def5 protocols the beauty of Defi and decentralized finance is that you get access to sophisticated Financial products and instruments in a decentralized context if you're not super familiar with financial terminology some of this might be a little bit difficult to grasp but it is a phenomenal Rabbit Hole to go down and it is a absolute ton of fun there's so many cool things you can do in Defi and in my mind defi is one of if not the most interesting and most important industries and applications that smart contracts enable so I highly recommend you get used to some defi some great places to learn about defi are going to be places like bankless which has a podcast that I listen to again like I said metamask learn to learn more specifically about wallets and safety about wallets and honestly so many more most Concepts that you've learned in web 2 or traditional Finance translate over to defi really well one of my favorite things to tell people to do is to try out a and Unis swap to really see how some of these protocols work so if we scroll down here we can go to the website same thing with this one scroll down we can go to the website here in a we can even launch the app and we could see what this app even looks like let's go ahead connect our wallet here I'm going to switch to I'm going to check my chain that I'm on we're on tooa testnet if you look about the top one thing that's really cool is you can see this little ipfs thing here this little ipfs thing only happens with brave but it means that this site is also hosted on ipfs right web 3 all about decentral but if we scroll down we can see we can supply different assets and get an interest rate on those assets if we Supply them for example if we were to supply usdc which is a United States dollar Peg stable coin we'd get 2.45% interest similar exactly to how a bank account works the reason that we get this interest is because there are other people who are borrowing these assets again similar to a bank and they get charged in interest rate for borrowing these assets so if you supply assets you get given an interest rate and if you borrow assets you get you have to pay some interest rate this is why this protocol is so cool it's permissionless banking permissionless borrowing and lending of assets Unis swap is another really cool application where you can very easily swap tokens between each each other for example let's if I were to switch to ethereum mainnet I could choose something like eth and swap to an asset the a governance token and it's a permissionless decentralized exchange and really enables access to financial markets in a much more transparent more accountable and fair way and I just get absolutely excited about working with these for those of you looking to get started here I definitely recommend trying to use some of these on test Nets unfortunately not all of these work on test Nets but I have a couple videos that shows actually working with some of these that we can that we can go ahead and actually watch such as leverage trading in defi become a defi Quant flash loans with a which is an advanced defi tool and a couple of more and when working with these I don't recommend doing this on the ethereum main chain I would recommend doing something like polygon optimism or arbitrum where it's going to be a lot cheaper to make transactions ethereum fees right now are too high and that's why we have scaling with layer twos like arbitrum and optimism one other thing that I should absolutely mention now that we're getting into defi is that there's this topic that we're not going to have time to go over called meev me or minor extractable value or maximum extractable value depending on who you ask is something that plagues the defi industry and something that a lot of eth core devs and protocols like flash spots are working on right now basically the concept is if you are the validator who gets to order the transactions in a block you can order those transactions in such a way that benefit you there are a lot of different protocols working on mitigating me and preventing meev in the future or making it more fair and there's all types of opinions on me I 100% recommend that if you're looking to go more into really deep me more into really deep defi stuff you check out this flash.net new to me repo and check out some of these videos and blogs they are absolutely astonishing to read they are a ton of fun to read and also show a terrifying side to the ethereum world as well but in any case the project that we're going to be building in this course is going to be a stable coin now the concept of stable coins is a bit of an advanced topic believe it or not maybe you've heard some stuff about it maybe you haven't in any case we're going to watch a video that I made previously about stable coins and what they really are and what a lot of mainstream media actually gets wrong about them and by doing this we as developers are going to have a much better understanding of what these stable coins really are and how they actually work under the hood this is going to be a tough lesson I'm going to say this straight up it's going to be very difficult there's a lot going on here I want you to be absolutely sure to go to chat jbt and ask chat TBT questions absolutely in the GitHub repo associated with this course be sure to use this discussion Tab and ask a lot of questions in fact if you want you can even browse around the maker Dow Forum which is the protocol behind the die token which is what our project that we're going to build is very roughly based off of and kind of read what people in the industry are actually working with and actually doing like I said there is a lot to Defi and this project that we're making I'm actually planning on getting audited after we release this course and this is easily going to be our most advanced project in the course hands down even though we have a couple lessons after this upgrades governance in introduction to security this Foundry stable coin project is the most advanced product we're working with hands down if you're able to go through this and understand everything in this lesson you should be incredibly proud of yourself and Incredibly excited to move forward because this is a hard project and that's okay take your time don't overburden yourself there's a lot to go through here if you've never understood defi take some time and look into defi if we go to Google we look up like learn defi we get a to coin Telegraph article get some medium articles maybe even udy coinbase coinbase actually has a great article on this there's a lot of places to learn about defi so yes I do recommend if you're completely unfamiliar with defi pause the video now take at least 15 20 minutes just to do some Google searching around right any knowledge that primes you for this next section is great and there's really just so much to defi the main thing is that defi is permissionless open-source finance and to me it is the absolute best thing about smart contracts with defi we can actually move away from financial institutions and products that have no transparency that don't help you that have centralization risk in the last 20 years have been a history lesson on why we need defi to take over the world so definitely want you to do a little bit of research here here so let's do a walk through the code and then let's walk through this video on what stable coins actually are so here's our code base if we go into SRC we see two main files we have decentralized stable coin. soul and if we look into here it's a real minimalistic very basic is erc20 we've got some more interesting more advanced Imports such as erc2 burnable and ownable but here it looks real similar to an ec20 right we've got a Constructor with ec20 we have a burn function where we can actually burn tokens remove tokens and we have a mint function where we can mint and print new tokens but the main contract is this DSC engine. Soul so this decentralized stable coin is controlled by this DSC engine and this has a ton of stuff in here some of the main function ality in here is going to be where we deposit collateral and mint DSC so this stable coin is going to work because it's going to be backed by collaterals that have monetary value we'll talk about more about that in a minute you can redeem your collateral remove your collateral look at all this natat spec by the way look at all these these comments we can burn DSC we can burn our decentralized stable coin people can get liquidated what the heck is liquidation we'll talk about that later they can mint DSC if they have enough collateral and we'll talk about collateral soon deposit collateral redeem collateral Etc but there's a whole bunch of collateral stuff and we'll explain that in a little bit we have this test folder where we have our unit tests where we go over engine where we test the engine the stable coin and also this Oracle lib thing we have mocks which we know mocks are and then we have this thing that we kind of briefly went over which is fuzz test and we have this invariant thing that what is this invariant thing and we have this new type of invariant underscore tests which we're going to go over and we're going to explain these invariant tests separate these invariant tests in my mind separate mediocre solidity developers from incredibly powerful incredibly Advanced solidity developers we've got our scripts as well real minimal here we mainly just deploy the stable coin we're going to be using chain link price feeds to measure the price of the underlying collateral again we'll talk about that soon but this is really the the highle walkthrough and you can find all the code and all the information you need on this repo like I said this is going to be an advanced section take your time with it be sure to ask questions use all the tools you have at your disposal to code along and understand what we're doing but the other reason why I want to make a stable coin here is because I strongly believe stable coins are going to be one of the most important def5 Primitives or def5 products that web 3 has to offer and in my opinion right now the current Solutions aren't good enough so hopefully this inspires some of you to go out and build a better one but let's go ahead let's go into this video let's learn about stable coins and take your time learning this all right let's watch this video when you research stable coins today you get a lot of misleading information and that's what we're here to clarify today in this video we're going to teach you everything you need to know about stable coins but actually what are stable coins why we care categories and properties designs of top stable coins and then the real reason behind what they do what stable coins really do this video is for both everybody Technical and non-technical and we're going to correct a lot of the misleading information out there there's going to be a lot of information here for people less familiar with defox so as always don't be discouraged if something doesn't make sense the first time you hear it buckle up buckle up dum dum we're in for a volatile ride about stability a stable coin is a nonvolatile crypto asset that's it fleshed out we could refrain it to a stable coin is a crypto asset whose buying power fluctuates very little relative to the rest of the market and this is the first place where we disagree with traditional media if you Google what is a stable coin you'll see something like this response everywhere stable coins are cryptocurrencies the value of which is pegged or tied to that of another currency commodity or financial instrument and to that I disagree I think that's an easy initial way to understand them but not the whole story a stable coin is a crypto asset whose buying power stays relatively stable a good example of buying power would be an Apple Market if you went to a market to buy apples with Bitcoin 6 months ago the number of apples you could buy would be drastically different than the number of apples you could buy today that's an example of buying power changing and not being very stable however someone buying apples with dollars would probably be able to buy the same amount of apples 6 months ago to now that's an example of buying power staying relatively the same since we could buy the same amount of apples today than 6 months ago a do would be considered a more stable asset whereas Bitcoin would be much less stable this is what we mean by buying power an asset whose price fluctuates rapidly all the time is a poor example of stable buying power oh it went to zero this for example would not be a stable asset now a stable crypto asset is just a stable asset that's a cryptocurrency most cryptocurrencies by Nature aren't stable but we will give examples of stable coins so summary here a stable coin is a crypto asset whose buying mind power stays relatively the same and if that's all you take from this video Perfect great let's keep going now why do we care about stable coins because money is important but not like I Love Money type of important in everyday Society we need some type of low volatility AK a stable currency to fulfill the three functions of money and for web 3 we need a crypto version of this the three functions of money are storage of value unit of account and medium of Exchange storage of value is a way for us to keep the value and wealth we've generated putting dollars in your bank account or buying stocks cryptocurrencies is a good example of storing your value apples would make for a poor storage value since they would rot over time and lose their value unit of account is a way to measure how valuable something is when you go shopping you see prices being listed in terms of dollars this is an example of the dollar being used as a unit of account pricing something in Bitcoin would be a poor unit of account since the prices would change all the time medium of exchange is an agreed upon method to transact with each other buying groceries with dollars is a good example of using dollars as a medium of exchange buying groceries with car tires would make for a poor medium of exchange since car tires are hard to transact with in order for our everyday lives to be efficient we need money to do all these three things and like I said in web 3 we need a web 3 money we need to be able to know the value of stuff in web 3 be able to pay for things things without prices going crazy and we need to be able to store our wealth in web 3 in a decentralized world we need a decentralized money assets like ethereum work great as a storage of value and medium of exchange but fall a little bit on their unit of account due to their buying power volatility however maybe in the future as ethereum because more adopted it'll become stable and we won't even need stable coins but right now it's a little too volatile and yet I'll still tell you it's ultra sound money since I do think it's an amazing store value but that's a conversation for another time banket don't kill me I'd love your content also if you're here be sure to like And subscribe because we're just cooking the fire up and we are about to pop off anyways okay so now we know what a stable coin is why we care let's talk about the different categories of stable coins and here is the second place I strongly disagree with traditional media if you search for types of stable coins you'll get something that pulls them into categories like this Fiat collateralized crypto collateralized commodity collateralized and then algorithmic now this isn't too bad of a categorization it does make it easier for new people to understand but I think it paints a in acccurate picture so let's categorize stable coins but actually the categorizations that I like are relative stability stability method and collateral type so what are these categorizations let's start with relative stability when we talk about stability something is stable only relative to something else the most popular type of stable coins is pegging or anchored stable coins and these are stable coins that are are pegged or anchored to another asset like the US dollar tether D and usdc are all examples of US dollar pegged stable coins they Follow The Narrative of one of these coins equals $1 and that's how they stay stable it's stable because they track the price of another asset that we think is stable and most of these stable coins have some type of mechanism to make them almost interchangeable with their pegged asset for example usdc says that for every usdc token printed or minted there is a dollar or a bunch of assets that equal a dollar in some bank account somewhere so the way it keeps its value is that at any time you should be able to swap your usdc for the dollar or at least hypothetically so something like d on the other hand uses a permissionless over collateralization to maintain its Peg but we'll get to understanding that a little later however a stable coin doesn't have to be pegged to another asset it can be floating remember to be considered a stable coin its buying power just has to stay relatively the same over time so a floating stable coin is floating because it's buying power stays the same and it's not tied down to any other asset with this mechanism you could hypothetically have a stable coin that's even more stable than an anchored or Peg stable coin let's look at an example let's say I can buy 10 apples for $10 today but in 5 years I can only buy five apples with $10 so it would cost me $20 to buy 10 apples this isn't an unheard of phenomenon to happen and it's commonly just referred to as inflation now let's introduce a stable coin whose buying power floats up and down with the market for now let's just pretend it does so magically and let's call it applecoin today you can buy 10 apples with 10 Apple coins and in 10 years you can also buy 10 apples with 10 Apple coins which one of these assets would you say is more stable yes the Apple coins buying power stayed the same over the 5 period so we'd say it's a more stable asset even though it's not pegged to something like a dollar and Yes stable coins like this do exist and they use a lot of clever algorithms to do this one such example is the Ry stable coin by reflexor Labs how Rye Works might be its own video but we've left some links in the description for you if you want to learn more about how it works because this concept can be a little hard to grasp to further explain it let's go through another analogy let's look at the anchor and the buoy in this image which of these do you think is more stable the anchor or the buoy well it depends on what you're comparing them to compared to sea level the buoy is more stable since it'll always be at sea level as the water level rises and Falls the distance between the anchor and the sea level is constantly changing the buoy is an example of a floating stable coin now if we compare these two to the ocean floor though the anchor is more stable of the two since it'll always be right on the ocean floor this is analogous to a pegged SL anchored stable coin now if we're going to be really serious with this this analogy then the question might be well what happens when a storm comes or what happens when the water's crazy or the Tide's crazy or something and to that I'd say you're right and a stable coin needs to take extra precautions to take these into account and maybe get the average sea level over the course of time and most popular floating stable coins have some mechanism to account for turbulence like that summary Peg stable coins are tied to that of another asset while floating stable coins use different mechanisms to keep the same buying power over time number two stability method the stability method is this mechanism that keeps the coin stable if it's a peg stable coin what is the pegging mechanism if it's a floating stable coin well what is the floating mechanism and it typically revolves around minting and burning the stable coins in very specific ways and usually refers to who or what is doing the minting and burning these are on a spectrum of governed to algorithmic in a governed stable coin there is a governing body or a centralized body that is minting and burning the stable coins you can imagine the maximumly governed and least algorithmic coin would be a single person/ entity minting new stable coins promising that the coins are not volatile but it could also be an organization like a government or even a dow choosing to Mint and burn new coins these govern coins are typically considered centralized since there's a singular body that is controlling the minting and burning you can make them more decentralized by introducing a dow and that kind of makes them more algorithmic but we'll get more into that later coins like usdc usdt and T USD are examples of of governed stable coins on the other hand an algorithmic stable coin is a stable coin whose stability is maintained by a permissionless algorithm with no human intervention and this is the third place where I disagree with traditional media a coin like dy I would consider much more algorithmic than govern because uses a permissionless algorithm to Mint and burn tokens whereas traditional media might say an algorithmic stable coin is always under collateralized or follow seniorage shares or something like that but an algorithmic stable coin is just when a set of autonomous code or algorithm dictates the minting and burning there are zero meddling humans would have been mine if it hadn't been to those meddling kids examples of algorithmic stable coins are going to be Dy frax rye and yes the $40 billion disaster us yes we're going to talk a little bit more about classic us and Luna now a token can have algorithmic and govern properties in the same way that it can be somewhere in the middle of being floating and pegged D for example does have an autonomous set of code that dictates the minting and burning but it does also have a dow where they can vote on different interest rates and what can be collateral types and different things like that so technically it is a hybrid system it has some governance mechanisms and also some algorithmic ones usdc would fall purely in the governed category because it's controlled by a centralized body us and Luna would fall almost purely in algorithmic the dirt roads block has some amazing takes on these pieces and a wonderful visualization of wearing a spectrum of coins that are more algorithmic or govern they use dumb as the opposite of algorithmic instead of govern which probably isn't wrong most classically categorized Fiat collateral stable coin almost all fall into the Govern or dumb section since they are dealing with fiat currency and you need a centralized entity to onboard that Fiat to the blockchain you'll also notice on this chart they have anchored versus reflexive on the x-axis that's referring to how the collateral type affects the stable coin and collateral type is what we're going to cover next so the summary here though is algorithmic stable coins use some sort of autonomous permissionless code to Mint and burn tokens whereas a govern stable coin have some human interaction that mints and burns the coins and keeps them stable now before we go into our final category let's look at this chart again we could replace the word anchored with exogenous and reflexive with endogenous and we'd have a chart that shows collateral type versus stability mechanism which brings us to number three collateral type now when we say collateral we mean the stuff backing our stable coins and giving it value for example usdc has the dollar as its collateral and it's the dollar that gives the usdc token its value because you hypothetically can swap one usdc for $1 D is collateralized by many assets for example you could deposit eth and get minted die in return and US was in a roundabout way collateralized by Luna exogenous collateral is collateral that originates from outside the protocol and endogenous collateral originates from inside the protocol so one of the easier ways to Define what type of collateral protocol is using is to ask this question if the stable coin fails does the underlying collateral also fail if yes it's endogenous if no it's exogenous if usdc fails the protocol does the underlying collateral the dollar fail no so the protocol has exogenous collateral if the usdc stable coin fails the dollar is going to keep being the dollar if die the stable coin fails does the underlying collateral eth also fail no so the die system is exogenous the value of eth isn't dependent on the value of D if us fails does the underlying collateral Luna Tera fail yes absolutely and this is exactly what happened that caused the system to lose $40 billion in what seemed like a day exogenous collateral originates from outside the protocol endogenous collateral originates from inside the protocol two other good tests that you can ask are was the collateral created with the sole purpose of being collateral or does the protocol own the issuance of the underlying collateral if the answer is yes to either one of those then it's endogenous collateral now the traditional media usually says that algorithmic stable coins are to blame but I think what they're really referring to is endogenously collateralized table coins it makes sense that they can be scary and potentially dangerous because their value kind of comes from nothing exogenously collateralized stable coins are typically over collateralized meaning there's more value of collateral than there is of the stable coins here we have another image from dirt roads comparing different stable coins the exogenous versus endogenous collateral of the protocols and how much they have maker Dow diey has almost all exogenous collateral frax which is another stable coin we haven't really spoken about too much has a mix of exogenous and endogenous collat and the old teral Luna and US system had mainly endogenous collateral which is how the system was able to crumble so quickly so yeah endogenously collateralized stable coins don't have a great track record so why would you want to make one well the answer is scale and often times people also say Capital efficiency with exogenously collateralized stable coins the only way can mint more stable coins is by onboarding more collateral you can only have a stable coin market cap that is high as high as that is the value of all your collateral so if you want to have $68 billion in stable coins that that means you need to have $68 billion worth of collateral and that's a lot of money that you would need to on board to your system if you have an endogenously collateralized stable coin you can have 0 worth of collateral meaning it's much easier to become massive faster now I agree with the dirt roads publication when they say that exogenously collateralized stable coins can't scale and I talked more about that in the blog associated with this video so if you're interested be sure to check that out after the rest of this video but watch the rest of this video cuz we're just getting started in the blog we also talk more about seniorage shares and shelling coin logic which if you're interested in that stuff definitely check it out most of these endogenous coins can be traced back to a paper written by a man named Robert Sams where he talks about how to build an endogenously collateralized stable coin using a senior shares model which again I'm not going to go into but I wanted to mention it because it's probably one of the most influential paper when it comes to these endogenously collateralized stable coins endogenously collateralized stable coins there a lot of words now there's more information on the endogenous collateral debate in the blog but let's do a thought experiment that I do think is compelling for endogenous collateralized stable coins indogen usly collateralized stable coins imagine you have a currency and it's collateralized 100% by gold and you run a bank and it's open 24/7 to allow people to exchange your generic coin for gold in your vaults people love the convenience of our stable coin instead of having to Lug around their gold so they treat our stable coin as if it was gold because they know that at any time they can exchange it at the bank this is an example of our generic coin being exogenously collateralized by gold pegged to its price and governed by us by Me by our entity since we own the issuance and burning of the coin you come to our bank we'll issue this coin or we'll burn it once you redeem your gold and since you can always Exchange change our coin for gold our coin keeps its value now let's say the bank is only open 5 days a week does our coin lose its value now that you can't always exchange it for gold well probably not the market probably won't even care now let's say you need to close the bank for a week for renovations does our coin lose its value now well let's say we close the bank for a month or a year or a decade forever if we get to the point where you can never actually exchange our coin for gold or the underlying collateral again maybe do people just use the coin as its currency backed by nothing in a way now it's moved from being exogenous to now being endogenous since it's now backed by well itself this is why dirt roads has reflexive on their chart one of our coins is no longer equal to some amount of gold it now equals one of itself okay I know there's a lot here and there's even more in the blog so if some of this confused you don't be discouraged you can always come back there's a ton of supporting documents and blogs and links that I personally watch to learn a lot of this as well so be sure to use that if you get confused but now let's look at some of the top stable coins what their properties are and then we're going to get to some really interesting stuff we're not going to go too deep into the architectures of these stable coins we are going to go over die a little bit more though because the die/ maker di system is a pretty standard model for what a stable coin could look like and it was one of the most influential stable coins ever created so there's that and it's important that we go through these so we can understand what's currently out there and why they're currently out there and then we can reveal why they're really out there why they're so many stable coins what are the incentives for people to Mint them and it may just blow your mind so let's start with Dy as we've mentioned before Dy is a pegged algorithmic and exogenously collateralized stable coin it's one of the most influential D5 projects ever cre ated and was a huge factor in supercharging the def5 space roughly the way it works is you deposit eth or some other crypto collateral into the smart contract that has this die algorithm code and based off the current collateral to US dollar or eth to US dollar price it'll mint you some amount of dye you can only mint less dye than the total value of collateral or E that you have this way the system always has more collateral than they'd have minted dye additionally every year or so you'll get charged something called a stability fee usually around like 2% and now you're free to do whatever you want with your die if you want to get your eth back you have to give your die back to the smart contract which will then burn your die it'll use the current price of e to figure out how much money it should give back to you it's because of this stability fee and collateralized eth that people often refer to this system as a collateralized debt position since we technically owe die back to the protocol at some point so yes all the Dy that's in existence somebody minted from the maker protocol and needs to pay it back at some point if you can't pay your stability fees or the price of e tanks and now the value of our collateral is less than the value of the die that we minted people can liquidate us which means they can take our collateral protocol always needs to have more collateral than meant to die so this is sort of your punishment for not keeping the collateral up and a way to save the system from becoming under collateralized and then there's also a maker token that's used to vote for stuff now the reason I give this overview is I want your brain to be asking the question hey uh I get charged to Mint a stable coin all the die in the world somebody's being charged to have it out there someone could take my collateral if I don't monitor the balance and most importantly why would I spend money to Mint this stable coin why would I be the one to do that great question that is the fundamental question and we'll get to that usdc usdc is a classic pegged governed exogenously collateralized stable coin it's backed by real world dollars in a bank account not much else to say here USD and Luna the classic old us and Luna we know it collapsed but we can learn from what happened to hopefully prevent it in the future us was a stable coin pegged to the dollar algorithmic and endogenous and it imploded on itself using what we know about stablecoins can you guess why well since the system was endogenous once Us lost its Peg Luna became less attractive to hold since people weren't holding Luna the price fell and it made it harder to keep the peg of us which made Luna's price fall which makes us harder to hold its bag which makes you see the pattern people still want to try using these endogenously collateralized stable coins because they do scale so quickly so protocols like fra have come a long way to do some type of hybrid between endogenous and exogenously collateralized stable coin Ry Ry is one of the few floating stable coins where it's not pegged to any other asset it's focused on minimal governance being floating and using only ethereum as their type of collateral with a nearly purely algorithmic stability mechanism in a way one could argue that because their collateral is only eth the price of Rye will always be somewhat pegged to the price of eth but that might be a longer argument due to these it's floating algorithmic and exogenously collateralized now they use some really cool supply and demand mechanisms to keep the price stable and nonvolatile but it's not really important how it works for the purpose of this video so once again I'm going to leave some links in the description if you want to learn more about Ry the video on screen right now I think is particularly good at explaining exactly how it works and explaining why it's such a good stable coin for normal average people to have so now that we've gone over some stable coins we've gone over the categories why we care what is a stable coin let's talk about what they really do we can start by asking the question okay which one of these is the best stable coin and to that I need to add ask the best stable coin for who centralized governed coins obviously have the issue of centrality which sort of defeats the purpose of being in web 3 so maybe we want some flavors of algorithmic stable coins maybe that's probably what we want for web 3 but these algorithmic coins might feel untested to non- crypto people and the fees associated with them might be a little bit scary for me personally like I said I really love the idea of Ry the idea is to have stable buying power as opposed to being pegged to some other asset and algorithmic nature as opposed to being centralized so it's a decentralized stable coin that's what we want but every coin has their trade-offs and I'd argue there is definitely no best coin right now the stable coin that's best for the average person might matter much less it's the stable coin that's best for Rich whales might be what's more important here yes the stable coins the whales like might be what's more important now for most algorithmic stable coins you'll see this some sort of fee associated with minting the coins protocols do make money off of the stable coin systems which I think is good sometimes they need money for maintenance incentives for the stability of the coin or money for improvements so I do think these fees are good and we need stable coins for the three functions of money storage of value unit of account and medium of exchange but are you going to be the one to pay these fees to Mint them and keep them in circulation someone has to pay to Mint these coins and often keep paying the market cap for some of these stable coins is in the billions if there is a 1% fee on these and the market cap is 1 billion we're talking about $10 million are average people going to collectively pay $10 million a year to keep these in circulation no so average people aren't printing these for the three functions of money well then who is minting these so let's play a little thought experiment let's say I have eth as an investment and I've bought up all the eth I've sold my house I've sold everything I own and I've used everything I have to buy ethereum but I want more what can I do I can put my eth into one of these stable coin protocols get the minted stable coin and then sell the stable coin for more eth you might have heard Concepts like Leverage investing or margin trading and this is essentially the web 3 equivalent it's kind of funny why are stable coins good well because we need those three functions of money but why are stable coins minted well because investors want to make leveraged bets in fact most stable coin platforms have this as one of the biggest reasons to Mint their stable coin to multiply exposure or to maximize your position on some crypto asset now for sophisticated investors this isn't new information at all this is like investing 101 however it does feel weird that we need stable coins for the three functions money but that's not why they're minted so even though I said I really like Ry as a stable coin for the people a reason D might be high market cap is that investors like The Leverage opportunity much more than they like the leverage opportunity that Ry offers it could be something else but that might be a big reason how much stable coins are minted are based off of how much investors think they can use that stable coin to get more exposure to assets that they really want so I know we've gone over a lot here and the rabbit hole really doesn't end there curve. Finance being one of the most important protocols for stable coins is a really interesting story as well my friend Garrett who teaches about technology and finance has a fantastic example as to why a stable coin exchange might be so important you might wonder how a stable coin exchange ever got off the ground is there really any demand out there to trade $1 for $1 then I think back to my university days one weekend my laundry pile grew so disgusting I was desperate to use the washing machine immediately but the laundry machine took quarters and I only had dollar bills quarters were in such short supply around the dorm room that I was willing to pay more than $1 for four quarters in this urgent moment I had specific utility in mind and that changed my personal equation for this and a and curve both look into launch their own stable coins soon is going to be really interesting as well so we'll just have to see how these unfold I do think though that we are going to get better and better at creating these stable coins because we do need them they are important and for you developers watching who want to build one of these we have some minimal stable coin contract examples in our defi minimal repo Link in the description so if you're looking to tackle this problem definitely be sure to get started there I'm really excited for the future of Defi and for the future of stable coins as I think they are a wildly important primitive for Defi and I know that this was a long video but I hope you all learned something and I hope this gives you a better idea of what stable coins really are and how they're created if you learned something leave a comment in the comment section if you didn't learn something leave a comment in the comment section or if I got something wrong leave a comment there thank you all for watching and I'll see you next time all right we have now learned a ton about Defi and hopefully I piqu your Curiosity on how much more there is still to learn but now we're going to move on to creating our own stable coin here so again you can follow along with all the code that we're we're going to be going over in this Foundry defi stable coin f23 section of this course and like I said I'm planning on getting this code actually audited so be sure if you have your GitHub repo be sure to watch this repo and look for updates I will be posting the audit reports in this as well I've got a couple videos on what smart contract audits are and why they're so important and I'll leave a couple links in the get AO associated with this course for those of you looking to go down the security track definitely be sure to watch this video but all right we are finally in our GitHub repo let's build this stable coin mkdir boundary defi stablecoin f f23 let's open this up with code or you know the drill file open folder we're going to be going a little faster this lesson because a lot of what we're doing is just going to be drilling in information that you already know we have a couple of new things to go over such as stateless fuzzing which we'll talk about in a bit but a lot of the coding aspect of this you already know all right we're in our folder Forge knit clear let's make a little read me over here and talk about the design of our protocol so we're going to make a stable coin but if you watch that stable coin video we're going to make a stable coin that is one anchored so when we're talking about the relative stability it's going to be anchored or pegged to the US dollar so this means we're going to have to put some code in here to make sure that our stable coin is always worth $1 number two the stability stability mechanism or the way we do minting is going to be algorithmic this means that this is going to be a decentralized stable coin there's not going to be any centralized entity that's going to Mint or burn or maintain the price this is going to be 100% onchain and algorithmic which is ideally what we have for the future of stable coins there's no controlling entity that controls our stable coin so this is great A Better stable coin for web 3 probably is an anchor to or pegged it's probably floating but that's a much harder mechanism to do so we're going to go ahead with the anchored or Peg for the moment and then finally the collateral type is going to be you guessed it exogenous and it's going to be crypto collateral we're going to use cryptocurrencies as collateral for this currency we're going to use ethereum and Bitcoin as the collateral for our system here so with this being our architecture we're going to keep this in mind okay how can we actually make sure that this is always pegged to a dollar and one way we can do this is with a chain link price feed so with the chain link price feed we get the price feed and we set a function to exchange eth and Bitcoin for whatever their dollar equivalent is and this way if right in our contract we have this exchange set up price of this stable coin should hypothetically always be around a dollar to make the stability mechanism algorithmic we're going to say people can only mint stable coin with enough collateral and that's going to be coded directly into our protocol and the collateral type being exogenous of course we're only going to allow these two types of cryptocurrencies to be deposited specifically we're going to use WRA eth and wrapped Bitcoin so the erc20 version of eth and the erc20 version of Bitcoin some might argue that this wrapped Bitcoin is a little bit centralized depending on who is onboarding the Bitcoin into ethereum but that's another conversation so over collateralized stablecoin with we and Bitcoin as the collateral for this let's do this so the first thing we're going to do is we're going to well we're going to get rid of all these goodbye goodbye goodbye delete and now we're going to create our two main contracts new file d eend centralized table coin do a capital c. soul and this is just going to be the actual token so I'm actually going to copy paste my layout of functions because I like them I like to have this and at the top of course spdx license identifier MIT if you want you can just copy this directly from GitHub repo associated with this course SRC right here copy the layout here I like to have it as a reference then you already know pragma solidity 0.818 and we'll do contract decentralized stable coin boom like this and now this is going to be one of the main differences between this code we're writing here and all the other products that we've done we're going to be very verbose with our code documentation and the reason for this is is when it comes to security Prof professionals who are going to review this code we're going to make their lives so much easier if we have a ton of text explaining what our code is doing additionally if you work with AIS AIS are fantastic at reading and understanding language so the more language that we have to explain what our code should do the better off our code can be sent through some AI model to make sure that it doesn't have issues so we're going to go ahead add a little bit of natspec here right from the GetGo at Title dentra by stablecoin all one word at author Patrick Collins or put your name here Yep this is open source MIT license you can do whatever the heck you want with it I'm even going to say collateral exogenous eth and BTC minting or the stability mechanism is going to be aloric meaning it's decentralized relative stability it's going to be tegged to USD then I'm going to say under here this is the contract meant to be governed by DSC engine this contract is just the I'm going to toggle word rep here erc20 implementation of our stable coin system so that's what this is going to be this decentralized stable coin is purely going to be an erc20 with minting and burning and stuff right it's not going to be it's not going to have any of the logic the logic is going to be in a separate contract so let's go ahead and let's make this so first Constructor boom and we're going to use op Zeppelin to get this kick started so right at the top import well actually before we even do that Forge install open Zeppelin slop Zeppelin D contracts d - no- commit and we go ahead we went ahead and installed that now we're going to open up our Foundry DOL we're going to add some remappings in here so REM mappings equals atop Zeppelin SLC contracts equals lib slopen Zeppelin contracts SLC contracts that looks pretty good right up at at the top of this now import little named import erc20 we're going to import this erc20 burnable contract I'll explain this in a second and then also erc20 from at open Zeppelin contracts token erc20 extensions slc20 burnable doou did I spell this right looks like that's right so what did I oh oops looks like I spelled contracts wrong let's spell it right okay cool that looks good now what we're going to say is that our decentralized stable coin let me even zoom out a little bit Yep this is going to be a big one so we're going to zoom out a little bit here hopefully you all can see this is ec20 burnable okay and the reason that we're going to use this contract if we command clicking it or just look it up is it has this burn function and we want this burn function because this is going to help us maintain the peg price we're going to be burning a lot of these tokens you'll understand that in a bit now same as in erc20 so the erc20 burnable contract is an erc20 which is why we can import the erc20 contract from it as well and the erc20 burnable Constructor is an erc20 which means we have to use the erc20 Constructor as well which takes a name where we're going to call ours decentralized stable coin and DSC like this and that's it this is going to be our whole Constructor we're not going to touch it that's all we're going to do let me zoom in a little bit I'm going to keep zooming in and out hopefully it's not too crazy now we want this coin to be 100% governed by our engine and our engine is going to have all this stuff about what collaterals to use how to use it what to Peg it to Etc this is purely just going to be the token so since we want this token to be 100% controlled by our logic we're going to make this ownable as well which means we're going to have only owner modifiers where the owner is going to be that immutable logic we're going to create so open zeppin has a package for that too so we're going to do import ownable from atop Zeppelin contracts access SL ownable doso I'm going to copy this so our contract is going to be erc20 burnable and it's going to be ownable and there's going to be two major functions that we want our engine to own those functions are going to be function burn where it takes in a un 256 uncore amount public we're going to override the burn function in burnable this is going to be only owner so that only the engine only the logic that we give it can mint and burn and we're going to say U and 256 balance equals balance of message. sender and we're going to make sure that somebody when somebody tries to burn some token they at least have that much token so we're first of all going to say if the amount is less than or equal to zero then they can't burn right we don't want people to try burning zero that's silly so we're going to revert with an error put all of our errors right up at the top here error decentralized stable coin underscore underscore must be more than zero like this so we're going to revert with this error and then we're also going to say if the user's balance is less than the amount that they're trying to burn then we're going to revert with with another custom error I'm just going to copy paste and I'm just going to say burn amount exceeds balance boom paste it in like this and then finally we're going to do this thing called super. burn which we haven't talked about yet so this super keyword basically says Hey use the burn function from the parent class which in this case is the erc20 burnable so all of this code is going to run it's going to hit this line it's going to say hey go to the Super class and use the burn function there so our codee's going to go oh okay well erc20 burnable that's the super class or the parent class ah just use the burn function in here which calls the burn function here in the erc20 sole which does all this stuff in here so that's what the super keyword does only owner only engine's going to add this now we're going to do this function mint this is going to be an address 2 and a uent 256 amount this is going to be public excuse me this is actually going to be external also only owner this one probably could be external as well but that'll come out in the audit external only owner and this is actually going to return the Boolean when you do mint you want to have a return of Boolean here when you do a mint we're going to return true if it actually works but we're going to say if 2 equals equals address Z we're going to do a little sanitization of the inputs here then we're going to revert revert with a new error error to Central stable coin not zero address we're not going to let people accidentally mint to the zero address because that happens kind of a lot and we're going to say if the amount is less than or equal to zero then we're also going to revert with this more than zero error here boom and then finally we're going to return true oh and then obviously we should run mint _ 2 commcore amount so we're not overriding any functions in here right we're just calling the mint function over here we had to do super because we're overriding the burn function and we're saying hey do all this stuff and then do the regular burn there is no mint function there's an underscore mint function that we're going to be calling and guess what that's it this contract's done we're not doing anym here Forge build cool and then we probably want to write some tests for this write a deploy script but we're going to do all that in a little bit now what we're going to do is we're going to build the engine the engine to the car the main components of this contract you want to take a break and be proud of yourself right here go for it if you want to even pause the video start writing some of your own tests write your own deploy scripts go for it but let's go ahead and start building this engine we're going to be building this a little bit different than some of the other projects we might even be testing some of this along the way to make sure we get things right so I'm going to go ahead create a new file d s c n g n. Soul centralized stable coin engine and let's build this engine to this car all right let's go back to let me grab I'm just going to copy paste this beginning part let's come to the engine P that in we have spdx lay of contracts prag musil contract DSC engine this let's give this a lot of natspec all right title DSC engine I don't want that at author athor Patrick Collins the system is designed to be as minimal as possible and have the tokens maintain a $1 maintain a one token equals equals $1 Peg toggle the word wrap this stable coin has the properties Jus collateral dollar pegged alori algorithm get stable it is similar to die if die had no governance no fees and was only backed by wrapped eth and wrapped Bitcoin at notice this contract is the core of the DSC system it handles all the logic for minting and redeeming DC as well as depositing and drawing collateral at notice this contract is very Loosely based on die on the maker Dow DSS die system you might be asking Patrick that's a lot of text here yes we want a lot of text when people read our code our code should be readable remember your code is going to be written once read hundreds of thousands of times I have read the A and maker code so many times times and so many other people have as well you want your code to be very verbose so that other people can come and understand what's going on so let's begin so let's think about what are the main functions that our project should have what are the main things that we should do right before we start even start coding anything and often times a lot of people will take this step and will actually create an interface for their code they'll create an interface and say hey here's all the functions that I want this to do and then they'll say hey our contract is that interface so that they don't forget any of those functions for us I'm just going to go ahead and write them out here so I want one function to be function deposit collateral and mint DSC I want people to be able to deposit their die or their Bitcoin and mint our DSC token I want people to redeem their collateral or DSC right when people are done with doing whatever they want with stable coin they can turn the stable coin the the DSC decentralized stable coin back in for whatever collateral they originally used I want people to be able to function burn their DSC and the reason for this is if they're nervous that they have too much stable coin and not enough collateral and they want just a quick way to have more collateral than DSC they can quickly burn stuff which is another part of the system we should even put a point in here our DSC should our DSC system should always be over collateralized at no point should the value of all collateral be less than or equal to the value of all the DSC or the dollar backed value of all the DSC we should always have more collateral than DSC in the system at all times and we need to code in such a way so burn DSC is a function that will make more sense in a little bit we should have a function called liquidate and this is going to be a really important function the reason that we're always going to have more collateral if the value of their collateral drops too much let's say let's say I put in $100 worth of eth and I minted $50 worth of DSC I have more collateral than DSC that's good what what if the eth price tanks to $40 40 eth now we are under collateralized right now we have less eth than we have DSC and keep and this user should get what's called liquidated they shouldn't be allowed to hold a position in our system anymore so ideally we set some threshold that's too low maybe it's maybe it's 20% and if you hold $60 worth of eth at $50 worth of d DSC you should get kicked out of the system because you're way too close to being under collateralized this liquidate function is going to be the function that other users can call to remove people's positions to save the protocol and we'll talk about that a little bit more very soon and we're going to want a function Health Factor this should be an external view function or excuse me get health factor and this will allow to see how healthy people are so let's go back up to this example here so if if the price of eth dumps to $40 we're now $10 under collateralized right and that's not good that's really bad we never want this to happen so what we can do is we can set a threshold to let's say for this example 50% or 150% so if you have $50 in the system you need to have at least 75 eth at all times this way there's a little bit of a buffer that way we can never be under collateralized if the price tanks here if you go to $74 now what we can do is we can liquidate and we can say hey if someone liquid if someone pays back your borrow your minted DSC they can have all your collateral or a discount so maybe we say hey somebody pay back this 50 DSC and you can have this $74 worth of eth somebody's going to be very incentivized to do this because they're going to make 20 $24 so we'll set some threshold maybe 150% and we'll we'll say hey anybody who liquidates your position if you're under the threshold they can have as a reward some of your extra collateral and this will incentivize people to always have extra collateral otherwise they're going to lose way more money than they borrowed if that didn't make sense so one more time let's do that example so if I min so if I put down $100 worth of eth as collateral and I mint $50 worth of DSC now I'm going to go off and do whatever I want with DC price of my eth tanks to $75 or better yet let's say $74 some other user is going to see oh my God under collateralized and we're going to let people liquidate their positions if they become under collateralized based off the threshold some other users going to see that and they're going to say okay I'll pay back the $50 of DSC I'll pay back the $50 of DC so now this person has zero debt and in return get all your collateral so now this person has $0 worth of eth and this user got the $74 and all they had to do was pay $50 of DSC to get $74 of eth so this person is now up just made $25 or $24 by liquidating you they're incentivized to make money and this is your punishment for letting your collateral get too low so hopefully that makes sense if this system of liquidations doesn't make sense to you you know where to go come to the GitHub repo assess with this course and start joining the discussion all right so hopefully this made sense if it doesn't use the discussions tab of course now these are kind of this combination function we're probably going to want a function just called deposit this deposit collateral external we're probably going to want a function redeem lateral external and then we're probably going to want along with a burn DSC we're probably going to want a function mint DSC external and these look like these are probably going to be the majority of what a protocol does and what a lot of people even do is sometimes they'll even write tests right now describing what each one of these should actually do to the system right we're not going to do that but we may actually write some tests as we go along here and I like to write my deploy script kind of early and you'll see me do that here that way I can write test using my deploy script so let's go ahead though where is the best place to start tackling this well to me the easiest place to start is actually with the depositing right because that's the first thing people are realistically going to do with this protocol is actually deposit the collateral so I'm going to start there so for this deposit collateral function what are they going to want to do here well we're going to need to let them pick what collateral they want to deposit so we'll say address token collateral address and then also the unit 256 amount collateral we're going to do a little toggle word rep all right cool so deposit collateral the token collateral address and then the amount that they're going to want to do so already we can see that there's going to be a whole bunch of stuff that we're going to want to do here so let's even doce a little bit of natspec bit aspect here we'll say at pram we'll just explain what the prams are and this is where get up copilot is really helpful because often times it's really good with docs so we're going to say Pam RM so both of those are good token collateral address the amount of token to deposit as collateral amount collateral the amount of collateral to deposit right real simple so we're going to want a couple of things here we're going to want to sanitize this a little bit so the amount collateral we're definitely going to want this to be more than zero so we're probably going to want a modifier called more than zero that we can use throughout these functions sometimes people might accidentally send a zero transaction we want to automatically revert those so we scroll up to the top here we see our modifiers come before our functions so we're going to create our modifiers here and we're even going to add like a little little section A whole bunch of these here boom boom modifiers like this cool and we'll say modifier more than zero and this modifier will take a un 256 amount and we'll just say if amount amount equals equal Z then we're going to go ahead and revert with a new error where do errors go let's scroll to the top errors go right underneath Imports actually it's not quite right they're going to go right underneath the contract so what we're going to do we're going to copy this whole section going to say errors we're going to go here we're going to say error DSC engine uncore uncore what do we want to call that but just needs more than zero needs more than zero this and we're going to revert with needs more than zero and of course add the little underscore here cool so now we have a more than zero modifier so we can make this external more than zero and we'll pass the amount collateral and boom okay cool we're doing a little sanitization here what else should we do you know what let's even copy this we'll paste this here we'll say functions and we're going to have a Constructor so I'm just going to put this here for now Constructor should spell Constructor right and then we're going to have a section after functions like a Subs section we're going to call it external functions this external functions cool cuz we want to go receive and fallback we're not going to have those but then external and public so external function first anyways okay more than zero got that and we probably don't want people to use any collateral right we probably only want them to use certain collateral that we allow so we're going to have to create a new modifier called is is allowed token so we're going to do modifier is allowed token this is going to take a address token basically we're going to say if the token not allowed the token isn't allowed then revert right however at the moment we don't have like a token allow list so let's create that this is probably going to be a state mapping so let's scroll to the top where do state variables go so errors type Declaration state variables okay errors great let's put it here State variables okay and let's do our let's create an allowed list of mapping so we'll do mapping address to BU you know private sore token to allow and we could do this however I already know that we're going to need price feeds so instead what I'm going to do is I'm not going to do an address to BU I'm going to do an address to address and this is going to be our price feed mapping so this going to be sore price feeds and normally I do the syntax token to price feed right well for this one we're just going to call this price feeds and we're going to use the newer solidity named mappings to make this a little bit clearer so I'm going to say address token maps to address S price feed now this is S price feed and anybody can look up and go ah okay so this is token to price feed cool so we're going to have this list of price feeds and where should we probably set this well we're probably going to want to set this up right in the Constructor right right when we deploy this contract that's when we're going to say okay these are going to be the allowed tokens these are the price feeds and that way it's going to be like that forever right we're never going to be able to change this so what we'll do is in our Constructor now we'll take in in the the allowed tokens and their price feeds right because in order for this system to work go to like data. chain. Link in order for this entire system to work if we want to know how much value our ethereum that people deposit in here is worth we need to have the pricing right the only way for us to know if we're over collateralized if we know the value of our eth in our Bitcoin so we're going to use these two price feeds to maintain that because these price feeds are going to be on different addresses on different chains you already know that we got to parameter tize it so we'll do an address array memory token addresses comma address array memory price feed addresses as input parameters and we're going to say token address zero maps to price feed zero token address one Maps the price feed one Etc and while we're in here I already know that our DSC engine is going to need to know about our decentralized table coin why because our DSC engine is going to need to know to call burn and mint so in here in the Constructor this is also where we're going to pass the address DSC address decentralized table coin address and so in here let's do some sanity checks on this we'll say if the token addresses. length does not equal the price feed addresses price feed address is price feed addresses length we have an issue right because if there's more tokens or more price feeds that means we mess something up so we're going to go ahead and revert with a new error go to our errors here we'll say error DSC engine uncore uncore token address is and price feed addresses must be same length it's a massive error I know but I like being verose like I've told you before form so if those don't match we're going to go ahead and revert then we're going to Loop through the token addresses and update our mapping that we just created here to say okay the token address is mapped to the price feed address now in order for us to get a pricing we're going to have to use the USD price feeds and everything every price feed that we're going to have to use is going to be the USD back to price feed so for example it's going to be eth USD BTC C USD mkr USD Etc okay so we're going to Loop through we're going to say four U 256 I equals z i is less than hoken addresses. length i++ so we're going to Loop through this token addresses array and we're going to say sore price feeds of token addresses I is going to equal to price feed addresses of I so we're going to set up this price feed so whatever the token so the token of I is going to equal the price feed of I and that's how we're going to set up what tokens are allowed on our platform if they have a price feed they're allowed if they don't they're not allowed and then I know we're going to do a lot of stuff with our DSC so this is where this is definitely going to be an a mutable variable so we can scroll up make a a mutable variable we'll say so we'll say d centralized stablecoin private iore DSC because we're going to make this immutable and since we're using decentralized stable coin we're going to have to go ahead and import this so let's scroll to the top here do import decentral stable coin from decentralized stable coin. Soul so now decentralized stable coin private idsc you can now do oh excuse me this is going to be private mutable go bit down to the Constructor we're just going to say idsc equals decentralized stable coin DSC address like that again using GitHub copilot if you don't have GitHub co-pilot that's okay there's a lot of other free AIS that you can use as well Okay cool so we set up our Constructor we're going back down to deposit collateral whole reason we were doing this is we're saying okay we should only allow certain kinds of collateral on our platform so now we can create a new modifier called is allowed token where we can just say if sore price feeds of token equals equals address zero then we can go ahead and revert with a new oh that looks like a good one DSC engine token not allowed I'm just going to copy that go to the top and thanks get up copilot just autofilled it in for me okay great and then of course we need to do this down here so is token allowed more than zero is allowed excuse me is allowed token token collateral address like this all right cool and then additionally I'm going to add a nonreentrant modifier here as well we're going to grab this from open Zeppelin whenever we're working with external contracts it might be a good idea consider making your function non-reentrant re-entrance are one of the most common attacks in all of web 3 and to be honest sometimes I'll just rip a non-reentrant modifier even if I'm pretty certain it's not vulnerable to re-entrancy attack I feel like to be honest most functions should be non- reentered by default but especially when working with external contracts it's a good idea to maybe put this modifier here now this might go to audit and we might say hey well we don't need this non-reentrant modifier and maybe we get rid of it but maybe we don't the trade-off is it's a little bit more gas intensive to have this here but it's also safer so I'm just going to stick it in here even if I'm pretty certain I don't need it we're going to get this from open Zeppelin has a non- reentrance a nonreentrant modifier from their re-entrancy guard so we'll import actually my GI co-pilot automatically had it reany Guard from open Zeppelin contracts security reany guard. Soul yep that's actually exactly correct and then what we can do is scroll down and we see our DSC engine is re-entrancy guard by doing this we now have access to this non-reentrant modifier and now this function is non- reenable which is what we want okay cool now we can finally start doing some collateral stuff so we're going to go ahead and deposit this collateral first thing we're going to need to do is a way to track how much collateral somebody has actually deposited so what's that look like well that probably looks like a mapping to me so let's go to the top we'll create a mapping of address user to mapping of an address token to un 256 amount private sore colateral deposited so this is a mapping to a mapping crazy right so we're going to map the users balances to a mapping of tokens which is going to get mapped to the amount of each token that they have all right so let's scroll back down to our deposit collateral function so now we have a collateral deposited mapping so we can do s collateral deposited of message. sender of this token collateral address now that we know it is an allowed collateral address it's going to be plus equal to the amount collateral right and and I'm actually run into an issue here where when I do Forge format formats the code look like this but right now when I'm saving it's reformatting in a different way so what I'm going to do is it looks like it's using a different formatter that I don't like so I'm going to go to the extensions solidity hard hat hit the settings here extension settings and we're going to change this from prettier to forge because I want to use the forge format settings now if I hit save okay great it saves and formats the way I wanted to okay great so as you can see here we're updating state and what should we do when we update State we should emit an event so we're going to emit collateral deposited we're going to have it be the message. sender who is depositing the token collateral address and the amount bilateral as well which means that we have our first event all right so let's go on up here and zoom back out scroll all the way up to the layout where do events go events go after the state variables okay so I'm going to copy this they go right after the state variables before the modifier so we're going to say events we're going to go here we're going to say event and get up copilot automatically filled it in for me awesome address indexed user address index token un 256 amount we don't really need to index that maybe we do why not let's just index it all right cool and just to know a keyboard shortcut that I use a lot is control back or control minus which allows you to go back to the last spot you were in your code if you do control shift minus it'll go forward and I use this all the time so for example if I'm way down here in my code and I hit control back I'll just go right back to the last place my cruiser was and I use this all the time I'm not sure what the keyboard shortcut on Windows or Linux is but on a Mac it is control back and control shift back and I use it all the time anyways so we are in deposit collateral we have this submit here we finally have the event and Okay cool so we're updating the collateral internal record keeping we're admitting EV vent now of course we should actually get the tokens right and you can see here we're following CI right so we do a little notice follows CI checks effects interactions so all the checks are happening in our modifiers here these are all the checks our effects are right here and then finally our external interactions so this is where we're going to do that transfer from and we're going to need to wrap our collateral as an erc20 so we're going to need to call transfer from on it so I'm going to go ahead and import I erc20 from at open Zepp contracts SL token erc20 ierc 20. Soul contrl minus to go right back down to here isn't that nice and we can finally IR C20 of the token collateral address do transfer from message. sender to address this amount collateral like this and we'll say so this function actually returns a Boolean bull success and we want to make sure that this is actually being true so we want to say if not success we'll just revert DC n uncore transfer failed like this what's this an error you bet it is so we're going to put this at the top airor DSC engine transfer failed and I'm going to hit control minus to go right back down to the code that I was working with Okay cool so this function looks pretty good to me I'm able to deposit collateral in here and update our mappings now might be a good time for us to start writing some tests for this right and we could do something something similar to what we did before where we just kind of threw together a real quick setup in our unit test and then had our integration tests be what our deploy script actually uses well let's write a couple more functions first and then we can go ahead and and do all that work so we have a way to deposit the collateral okay awesome what should we do next well the next thing that we should do is have a way to Mint our DSC token right once they deposit the Al they should be able to Mint the DSC token and then the combination of those two will be this function deposit collateral and mint DSC so let's go ahead and actually create this mint DSC function CU now that they have some collateral we should be able to Mint some DSC and now this is actually going to be a surprisingly involved method right because in order to Mint DSC we need to check if the collateral value is greater than the DSC amount and this is obviously going to involve a number of things things right it's going to involve price feeds we're going to be checking values we'll be checking a whole lot of stuff okay so this is actually going to be a little bit more of an in-depth function here so let's create this mint DSC function and we'll have this get pass in a un 256 amount DSC to Mint people can pick how much DSC they want to Mint so let's say for example someone deposits $200 worth of eth maybe they only want a mint $20 worth of DSC right so they can pick how much they want to Mint here so amount to Mint here and let's add some checks here we should have the mint more than zero Mount DSC to Mint this what else we probably want this to be non- reentrant even though we probably don't need this to be non re-entrant because it's our DSC token but let's put it in here anyways it's probably all we need for now we probably want to do some looks like G up co-pilot even gave me some some follows CI yes oh that's wrong amount DEC to Mint amount DSC to Mint the amount of decentralized stable coin to Mint at notice they must have more collateral value than the minimum threshold we're going to figure out what that means in a second so mint DSC we'll need to keep track track of how much everybody has minted right so whenever they're minting DC they're in a way they're minting debt right so we're going to need to keep track of that where can we do that well we can do that as a state variable so we'll do mapping of an address user mapped to their U 256 which is going to be an address user mapped to the U 256 Mount DSC minted it's going to be private s underscore DC minted this now I can go back down here with this new mapping sdsc minted message. sender plus equals amount DSC to Mint so we're going to keep track of all that they minted again this is going to follow CI so now we want to do a little check here if they minted too much for example like they minted $150 or $150 worth of DSC but they only have $1100 worth of eth that's going to be way too much we should 100% revert if that happened so I'm actually going to make a function going to make an internal function called revert if Health factor is broken with the message. sender being sent so we're going to create this new internal function so up here we have external functions we going to scroll down here we're going to make this private and internal functions this this and we're only going to be able to call this if we're only going to be able to call this internally right so we're going to create this function function revert if Health factor is broken address User it's going to be an internal view function and we're going to basically one check Health factor which is basically do they have enough Catal right and then revert if they don't have a good health Factor so this health factor is actually a term that I borrowed from the a documentation for each wallet these risk parameters enable the calculation of Health Factor you can see a little bit of an image here that shows it so additionally we're going to need to make a function that checks the health Factor actually these are going to be private and internal view functions so first we need to make a function that can get the health Factor so we're going to make another function here called function underscore Health Factor we're going to take an address user and you see we have this leading underscore to tell us as developers that this is an internal function so let's actually give this in underscore as well FK oops Health Factor this will be a private view going to return a u into 256 so what this health Factor thing is going to do give it a a little bit of Nat speec yeah we can say this is going to returns how close to liquidation a user is say if a user goes below one then they can get liquidated so we're going to figure out what the ratio of collateral to DSC minted that users can have with this health Factor function we're going to be building a lot of stuff here so in order to figure this out what do we need well we're going to need to get both their total DSC minted right and we're going to need to get their total collateral value right not just the total collateral we're going to need to get the total collateral value to make sure the value is greater than the total DSC minted so we're going to have to make another function we're going to need to get the UN 256 total DSC minted and the UN 256 the lateral value in USD we're going to create a new function called get count information from that user so we're going to do another one boom function undor get account information like this we're going to take an address user this will be a private View and we're going to return two things un 256 total DSC minted and U 256 six collateral value in USD two functions here to get the total USD that's easy right we just do total DSC minted equals this array this excuse me this mapping that we just created right we're keeping track of this exactly so all we got to do is this to get the total collateral value in USD we're going to need to do some more math so I'm going to say collateral value in USD equals get account collateral value and we're going to pass some user so this is going to be a different function and we're going to make this a public function so that anybody can call this function themselves so we're actually going to copy this private and view internal functions public internal View and then we're going to do View and pure public and external functions all the way at the bottom we'll say private instead of we'll say public and external view functions we'll do function get account bilateral value address of the user this will be a public view so that anybody can call it returns a uent 256 stay with me I know we're kind of going down this tree stay with me here we're about to go even further now to get the actual value what do we need to do well we need to Loop through each collateral token get the amount they have deposited and map it to price to get the USD value so we're going to need to Loop through all the collateral tokens uhoh do we have a way we can do that let's scroll to the top well we have a mapping of price feeds but we don't have a way to Loop through them so what we can do is we could just have like you know address we and then address address wrapped BTC we could just have two tokens like this we would have to Loop through anything we're going to make this system a little bit agnostic so that you could deploy this with any amount of stable coins any amount of collaterals so we're going to make a new state variable it's going to be an address array private sore collateral tokens and what we're going to do is right in our Constructor when we update our price feeds with the token and the price feed we're also going to add the tokens addresses of I to this array now we have this array of collateral tokens that we can Loop through and that way we can calculate how much value people have based off of all of the tokens so get account collateral value we're going to say four U 256 I equals z i is less than S collateral tokens. length I plus plus address token equals s collateral tokens of of I and we'll get the amount so this is the token that we're working with we'll get the amount by un 256 amount that is deposited by this user by sore collateral deposited user token like this then total collateral value in USD plus equals uhoh now that we have the amount we're going to need to get the USD value of this and this is probably a function that we're going to want to have public so that other people can use this as well so create a function get USD value or somebody passes in an address token un 256 amount this will be a public view returns us 256 and this is where we're going to do some price feed stuff some stuff that's very familiar so we're going to need to get the price feed for the token and then times the amount by the price so we're going have to work with aggregator V3 interface again that chain link data feeds so import and I know we've worked with this before agregator V3 interface from it looks like get up co-pilots got my back at chain link contracts blah blah blah this means we're going to have to install that remember we can install the smaller one with Forge install Smart contract kit SL chain link brownie contracts at 0.6.1 D- no- commit like this chain Le brownie contracts awesome then we're going to have to go to our founder. add some remappings in here so we're going to put a little comma we're going to say at chain link SLC contracts equals lib SL chain link brownie contracts SL contracts like that so now we have the aggregator V3 interface scroll down to the bottom get USD value I know we've done this before I know this is familiar to a lot of you but we're going to say aggregator V3 interface price feed equals aggregator V3 interface of sore price feeds of the token so we're going to get the price feed of the token we're looking to get the value of now we have the price feed here we're going to do this WOW get a co-pilot spot on we're going to get the price by calling Price feed. latest round data and this is where we're going to do a little bit of math right let's say one eth equals $11,000 The Returned value from CL will be 1,00 Time 1 E8 how do I know this well if I go to docs. chain. link go to data feeds I can scroll down on to price feed addresses and I can see if I do show more details for eth USD eusd it has eight decimal places and I know Bitcoin USD also has eight decimal places we could add some code in here so that we make sure we're getting the right decimals but I'm just going to go with eight for now and now we can do a little bit of math here so we're going need to do the price times the amount right but is this all we need do turn price times amount no because the number is going to be way too big right let's say the price is a th000 Time 1 E8 and now we're multiplying that by let's say the the amount is a th000 times 1 E8 because it's going to be in way this number is going to be absolutely massive right so first we need to multiply this a th by a number to get this number to match this one so these need to be the same units of precision so that's going to be we're going to have to multiply this first by 1 E10 and because I don't like magic numbers we're going to scroll the top create a new state variable right on here we're going to do a u 256 private constant additional feed Precision equals 1 E10 like this and now it's not a magic number so instead of doing this now we're going to say okay price and we'll we're going to wrap it as a u into 256 so that everything's down 256 we say the price first needs to be multiplied by the additional feed Precision so that now both of these are U and 256s and they both have 1 E18 but then we're going to have to divide all of these by 1 E18 as well so that this number doesn't look super wonky so we're going to have to wrap this whole thing by 1 E18 and as I hate floating magic numbers like this so we're going to scroll back to the top copy paste this this is now just going to be called Precision 1 E18 grab Precision divide by Precision so u56 price times additional feed Precision times amount divided by precision and we should be good to go here this is where my brain immediately goes okay definitely need to write some tests for this so once we finished going through this we're definitely going to read we're definitely going to write some tests at least for get USD value here so let's go back up through our massive tree of functions that we just created that are not complete so let's go back to get account collateral value and this is going to be the total us the total collateral value in USD is going to be get the USD value of the current token we're on times the amount that we're working with ph Cal value in USD actually let's put that there boom and that's it right so we just Loop through all the tokens in the token array and we just add up the value and USD of each one of these tokens and I know we don't need a return here but I'm going to add a return here anyways return this so cool so now we have a way to get the collateral value in USD we needed that way up here oops let's do collateral value in USD get collateral value oops let's do this and awesome so now our get account information is going to return the total USD minted the total DSC minted and then the total value of all the collateral here okay great and we can scroll up again we have this revert if Health factor is broken which is still busted because this function doesn't do anything but now we can actually have it do something because we have this health Factor here we're going to update our health Factor function because now we have the two of these what we can do is we can just just get the ratio of these two so we could say collateral value in USD / total USD minted this is what we're going to return for a health Factor right well not quite so let's say we minted we have 100 collateral divided by 100 DSC right this is one: one if we go down a we go down a penny we're going to be under collateralized right and we don't want to go under collateralized we always want to be over collateralized because if this ever goes below 100 our system is is bunked up right so we want to set the threshold to be like hey if you go under 150 lateral you can get liquidated right so we go under 100 it's already too late so we want to say hey we want you to go at least 150 so we're going to create a liquidation threshold and we're going to do this at the top so we're going to say unit 256 private constant liquidation threshold equals 50 and this means you need to be 150 or no this means you need to be 200% over collateralized I think might be 150 but we'll find out in the test so now if we go back down to where we were to get our health Factor we're not just going to divide these two and even this doesn't really work because if we have 150 over 100 1 15 / 100 is equal to 1.5 decimals don't work in solidity so it would just be one I guess that would work but we want we want to know exactly what the health factor is right with Precision so first off let's instead of just doing this let's say U into 256 collateral adjusted or threshold equals the collateral value in USD times liquidation threshold and then we should divide by 100 right because the liquidation threshold has is multiplying it's making our number much bigger so we should divide by 100 as I don't like floating numbers so we'll do un 256 private constant liquidation Precision equals 100 so we'll go back down divided by the liquidation Precision so now we have this collateral amount adjusted for this this threshold right so now you can kind of think of it as instead of say we have $150 of eth divided by $100 of DSC right this would be 1.5 but now they need to multiply by 50 as well but now this collateral value is multiplied by essentially 1 over five right let's let's do the math here right if we had say $1,000 of eth we just times that by 50 which gets us to 50,000 but then we divide by that by 100 which equals 500 so if we had $1,000 of eth * 50 was this ID 100 is 500 same thing with this this example down here if we had $150 worth of each eth we say 150 * 50 equal 75 ID 100 equal 75 and then if we do 75 divid by 100 that is going to be definitely less than one right so we we're basically saying with this 50 threshold 50 over 100 is essentially 1 over two we're saying you need to have double the collateral in here so yeah so now that I'm talking it out loud this 50% liquidation threshold means we need to be 200% over collatz right we need to have double the collateral that we have the minted DSC anyways so whole bunch of math hopefully this makes sense if not definitely work with your AI to make sure this makes sense or ask questions in the discussion right I know some of this math can get a little bit tricky here so collateral adjusted for threshold and now we can return the collateral adjusted oops this collateral adjusted for threshold times Precision divided by that total DSC minted now this will give us our true Health factor and if this is less than one you can get liquidated now this is one example right let's look at another example let's say I guess this is two examples so let's say they have $1,000 worth of eth and 100 DSC right so let's do the math here 1,00 * 50 = 501 23 / 100 is equal to 500 500 divided 100 which is definitely greater than one right 500 divid 100 is five so this person with $1,000 of eth deposited and 100 DSC minted which would have a health factor of 500 nice so now that we have a health Factor we can actually finally do this revert if Health factor is broken function where we say we can even put this above this as kind of like a pseudo npack we could say U into 256 Health Factor equals underscore Health factor of the user and we say if the user excuse me actually let's do user Health Factor and if the user Health factor is less than the some Min Health factor which is going to be one Health Factor let's go ahead and create this let's go to the top because we hate floating numbers you into 256 private constant Min Health Factor equals 1 if the user Health factor is less than the Min Health Factor then we're going to go ahead and revert I don't love this we're going do DSC engine uncore underscore brakes Health Factor we're going to pass in this health factor that we break with boom new air scroll the top Air engine breaks Health Factor un 256 Health Factor back door right looks like we still have some red here what did I forget okay revert if Health factor is broken underscore like this boom now it looks like nothing's red let's just make sure Forge build successful nice okay where were we mint DSC okay mint DSC so we added some more DSC minted and if adding this DSC breaks the health Factor because breaks the health Factor we should revert we should not let anybody mint DSC if they're going to cause themselves to get liquidated I mean we could go ahead and let them do it but like let's not cuz that's not a very good user experience now what we want to do is we want to actually mint the DSC so this is where the DSC has this mint function that's only owner and the owner of this is going to be the DSC engine now we could say and if we look at this mint function it returns a Boolean so we'll say bu minted equals iore DSC mint and what does it take for parameters address two and amount so address 2 is going to be message. sender and amount is going to be amount D to Mint and then we'll say if not minted we'll just say revert DSC engine uncore uncore mint failed and which is a new error scroll to the top error DC mint failed Okay cool so now we have a mint function and we have a deposit function so we can deposit collateral we can mint DSC but additionally we can get account information we can calculate someone's Health Factor we can calculate the USD value of these different tokens so at this point I'm like o I have no idea if what I'm doing makes any sort of sense I want to make sure I write some tests here so this is where we could go ahead and create a new folder unit tests and if you wanted to you could skip writing the scripts and just kind of deploy in your unit tests and then do some integration tests but I'm just going to have my unit test also be my integration test for this one so let's go ahead let's write a script deploy DSC s.o you already know the drill for this spdx license I even zoom in a little bit identifier MIT contract deploy DSC is script import script from Forge STD script. Soul like that pragma solidity 0.818 it's good in here we're going to have our function run external we've done this a 100 times exteral and this is going to returns a couple of things it's going to both return the DS decentralized stable coin and the DSC engine and it's going to return something else but I'm not going to put it in quite yet so to do that we're going to have to import centralized stablecoin from slsrc centralized stable coin. we're going to close and reopen my vs code it's being really weird right now there we go all fixed so the two of these what are we're going to do what we're going to do vm. start broadcast this vm. broadcast this oh and we need the DSC engine import DSC engine from srcds engine. Soul and in here we're going to deploy both of these so we'll say de centralized stable coin DSC equals new decentralized stable coin as our decentralized stable coin have any parameters it does not we're also going to deploy our DSC C or DSC engine engine equals new DSC engine this takes a whole bunch of stuff right this is going to take go to the Constructor token addresses price feed addresses if we toggle oops tle the word wrap addresses price feed addresses and the DSC address so we have the DC address boom it's going to be this one where do we get the price feed addresses and you guessed it we're going to make a helper config so what does this DSC engine need instructor an array of token addresses an array of price feeds and then the DSC address so where are we going to get those addresses from you guessed it a helper config so new file helper config dos. Soul spdx license identifier MIT pragma solidity 0.818 contract helper config is script import script from Forge sd/ script. soul for now let's do this on the sepolia Chain so we'll do struct Network config what do we need in here we're going to need an well we're going to need we and wrapped Bitcoin those price feed addresses and those DSC addresses address we USD price feed address wrapped Bitcoin USD price feed again we is the erc20 version of ethereum I've got a example we token contract on zolia and if you look at it right here we go to write contract it's got this function deposit where you deposit eth and it'll return to you an erc20 version of eth to your metamask called we then when whenever you're done with it you just withdraw your eth and burn your we WRA Bitcoin is something similar but with Bitcoin the difference is since Bitcoin doesn't originate on the E blockchain there is some risk in bridging it over but I'm not going to go into that that's something for you to look up so we're also going to need the address of the we token itself we're going to need the address of the r Bitcoin itself and we're going to need a un 256 deployer deployer key kind of like what we did in one of our previous lessons we're going to have Network config public Active network config and then we're going to have Constructor like here we're going to have a function get sepolia eth config public view returns Network config memory this and then we're going to return Network config we're going to have we USD price feed B let's go to doc. chain. link let's go to theia theia where's eth BTC eth excuse me eth USD right here copy that paste comma we're going to need R Bitcoin USD price feed on supp poia bitcoin USD right here gra that we need the we contract address which I have here this is one that I deployed with here we're going to need wrapped Bitcoin and if you're looking for all of these and you want to just copy them out of the GitHub repo associated with this you can go to SRC you can go to script upper config and they're all in here if you want to just copy paste by the way but also wrapped Bitcoin which I guess is this address thought I had a different one well whatever we're going to use this one and if it doesn't work that's fine we're going to use this one and of course player key vm. EMV unit private key like this okay and then we're going to do function get or create envil eth config public returns Network config memory and we're going to do a little bit of mock deployments here but we're going to set if Active network config do wusd price feed does not equal to the zero address then we've already set it turn Active network eth config we're going to do some broadcasting so we're going to need a couple of couple of mocks in here we're going to need some mock price feeds and some mock year cc20 tokens so we're going to need a mock B3 aggregator which we're going to go to test new folder mocks and I'm going to copy paste a mock from this repo if you want to copy paste as well go for it test mock mock V3 aggregator this new file mock V3 agre gator. Soul cool import that import mock B3 aggregator from dot dot SL test slmx slm V3 agregator Doo so we have that we're also going to need some mock ERC 20s we can get those actually directly from open Zeppelin so if we do import erc20 mock from atop Zeppelin contract slmx erc20 mo. soul and if we command click into this or or you open this up you can see there's a whole bunch of stuff in here like we can mint as much as we want burn as much as we want do transfers and stuff we can do pretty much whatever we want and that's why it's a mock token good for testing with so down here vm. start broadcast we're going to create a mock V3 aggregator ethusd price feed equals new mock V3 aggregator and what does this take for the Constructor takes decimals and an and an ini initial answer so we're going to scroll up here we're going to say UN 2 excuse me U 8 public constant decimals decimals equals 8 and we'll say un or not un me int 256 public constant ethusd price equals 2008 and then we're going to do the same thing but instead of eth it's going to be BTC and we'll make this 1,000 to E8 eth USD scroll down all right new mock what does it take control click U into 8 decimals initial answer control minus to go back decimals and then the initial answer those okay oh and let's do vm. stop broadcast now we're going to do erc20 mock we mock equals new erc20 mock what does this one take name symbol initial account initial balance okay say we we message. sender 1008 we probably want to do more than we probably don't want to have these floating numbers in here but it's just a mock it's not a big deal I guess now we're going to copy paste all of this for BTC BTC we're going to say BTC it's going to be the wrapped BTC R BTC WRA BTC like that stop the broadcast and then return Network config we USD price feed is going to be address oh thanks get up co-pilot thanks get up co-pilot thanks get up co-pilot thanks get a co-pilot and this is actually going to be the default Anvil key which if you want you can just go back to here again and copy paste it out of here or you know what we just run Anvil scroll up boom private key right here cancel that say u in 256 public excuse me int 256 public default Anvil key equals B that in and we'll say just use the default Anvil key if you're working with Anvil okay nice so now we have get or create Anvil get aoia let's update our Constructor so we'll say if block. chain ID equals equals 111 55111 then active Active network config equals get sepolia eth config else Active network config equals get or create eth Anvil config nice so we've got a little bit of a helper config here a little semicolon down here this looks pretty good what's wrong here sorry this a ent6 Okay cool so now that we have a helper config we can go finally back to our deploy DSC let's import that in here import upper config from upper config right at the top we'll say helper config config equals new helper config and out of this config we're going to get all this we Bitcoin we rep Bitcoin deyy Etc so I'm going to say address with USD price feed oh I can even just hit Tab and it looks like it has most of it yep W USD rep Bitcoin we rep Bitcoin depl equals config do active Network config cool that's good to me I'm going to toggle word wrap so that it wraps around okay cool we have all of those now our DSC engine takes an array of token addresses an array of price feeds so we can say it's right at the top let's make those arrays we'll say address array public token addresses address array public price feed addresses and we'll say token addresses equals we and W BTC price feed addresses equals we USD price feed address W Bitcoin USD price feed okay cool I think that's everything right yeah so now we can go back to this line now DC engine engine new DC engine and it takes the token addresses price feed addresses and DSC okay cool and then finally something we haven't really talked about too much but this decentralized stable coin like I said it's ownable but it needs to be owned by the engine so this ownable actually has a transfer ownership function and we're going to call that to transfer ownership to the engine we'll go back to our deploy here oh sorry this isn't DSC me address DSC so then we're going to call DSC do transfer ownership to the address DSC engine now only the engine oops engine excuse me only the engine can do anything with it and then we're going to return all these return DC and engine nice oh and the deployer key is going to go here okay cool so the reason we did all this was because I wanted to write my unit tests using actual deploy scripts because I prefer to do that but like I said it might be a good idea for you to write unit tests before you write your deploy scripts and then integration test with your deploy scripts but in any case let's go ahead and finally create a test in here DSC engine test. T.O remember the whole reason we're doing all this I know we've been coding a lot is in the DSC engine we added a ton of functions in here some of them like get USD value which we definitely want to check get collateral account value we want to make sure minting Works our Constructor Works depositing Works Etc so we're just kind of testing as we go along which like I said when I'm actually coding this I did write tests and I did write deploy scripts because I did want to test as I was going right I didn't want to have to go back and refactor and rewrite my code if I made some glaring mistake right it's really good to test while you're building as well and to be honest I I feel like it makes me go faster because I have more confidence that what I did was correct while I'm coding so spdx license identifier MIT pragma solidity 0. 8.18 little carot here contract DSC engine test is test import test from Forge STD test that's all like this all right cool function setup public or external we're going to need to deploy to deploy our contract so we're going to import deoy DSC from do do script SL deploy dc. s.o deploy DSC deployer we're going to say deployer equals new deploy DSC like that again I'm using a lot of tabs here and we're going to say we're going to need the import de centralized stable coin from do do do slsrc decentralized stablecoin doou we're also going to need to import the engine thece from again this is where get a co-pilot could really make your life a lot easier just being able to hit tab here or just whatever AI that you're working with now we're going to say DSC let's actually make these we'll say decentralized stable coin DSC and DSC engine we'll call dsce that's confusing you call this like engine or something I'm going to call my dsce so now our deploy returns DSC and the engine so we're going to say return DSC dsce equals deployer run okay that looks pretty good there's a bunch of stuff more for us to do but at least we have our test set up here here so one of the first tests that we want to do is this price feed test right we want to make sure this get USD value this math that we're doing here because we're doing some weird math stuff we want to make sure this is actually working correctly so I'm going to do I'm going to set up a little price feeds Test Section price tests like this we're going to say function do test get USD value and here we're going to test our get USD value function so it gets past a token address and an amount so we're going to need to get those tokens that we use to deploy this we can get that pretty easily from our helper config so what we can do actually back in our deploy we can also have this return the config and just at the bottom we'll also have a return config Comm a config and config will be the helper config helper config config import that import helper config from dot dot script hel fig. s.o cool and now we can get the we address and we can also get the eusd so we'll put those up at the top two we'll say address e USD price feed and we'll say address we get those from the hel helper config so those are the first two so it's eth USD price feed bitcoin price feed goes here so comma we comma this is the Bitcoin token comma this is deployer key equals config do Active network config cool we have the price feed and we have we so now we can finally go down here we set this function up so we'll say un 256 eth amount equals let's say there's 15 eth right 15 e if we have 15 eth times it by $2,000 for eth equals what 30,000 30,000 e 18 right real simple simple math so let's do that un 256 expected USD equals 3 301 23 $30,000 and we'll say U into 256 actual you USD equals dsce doget USD value we and eth amount and the reason this should work is because in our engine we pass the token and the amount and internally it uses the price feed associated with that token calls the price to get the amount and now we should be able to just do assert equals expected USD and actual USD all right I know there's a lot of set up just to write this one test but like I said I like making sure my deploy scripts are part of my test Suite right from the beginning but it might be a good idea to just do them as integration test so Forge test- m test get USD value and it works now I will point out the first couple of times that I ran this test I actually failed miserably I got a number of things wrong and that's okay because you will and that's why you write tests so I also while I'm here let's also write at least at least one deposit collateral test so let me copy this paste it here because we're going to write a lot of deposit collateral dite collateral test make it look a little bit pretty at least that and we can do some more simple tests like function test revert reverts if collateral uh zero public uh will'll prank a user so at the top we'll do an address public user equals make ADR user this like user Capital user let say bm. start prank our user now we'll at least approve the token can go to the protocol so we'll do erc2 mock we do we have that imported nope we're going have to import that import erc20 mock from atop Zeppelin contracts slash what is it MOX slash or contracts MOX erc20 mock okay erc20 mock doou E320 mock we. approve uh address dce some amount let's do at the top let's make another un 256 public constant amount collateral equals say 10 ether worth of collateral down here we'll approve that 10 collateral and then we'll do vm. expect revert with DSC engine dot we're going to need to use that needs more than zero in here needs more than zero do selector and now you guys know what the selector bit means ds. deposit colat collateral say we zero this and then vm. stop crank and actually this might fail for a different reason but let's go ahead and try it Forge test DM oops okay cool and this actually did pass now if we want to make this a little bit better of a test we should also mint our user some weth and we probably should do that right in the setup so we don't have to do that for every single test what I'm going to do is I'm going to do erc20 mock we. mint user we're going to do a into 256 a constant starting herec 20 balance balance equals and let's say this is 10 ether as well 10 ether starting year20 balance boom all right cool so now Forge test all of our tests are passing cool and like I said I'll do this kind of as a sanity check to make sure that my architecture is even making sense right so we what we probably also want to do next then is have a test for collateral is being deposited in these data structures but for now I'm content with these tests so I'm just going to go back to writing my my contracts like I said there's no one single process and I don't think I've ever written a smart contract completely in one go I'm pretty much always writing tests as I'm writing the code so it is a really good idea to to do this yes you do not have to write the deploy script as you're writing your code but it's something that I like to do and then you know what while we're writing these tests let's also do D- Fork URL sepolia RPC URL let's also do this because this probably will fail actually because we can't just mint we at a thin air and we do indeed fail test get USD value oh interesting that's the one that fails test get USD value ah this one fails because we're hardcoding the expected USD right here and of course the price on sapoia is the actual price as opposed to kind of this fake price that we're making up so we should probably update this test to make it more more agnostic right we probably should update this test so that instead of just hardcoding 3,000 in here update this test to use the price of the actual price feed for now I'm going to leave it as is and then I can fix it later for running those Fork tests so where are we now okay so we have a way to deposit collateral we have a way to Mint we don't really have too many tests here we're just assuming that this kind of works for now which is okay but this is good right we're getting somewhere so we can mint our debt or our DSC we can actually now we can get a whole lot of information as well which is awesome let's now combine these two into kind of this main function that we're thinking a lot of people are going to call this deposit collateral in mint USD right the purpose of this protocol is to Mint this stable coin right deposit collateral and mint DSC which is just going to be the combination of deposit collateral and mint DSC so in here what this this is going to take it's going to take similar stuff to deposit collateral and address token collateral address a u into 256 amount collateral and then also a u 256 amount DSC to Mint right that and here we're just going to call so deposit collateral is external right now we'll make this a public function so we'll change this to deposit collateral where we give it the token collateral address and the amount collateral and then we'll call Mint DSC amount DSC to Mint boom so it's all this function does is just combines the two of them oh and mint DSC mint DSC is not defined as it's external we'll make this public as well so that our contract can also call it toggle word w put that back on okay and cool so this is going to be one of our main functions we're thinking so let's add some n spec to it we'll say at Pam this is where get a co-pilot is really helpful token collateral address the address of the token to deposit as collateral at Pam amount collateral yep at pram that looks good too and then we'll at notice this function will deposit your collateral and and mint DSC in one trans action right because otherwise we're going to have to have people call deposit collateral and then mint but some people they're probably just going to want to do both at the same time because that's kind of the purpose of this protocol okay great so we have a way to for people to get money in how do they get their money out so we're going to need to write this redeem collateral right so in order for them to redeem collateral let's talk about this in order to redeem collateral they need what one their health Factor must be over one after collateral pulled so we're going to want to put some checks in here to make sure that they have enough money in here and that's kind of the main thing right that's all we really need to worry about so let's go ahead start writing this so first we should let them choose which collateral they want so address token collateral address and then obviously the amount amount collateral and we're going to want to add this more than zero modifier in here for the amount collateral we don't want them to be sending accidental zero transactions and because we're going to be moving tokens around we'll just do non- re-entrance better safe than sorry we can figure out later in kind of like a gas audit if this is even needed now I'm going to write this function as if somebody redeeming collateral is the only time they actually redeem collateral however we're going to refactor this in the future to make our code much more modular there's this concept in computer science called dry don't repeat yourself if you find yourself coding the same thing that that should send off a light bulb in your head going oh maybe what I'm doing isn't the best practice so we're going to code this one way and then I'm telling you right now we're going to go back and we're going to refactor this in the future but I want to code it this one way first just to show you the process that you'll probably go through and how you'll probably refactor it when you come across this yourself so we're code this one way now let's do it we're going to need to pull the collateral out and we're going to update our internal accounting so we have this sore collateral deposited of message. sender of the token collateral address right this is the our internal accounting how much collateral they've added we're going to do minus equals amount collateral so this is assuming we're going to pull it out if they try to pull out more than what they have we're relying on the solidity compiler a little bit to throw an error right if in their balance they have 100 and they subtract try to pull out 1,000 right it'll revert because as of newer versions of solidity they don't let you do this unsafe math stuff which is awesome that saved us a lot of hassle so and then since we're updating State we're going to emit an event let's call it collateral redeemed we'll say it's message. sender so from message sender the amount collateral uh the token collateral address like this so we're going to go to the top we're also going to refactor this event but you'll understand why later event collateral redeemed address indexed user address indexed token U 256 indexed Mount like this okay control minus go right back down to where we were okay amount collateral oh what's wrong with this oh these are backwards okay cool now all we have to do is return the money well how do we do this so we want to follow CI right checks effects interactions checks effects interactions but we also want to make sure the health factor is good after collateral collateral is pulled and this is where sometimes you'll see CI be violated when I need to check something after a token transfers happen sometimes you'll see this CI be violated a little bit and what you could do is you could do like calculate health Factor after and then like simulate it but a lot of people choose to not do this because this is really gas inefficient so what a lot of people do is they just go ahead with the doing the token transfer first and then checking this and reverting if this happens and that's usually fine though because we're going to revert the transaction if it's bad right so what we'll do is we'll do this token transfer and then we'll make sure the health factor is okay so you know how to move tokens around so we'll say bull success equals ier 20 token collateral all address dot we can just do transfer instead of transfer from since transfer is when you transfer from yourself transfer from is when you transfer from somebody else so transfer and we're going to be sending it to message. sender and we're going to send amount collateral and then if not success if if not success we're just going to go ahead and revert DSC engine we'll just do transfer failed like this and then we want to make sure that the health Factor isn't broken and we have WR a function that does that already called revert if Health factor is broken so we can just grab this go back up to our redeem and just do revert of Health factors broken for the message. sender okay cool like I said we're going to refactor this very soon okay but it looks like this is actually pretty good for redeeming collateral now this revertive health factor is broken is a little bit Troublesome with just this raw redeemed collateral let's say I put $100 in and then I mint say $20 worth of DSC put $100 worth of Ethan and I mint $20 worth of DSC let's say I'm done like I want to burn all my DSC and I want to withdraw all of my eth well if I try to redeem all my eth it'll break right it'll break my health Factor so what I need to do first is I need to First burn back my DSC and then I need to redeem eth so it's a kind of this two transaction process here this kind of stinks so let's turn it into a one transaction process so we're going to combine redeeming your collateral with also burning your DSC which means we're going to need to create a burn DSC function and we're also going to refactor this in a little bit but I'm just going to write it as if this is the only burn DSC function for now so let's have people burn their DSC right this is when they they say hey I'm done with these tokens and this will reduce that if we scroll up to the top we have this mapping here SDC minted it'll reduce this sdsc minted so essentially it'll reduce their debt in the system so burn DSC we're going to add some modifiers here there should be more than zero amount so we want to do a un 256 amount so they can burn as much as they want and then what we're going to want to do is we're going to say sore DSC minted of the message. sender it's going to minus equal amount so we're going to remove that debt remove that DSC minted then we're going to do a little bu success equals iore DSC transfer from DS message. sender to address this Mount and we could also send this to the Zer address but we're going to just send it to our addes for now because the decentralized stable coin erc20 burnable has its own burn function and we're just going to call the burn function directly on the token itself but first we're going to take it from them bring it into our contract and then we're going to burn it so if not success then we'll revert dsce transfer failed this and this conditional is kind of hypothetically unreachable because if the transfer fails up here we're going to throw the transfer from fail error but let's say this DSC token is implemented wrong great we kind of have this backup but so they're going to send their DSC token here then we're going to call IOD dc. burn amount now since we're burning DSC question is do we need to check if this breaks Health Factor well probably not right because we're burning DSC we're burning debt it's high highly unlikely that burning your debt removing your debt is going to break the health Factor right we probably don't ever need this but I'm just going to add this in here for now just as a backup in a gas audit we can figure out if we actually need it I don't think this would ever hit and this is where when I do go to an audit when I do go to security professional I can make sure to point this line out say hey I don't think line will ever hit and I'm thinking of pulling it out what do you think right it's good to call these out in your comments that when you do go to professional who knows they can help you out figure this out so for now we're going to put it in here although it's highly likely we don't even need this and we're going to refactor this function pretty soon anyways so we have this burn DSC function we're going to make it public because we're going to be burning DSC and redeeming collateral at the same time so now we have redeemed collateral we have burn DSC now we can write this redeem collateral for DSC where we send DSC and redeem collateral at the same time and so in here we're going to say address token coatal address U 256 amount collateral un 256 amount DSC to burn we'll have this be external so then we're going to call burn DSC with the amount of DSC to burn we're also going to call redeem collateral so we're going to burn the DSC first and then we're going to redeem their collateral with the token collateral address the amount collateral redeem collateral oh this is external let's make this public let's go back and then of course we should revert if Health factor is broken but if we look our redeemed collateral function currently does this already so we don't need to do that here so I'm just going to put this comment redeem collateral already checks Health Factor right here then we'll add a little bit of natspec here so at Pam boom that's not even the right Pam to CL Alis the collateral address to redeem Pam amount collateral the the amount collateral to redeem RAM amount DC to burn the amount of DSC to burn this function Burns DC and redeems underlying collateral in one transaction okay are we going to refactor these two functions soon yes absolutely but I want you to understand why we're going to reactor them so we're going to leave them in as they are for now Okay cool so this is looking pretty good so we have a lot of stuff in here uh we have deposit collateral and mint DSC so people can mint our stable coin by depositing collateral people can just straight up deposit collateral people can then redeem their collateral for the US for the DSC that they minted they can just straight up redeem collateral they can just straight up mint DSC so long as they didn't break the health Factor they can burn DSC to go help their health factor and I don't think this line will ever hit we've got to do a couple of more things here most importantly we got to do this liquidate function so this liquidate function is kind of the the key thing that holds this whole system together if we do start nearing under collateralization we need someone to start liquidating positions removing those positions we need somebody to basically call redeem and burn for you if your health Factor becomes too poor right because the worst thing that would happen is let's say there's $100 worth of eth backing $50 worth of DSC and then the price of eth Tanks to $20 right $20 of eth backing $50 of DC well now the dsse isn't worth $1 right the DSC then is going to be worth you know whatever 20 over 50 is so we can't let this happen right we need to make sure we liquidate people's positions we remove people's positions in the system if the price of the collateral tanks okay and this is where liquidation comes in so we say if some some one is almost under collateralized we will pay you to liquidate them we have kind of this gamified incentive system here where people can get basically free money for removing other people's positions in the protocol so in this situation up here as the price is going down let's say the price goes down to $75 backing $50 of dsse this is way lower than our 50% threshold so what we're going to do is we're going to let Liquidator Liquidator take this $75 backing takes the $75 backing and pays off the $50 DSC and Burns Burns off the 50 DSC so we're going to have somebody able to take their money in exchange for them making sure our protocol stays collateralized so that's what this liquid a function is going to do so first off they're going to be able to choose the collateral the user that they want to liquidate and the UN 256 debt to cover and they'll be able to track the users and their positions by listening to these events that we've been emitting which is exciting we're going to definitely want a lot of n spec for this at Pam collateral is going to be the collateral to liquidate or better yet the rc20 address colateral address liquidate from the user at Pam user the user who has broken the health Factor their health Factor should be below Min Health Factor at Pam debt to cover is going to be the amount of DSC you want to burn to proove the users Health Factor yeah we're going to add a lot of at notices here at notice you can partially or liquidate a user just so as so long as you improve their health Factor that's all we care about at notice you will get a liquidation bonus for taking the users funds right we want to incentivize them to to actually do this right if we say okay cool you'll get the $50 back for paying off the $50 debt it's going to be hard to incentivize people to do that but if we say you get all $75 and all you have to do is pay back 50 then that's going to be a bonus that they should be able to take to incentivize them to do this at notice this function working assumes the protocol prot call will be roughly 200% over collateral ized in order for this to work why well because in this scenario if this drops down to $20 backing $50 of DSC and if I pay back the 50 DSC and I get $20 well then I I'm not going to do that I'm not going to pay $50 to get back 20 so this whole system only works if the system is always over collateralized the only way we can give liquidation bonuses is if we're over collateralized so the only way we can incentivize people to liquidate poor users is if we are over collateralized so we could say at notice a known bug would be if the protocol were 100% or less collateralized then we wouldn't be able to incentivize the Liquidators and then we would just say like for example if the price of the co Al plummeted before anyone could be liquidated so hopefully this makes a lot of sense if this doesn't make sense you know what to do ask chat chbt ask in the discussions Forum Google it use the resources that you have to your advantage yes yes okay good so debt to cover we probably want to do more than zero very lame if they did just zero so we're going to do more than Z zero here we're going to be moving tokens around so we're going to do non reent as well maybe we'll do some more modifiers but that looks pretty good to me right now so now what do we need to do well we need to do a bunch of stuff here well we first need to check Health factor of the user right is this user even liquidable right remember we want to do follows CEI checks effects interactions right we always want to follow CI so we should do some more checks here because we should only liquidate people who are liquidable so first thing we should do U into 256 starting user Health Factor equals underscore Health factor of the user right because we have this health Factor function which gets that Health factor and what we can say and let's put this above now we'll say if the starting user Health factor is is greater than or equal to the Min Health factor which what's our Min Health Factor again one actually it should be 1 E18 and we're definitely going to write some tests to make sure this is correct so 1 E18 because we're using our Precision here what else are we doing Health Factor why didn't we write test elsewhere revert if Health factor is broken oh I guess we haven't tested this yet well I guess we're going to be testing it very soon make sure that that Health Factor bid is right so the starting us a health factor is is greater than or equal to the health Factor then we revert right revert DSC engine underscore uncore Health Factor okay right Health factor is fine got a new error let's go to the top scroll down error Health Factor o back back cool back down here remember I'm doing control minus to go back might be something else depending on your setup so let's do some thinking so now we have their starting Health Factor what do we want to do we want to burn their DSC debt right we want to reduce the amount of DSC they have and take their collateral we want to remove them from the system basically right so how do we do that let's say they have 140 $140 of eth deposited and $100 of DSC with a setup like this their health Factor should be below what it currently is what we could do is we can say okay we're going to cover so this is what bad user this dis B user has that means we could cover we could say okay we're going to cover debt to cover is going to equal that $100 and we need to pay back $100 so we're going to have to get a u into 256 collateral or token amount from debt covered covered cover covered so we need to figure out okay if we're covering $100 $1 of debt $100 of DSC equals how much eth so we're going to pay back $100 of debt and how much eth is that okay how much eth is that so we're going to get the token amount of death color the eth basically equals and we're going to have to do some pricing stuff we're going have to say equals get token amount from USD so we're going to add the collateral and the debt to cover so we're going to figure out okay how much of this token are we going to get right we're going to cover $100 worth of debt how much in eth or whatever collateral token is $100 worth of debt so we're going to create a new function get token amount from USD this is going to be a public view function so we're going to scroll all the way down here public and external view functions function get token amount from USD and we're going to pass an address token or collateral unit 256 USD amount in way this will be a public view returns 256 and we're going to have to do some price feed stuff so we're going to need what are we going to need to do we're going to need to get the price of eth or the token then we're going to have to say Okay so if the pricing is dollar per eth and we have eth how do we get the dollar well if we do some math here let's say it's $22,000 of eth and we we have $11,000 right how much eth is that we're going to do the 1,000 / 2,000 which is going to equal 0.5 eth right so we're going to do this number divided by this number the amount the USD amount in way divided by the price and that's how we're going to get this token or collateral amount from the USD amount so we'll say agregator V3 interface price feed equals aggregator V3 interface of S price feed of token oh wow it even build in a lot of this for me that's great yes this looks right so we're going to get the price feed of the token and get called the latest round data on it to get the price here and then we're just going to do this right here so we're going to say the amount USD in way divided by the price or un 256 price is this the full story no absolutely not because we should always multiply first so we're going to do this times our Precision then we can divide by the price but is that the whole story no because the price has eight decimal places and we need it to have 18 so we're going to do additional feed Precision like this does that look right so if we have let's say we have 10 E8 for amount in way we're timesing that by 1 E18 like this we're saying divide that by the price let's say the price is $2,000 $2,000 E8 times the 1 E10 the additional piece here this looks pretty correct do we need anything else let's see just pull out the calculator right so 10 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 10 times 1 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 nine 10 divided by 2 1 2 3 2000 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 equals this number which is probably a half right 1 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 that right 1 2 3 4 5 6 7 89 1 2 3 4 5 6 7 8 n 8 n 0 point is that right oh because it's $10 thoughh yes this is right I was like I thought we did a thousand dollar but this is $10 yes okay cool that looks good to me great and then obviously we're going to test this soon to make sure that it is right so we have this function where we get the token amount from the USD so we're saying hey we're going to cover $100 of your debt or something like that how much eth is $100 worth of your debt maybe it's if the price is $22,000 we obviously we would do 100 divided by 2,000 0.05 right there right this is going to be something like 0.05 eth or whatever it is right cool so we have how much eth we need to take away from their collateral as a reward for paying back this DSC but additionally we also want to and give them a 10% bonus right because we want to incentivize them if they're just if it's just a one for one they're not going to want to do this so let's say we're going to give them a 10% bonus so we are giving the liquid dator $110 of weth for 100 dsse whatever $110 of we is going to be we should Implement a feature to liquid date in the event the protocol protocol is insolvent we're not going to add that in yet though but we should probably add something like that and then and sweep extra amounts into a treasury but we're not going to add either one of those so don't worry if that's confusing don't worry about that we're not even going to implement that anyways so we'll say un 256 bonus collateral equals this token amount debt covered times some liquidation bonus that we haven't defined yet although we're going to do 10% divided by 100 but I hate these floating numbers so we're going to do something better than 100 we're going to do Liquidator Precision which is 100 and we'll do unit to 256 private constant liquid dator bonus equals Shan bonus it's going to be 10 be like this means a 10% bonus and since it's going to be 10 ided 100 that's going to be 10% let's go back down liquidation bonus divided by liquidation Precision so the bonus collateral is going to be 10% so let's say it was 0.5 0.05 eth we're going to multiply that by .1 right because we're going to multiply first and then divide to get 0.5 e so as a total or that's not quite right it's going to be 0.005 0.05 * 0.1 equals yes so that means they're going to get 0.055 is that right I think that's right why why am I being bad at math I'm one yes okay cool great so that's what they're going to get this bonus collateral we got to add the bonus collateral to the actual collateral we're going to say like U into 256 total collateral collateral to redeem equals token amount from covered plus bonus collateral like that and so and now we need to redeem this amount of collateral for whoever's calling the liquidate function right we need to redeem that collateral and then we also need to burn the DSC from this user as well so we need to give them the collateral and burn the DSC that they're covering with their debt to cover now though if we look at our redeemed collateral redem collateral function which is public right now we can see as inputs it takes to collateral address and amount collateral right and it is hardcoded to message. Sender our third party user isn't the one with the bad debt right we need to redeem a random person's collateral so what we can do is we can refactor this code so that there's an internal redeem collateral function that can redeem collateral from anybody right and only very permissioned functions can call redeem collateral so what we're going to do is actually we're going to take all of this code and we're going to change change it and we're going to delete it and we're going to put it into a different function all the way down the in private and internal functions here we're going to make a function underscore redeem collateral and this is going to be an internal function where we can actually redeem collateral from anybody and as input this is going to take address token collateral address same as the regular redeem collateral also the unit 256 amount collateral but we're going to add address from and an address two so this way and this is going to be private so this way somebody can liquidate and address from and then get the rewards too and this is where I'm going to paste all that code we got from above and I think this looks good yeah we're just going to paste that code exactly like this instead of doing message. sender this is just going to be from and emit collateral redeemed we're going to update our collateral redeemed to redeemed from we'll do address redeemed from address redeemed two we'll do the token and then we'll have amount not be indexed so from to token and amount so now we got to refactor some of these collaterals so from when we do just the regular redeem collateral we'll update this in a minute actually yeah we'll update that in a minute so in this internal function it's going to be from from to address collateral and then we're going to transfer we're going to transfer the tokens two whoever the two is so this is going to be like the Liquidator Mount collateral and do that and now we're going to use this internal function up in our regular redeem collateral function that we just created right uh up here oh no up this one up here we're going to dump all this and just use this underscore redeem collateral and for here we're we're just going to say message. sender so from message. sender to message. Sender token collateral address amount collateral and now that we have this internal function we can use this redeem collateral bit down in our liquid date which is down here we can now just say redeem collateral from the user that's being liquidated so from user to whoever's calling liquidate here so it's going to be message. sender the collateral token that we're liquidating and then finally the total collateral to redeem so this is why I said we were going to do a little bit of refractor soon right we generally only want to redeem collateral from into the same person however when we're doing a liquidate we're going to redeem to whoever's calling the liquidate so they're going to get that reward the total collateral to redeem is that total amount debt to cover plus some bonus here and now we actually need to yeah we need to burn the DSC now so right now if we look at burn burn DSC we have this public function which just does the same thing it just does it just burns from message. sender we're going to have to do the same here we're going to want to make an internal burn DSC function that allows us to burn from anybody right so if we scroll down to where we're doing those private functions or scroll up so we have this internal redeem collateral we also are going to need an internal burn DSC function burn DSC unit 256 amount DSC to burn address on be half of like whose DSC are we burning for whose debt are we paying down and then address DSC from where are we getting the DSC from be a private and we can go back to the burn DSC let's burn DSC function right and same thing we can just copy all of this go back to our internal burn C function paste this in here we're going to want to update this right instead of message. sender this is going to be on B half of we're going to B we're going to take away their debt we're still going to do this but instead of message. sender it's going to be DC from and it's going to be amount DC to burn this is still fine this just needs to be a mount DC to burn and we don't need to check Health Factor yet because this is going to be our internal function so we might even say like in the comments here low level internal function or at Dev low level internal function do not call unless the function calling it is checking for health factors being broken so now we have this burn DSC we can go back up to our burn DSC function we can just swap delete all of this call burn DSC and this going to be message. sender message. sender amount right if somebody calls burn DC thems great we'll just have them call this burn DC amount to burn on behalf of themselves from themselves oh looks like I got this backwards amount should be the first one okay and now we have this burn DSC function we can go down to liquidate and we can call burn DSC what are the uh amount on behalf of from so the amount is going to be this debt to cover amount on behalf of is going to be the user and the one who's going to be paying this is going to be message. sender right because it's the whoever's the Liquidator whoever's calling liquidate is going to be the one who's paying down the debt to cover right paying back that minted DSC and now since we're doing these internal calls that don't have checks we absolutely need to make sure we're checking this health factor is okay right so we're going to do un 256 ending user Health Factor equals underscore Health factor of the user and if the ending Health factor is less than or equal to the starting Health Factor right if we didn't improve the health Factor we should revert DSC engine underscore Health Factor not improved copy this go to the top we'll do error DSC engine Health Factor not improved go back down so if we don't improve the health Factor Factor we should 100% revert and then also if calling this liquidate function if paying down some debt and doing all this stuff actually hurts the liquidator's health Factor we should also revert right so we should also call revert if Health factor is broken for the message. sender right if this process ruined their health Factor we shouldn't let them do this okay so we're following checks effects interactions here for the most part these two functions are making external calls to external contracts right and then we're doing kind of like a check afterwards again this is bit of a trade-off we could calculate before and then run this but that's kind of gas inefficient we're just going to check after we do all this hey just make sure that the health factor is okay make sure that we didn't break anyone's Health Factor so now we have this liquidation function which is incredibly powerful and kind of what ties this whole thing together right there's an incentive here for people to call liquidate so that our protocol is never insolvent right and I know I've been kind of throwing around a lot of these financial terms but our protocol always has more collateral than it has minted dsse the value of the collateral should always be more than the minted DSC always incredibly powerful function we're obviously going to be testing the living hell out of this right because we're want to make sure it actually works okay what do we need now oh looks like we broke some Stu stuff oh this needs a semicolon what else do we break there's a little red thing down here let's go fix it amount this should be amount DC to burn got a couple more red things redeem collateral user message sender redeem collateral uh oops we did these backwards I'm going to copy these put these at the front okay oh looks like that fixed pretty much most of this I don't see any more red stuff on the side here so we're going to go ahead and run Forge build make sure everything's at least compiling awesome maybe we'll even run Forge test I don't think this would have broken any tests looks like those are working fine but all right we're doing some fantastic work and like I said at this point I probably would be running tests with this but we're almost done with all of our code here so we're just going to keep going right and this code is starting to look pretty darn good right we've got these amazing natspec comments in here we've got comments all over the place maybe these probably should be cleaned up a little bit but that's fine we've got a little this little Dev thing a shout out saying hey don't let anybody call burn DSC without checking the health Factor right this is really good to tell Auditors and Security Professionals about this right it's really good to call this out we've now have this internal redeem collateral function so it can be used for the liquidate or the redeem collateral Health Factor looks like pretty much all the functions that we originally wrote are working in here right and the the reason again that this all works is because when we mint DSC we can only mint as much as we have collateral in the system we're setting this exchange rate essentially for our protocol hey cool you have a$1 you have $150 worth of eth deposited great you can mint $100 worth of DSC so it's this exchange rate that we're setting which is maintaining the price let's just double check that we have kind of most of the functions that we want here and let's also check that they're in the right place so we go to the top here got a whole bunch of Errors that's great got a whole bunch of constants because we hate magic numbers we have a mapping of price feeds mapping of collateral deposited from user to token to the amount they have deposited we have their debt or their DSC minted collateral Tokens The idsc Token we've got some events in here couple modifiers some functions we've got a way to deposit collateral and mint deal see in one transaction we've got a way to calculate health Factor I'm going to tell you right now there's actually a bug in here not going to tell you what that bug is yet though maybe you can figure it out we've got some view functions down below we're probably going to add more as we write tests but this is looking pretty darn good now like I said there's at least one big bug and there might even be and there's likely more but there's at least one big bug in here so now would be a good time to take a break because after this we're going to go deep into writing tests for this protocol we're going to write some new tests and we're going to show you some really Advanced testing methodologies so take that break go for a walk and I'll see you in a few all right so let's pull up our terminal here Forge coverage oh we got some work to do all right well no time like the present let's get into it so we have some price feed tests over here we probably also want to set up some Constructor test right we want to make sure that stuff is being initialized correctly so let's copy that we'll do con structor structor test like that we'll fix this so our ADHD doesn't go crazy and we'll do function test something what are we testing uh let's go down to the instructor here and what should we be testing okay well we're doing this revert here so we should make sure we actually are reverting correctly when the lengths aren't the same so function test reverts if token length doesn't match price feeds feeds public zoom in zoom in we're going to be in here a while so function this and we're going to do we're going to create some address arrays address array public token addresses address array public price price feed addresses we're going to say token addresses. push we're going to push we into here feed addresses add push FUSD price feed and we're going to push two in here oh cool BTC do we have I guess we should pull BTC USD price feed get this too so FUSD BTC USD price feed okay oops price feed addresses price feed addresses so we'll push the two of those in there now we'll do vm. expect revert DSC engine dot what's the name of the error copy this boom do select door selector like that doing some toggle word wrap now expect revert now we call a new DSC Engine with the token addresses and the price feed addresses oh what else El goes in the DSC oh we also need the address DSC right address DSC so this should revert let's see for test DM nice okay that's passing all right cool price feed tests we're testing getting the USD value I think we had another one down here right we had some like get token amount from USD we sure did this is a public view so let's test this one as well do function test and I usually just like to paste the function names especially when they're like this public so we're going to do basically the opposite of this this got the USD value of some eth amount we're going to do U 256 USD amount right equals we's say 100 eth under ether and then you 256 expected West do a little bit of math here if we have if it's $2,000 per eth and we have $100 we're going to do 100 divided 2,000 so 100 divid 2,000 0.05 so we can say expect a we is 0.05 ether now we'll do U into 256 actual we equals dsce do this function with the lowercase pass in we and then the USD amount assert equal expected X expected weth and the actual weth the two of them should be the same Let's test it out Forge test- M nice that passed all right let's keep going posit collateral tests test revert if collateral is zero that's good what else let's go to this deposit collateral deposit collateral fun okay we should also revert here we're basically just going to go through this whole function and kind of test each line we just test this one let's tested this one so this will be something like function test reverts with unapproved collateral public we'll make an erc20 mock some Rand token right we'll just make some silly token new ERC 20 mock ran will be the the name ran will be the token do we have a user in here I think we do have a user right okay yeah we do have a user let's give this money to a user and then we'll give him some starting amount I think we have starting erc20 balance or amount collateral yeah we'll do amount collateral give them the amount collateral we'll do vm. start prank this user who has this token and they're going to try to deposit this collateral and we're going to expect it to revert so vm. expect revert and this error here is allowed token right now doesn't take any parameters so that's easy enough for us let's just copy this we'll do DSC engine. this. selector and then we'll do we'll call the deposit collateral so DS C.D deposit collateral address of that Rand token right Rand token or random token we'll do amount collateral as well so it'll just be that whole amount and then we can do vm. stop prank and that should work Forge test DM see if that's correct yep looking good all right let's keep going what else what's next deposit collateral not that one okay did this did this non reentry we could be go ahead and test re-entrant I'm going to skip doing that for now but we probably do want to do some re-entrance tests at some point but yeah I'm going to skip them for now and all right cool so then we can start testing some of this so if they deposit collateral we should see that they actually do this we should see that they emit an event let's go ahead and do that so let's do function test can posit collateral colateral and get account info because once they deposit we have this get account info oh it's private right now so let's actually go to the bottom let's create a public version of that so we'll do function get account information this will be uh external external view returns return this account address user returns these two I'm going to copy this go back down uh external view returns these two things and we're going to say total D ISC minted comma V value in USC equals this internal function and that should be good right oh we're going to do instead of message. sender we'll do address user this paste the user in here so now we get the total DS minted and their collateral value in USD from an external view function we should be able to get that information so let's have them actually deposit collateral in here and since we're going to be doing a lot of deposited collaterals we know we can actually make a modifier deposited collateral this bm. start prank user herec 20 mock we in in order to deposit weth we need to approve address esce comma amount collateral we're going to do dsce deposit collateral we amount collateral bm. stop prank bm. stop prank underscore like this modifier right and we'll have this can deposit collateral and get account info we'll have them deposit collateral and we'll now get that account information so we'll say U 256 total DSC minted U 256 lateral value in USD equals dsce do get account information the user oh from the user and now what we're going to say we're going to make sure these two numbers are correct the total DSC minted and the collateral value in USD they should have minted no DSC so you 256 expected expected total DSC minted yep equals zero un 256 expected colateral value in USD equals this is going to be that dsce doget token amount from USD we collateral value in USD so expected collateral value should should just be this function then we can say assert equal total DSC minted should be this expected total D minted and then we can do assert equal collateral value in USD it's going to be this expected collateral value in USD all right clear Forge test DM all right we have a fail you know what to do we're going to run it again Dash vvvv see what we mess up here says the assertion failed left is this number and right is a much smaller number this is why it's not cool to do two types of asserts but I know it's the second one so we're saying the collateral value in USD is this but the right side is expected collateral value is going to be this so let's see what's wrong here 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 so it's saying collateral value in USD is 20 grand does that make sense well it's 10 ether times $2,000 equals 20 grand right so that is so the collateral value in USD is right it looks like my right is wrong collateral expected collateral value in USD dc. from token amount we oh what the heck why am I doing that 1 2 3 4 5 5 6 7 8 9 10 1 2 3 4 5 6 7 8 so it's saying that $20,000 is equal to 10 e so I don't know why I'm calling this oh this is actually expected expected deposit amount and we shouldn't be comparing these two this should be compared to the amount collateral right so 10 is how much collateral we're putting in here and then collateral value in USD yeah that's correct so we're getting we're using this collateral value in USD to get the expected deposit amount that looks more correct okay cool Forge test- M and this is one of the kind of weird Parts about writing test right okay cool we fixed it sometimes your test is wrong like what we just showed here I wrote my test wrong but sometimes your code is wrong and that's what these tests really should be testing hey when is the code actually wrong making some progress for coverage not a whole lot of great coverage here let's keep going so instead of me just kind of walking you through the rest of these tests you know how to write these tests in this file I'm not really going to show you any more unique tests right but like I said there is at least one glaring issue in our DSC engine. Soul there's a big issue in here here right we definitely need some more getter functions as well so write getter functions as you test but there's at least one giant issue so what I'm going to do now is instead of me literally walking you through the rest of these tests I mean it's you can see all the tests in here is I'm going to challenge you to write these tests yourself to get this Forge coverage up remember you can do Forge coverage to obviously see what's going on we're focusing on this one right now you can also do Forge coverage D- report to see oh D- report debug to actually see the exact lines that are missing right and all these things are just kind of line items line items whatever IC doesn't matter scroll scroll scroll scroll scroll okay these are the ones that are actually issues right what which one's this oh that's that is the decentralized stable coin we want to write test for that as well but let's just focus on this massive list up here DSC engine Focus on this list and write some tests for this because yeah the rest of these unit tests or staging tests we're not going to learn anything new this is just one of these things that you got to do that you got to get good at that you got to write now you don't have to get it to 100% if you get it to like 8590 that's pretty good some of these tests are actually very difficult to write but you should writing these test should find a glaring bug in at least one of these functions and maybe if you find more than one glaring bug that's great make a PR make an issue to the repo but I want you to pause the video and take some time right it might be an hour it might be two hours it might be 30 minutes right depends on how quick your AI buddy is how quick you are and write some more tests and sometimes actually you can even come to your contracts and you could do something like grab this go over to your chat GPT say hey this is one of my solidity functions can you write some tests for it for it in Foundry and because it doesn't know what Foundry is it's going to totally bunk it up but you could use chat PT to help you write some tests as well help you get your coverage up but there's definitely one major issue in here you might even need to go back and refactor some code right I'm going to say keep that to a minimum though but there are some spots where maybe you need to refactor your code to make writing tests easier maybe you need to write some more helper functions right take this time to experiment and tinker and think what should I do how can I make sure my code is safe and importantly how can I write enough tests to find this bug that Patrick is talking about right maybe you do some refactoring now don't write any fuzz tests yet we are going to go over fuzz tests in a little bit but yeah just try to write the rest of these unit tests rest of these pseudo integration tests and I'll see when you come out the other side but when you finish writing the tests take a break take a minute I I want this to sink in this is one this is the most advanced lesson that you're going to take in this course and to be honest probably it's going to be one of the most advanced courses you'll ever take in solidity okay so I want you to take your time with this I want you to understand what's going on sometimes it might even make sense for you to go oh well what does maker Dow do how can I learn more about stable coins where else can I go maybe I can ask chat gbt for questions right those of you who are going ah I really don't want to that you can 100% just copy paste mine but I recommend you go through this exercise okay lock off some time and I'll see you soon all right so let's pull up our terminal here Forge coverage oh we got some work to do all right well no time like the present let's get into it so we have some price feed tests over here we probably also want to set up some Constructor tests right we want to make sure that stuff is being initialized correctly so let's copy that we'll do constuctor structor test like that we'll fix this so our ADHD doesn't go crazy and we'll do function test something what are we testing uh let's go down to the instructor here and what should we be testing okay well we're doing this revert here so we should make sure we actually are reverting correctly when the lengths aren't the same so function test reverts if token length doesn't match price feeds feeds public zoom in zoom in we're going to be in here a while so function this now we're going to do we're going to create some address arrays address array public token addresses address array public price price feed addresses we're going to say token addresses. push we're going to push we into here feed addresses add. push FUSD price feed and we're going to push two in here oh cool BTC do we have I guess we should pull BTC USD price feed get this too so FUSD BTC USD price feed okay oops price feed addresses price feed addresses so we'll push the two of those in there now we'll do vm. expect expect revert DSC engine dot what's the name of the error copy this boom do selector selector like that doing some toggle word wrap now xect revert now we call a new DSC Engine with the token addresses and the price feed addresses oh what else goes in the DSC oh we also need the address DSC right address DSC so this should revert let's see Forge testm nice okay that's passing all right cool price feed tests we're testing getting the USD value I think we had another one down here right we had some like get token amount from USD we sure did this is a public view so let's test this one as well do function test and I usually just like to paste the function names especially when they're like this public so we're going to do basically the opposite of this this got the USD value of some eth amount we're going to do U 256 USD amount right equals we's say 100 eth 100 ether and then 256 expected we do a little bit of math here if we have if it's $2,000 per eth and we have $100 we're going to do 100 divid 2,000 so$ 100 divid 2000 0.05 so we can say expect a we is 0.05 ether now we'll do U into 256 actual we equals dsce do this function with the lowercase pass in we and then the USD amount assert equal expected X expected we and the actual we the two of them should be the same Let's test it out Forge test DM nice that passed all right let's keep going POS a collateral test test revertive collateral zero that's good what else let's go to this deposit collateral deposit collateral function okay we should also revert here we're basically just go through this whole function and kind of test each line we just tested this one let's tested this one so this will be something like function test reverts with unapproved collateral Cal public we'll make an erc20 mock some Rand token right we'll just make some silly token new erc20 mock ran will be the name ran will be the token do we have a user in here I think we do have a user right okay yeah we do have a user let's give this money to a user and then we'll give them some starting amount I think we have starting erc20 balance or amount collateral yeah we'll do amount collateral give them the amount collateral we'll do vm. start prank this user who has this token and they're going to try to deposit this collateral and we're going to expect it to revert so VM expect revert and this error here is allowed token right now doesn't take any parameters so that's easy enough for us let's just copy this we'll do DSC engine. this. selector and then we'll do we'll call the deposit collateral so DS c. deposit collateral address of that Rand token right Rand token or random token we'll do amount collateral as well so it'll just be that whole amount and then we can do vm. stop prank and that should work Forge test DM see if that's correct yep looking good all right let's keep going what else what's next deposit collateral not that one okay did this did this non- reentrant we could be go ahead and test re-entrant I'm going to skip doing that for now but we probably do want to do some re-entrance tests at some point but yeah I'm going to skip them for now and all right cool so then we can start testing some of this so if they deposit collateral we should see that they actually do this we should see that they emit an event let's go ahead and do that so let's do function test can posit collateral L leral and get account info because once they deposit we have this get account info oh it's private right now so let's actually go to the bottom let's create a public version of that so we'll do function get account in foration this will be uh external external view returns return this account address user returns these two I'm going to copy this go back down down uh external view returns these two things and we're going to say total D ISC minted comma F value in usdc equals this internal function and that should be good right oh we're going to do instead of message. sender we'll do address user this paste the user in here so now we can get the total DS minted and their collateral value in USD from an external view function we should be able to get that information so let's have them actually deposit collateral in here and since we're going to be doing a lot of deposited collaterals we know we can actually make a modifier deposited collateral this bm. start prank user here see 20 mock weth in order to deposit weth we need to approve address dce Comm amount collateral we're going to do dsce deposit collateral with amount collateral bm. stop prank bm. stop prank underscore like this modifier right and we'll have this can deposit collateral and get account info we'll have them deposit collateral and we'll now get that account information so we'll say U into 256 total DSC minted un 256 L lateral value in USD equals dsce do get account information the user oh from the user and now what we're going to say we're going to make sure these two numbers are correct the total DSC minted and the collateral value in USD they should have minted no DSC so un 256 expected expected total DC minted yep equals zero 256 expected colateral value in USD equals this is going to be that dsce do getet token amount from USD with collateral value in USD so expected collateral value should just be this function then we can say assert equal total demented should be this expected total demented and then we can do aert equal plal value in USD it's going to be this expected collateral value in USD all right clear Forge test DM all right we have a fail you know what to do we're going to run it again Dash VV VV see what we messed up here says the assertion failed left is this number and right is a much smaller number this is why it's not cool to do two types of asserts but I know it's the second one so we're saying the collateral value in USD is this but the right side is expected collateral value is going to be this so let's see what's wrong here 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 so it's saying collateral value in USD is 20 Grand does that make sense well it's 10 ether time $2,000 equals 20 grand right so that is so the collateral value in USD is right it looks like my right is wrong collateral expected collateral value in US D dc. from token amount we oh what the heck why am I doing that 1 2 3 4 5 6 7 8 9ine 10 1 2 3 4 5 6 7 8 so it's saying that $20,000 is equal to 10 e so I don't know why I'm calling this oh this is actually expected expected deposit amount and we shouldn't be comparing these two this should be compared to the amount collateral right so 10 is how much collateral we're putting in here and then collateral value in USD yeah that's correct so we're getting we're using this collateral value in USD to get the expected deposit amount that looks more correct okay cool Forge test- M and this is one of the kind of weird Parts about writing test right okay cool we fixed it sometimes your test is wrong like what we just showed here I wrote my test wrong but sometimes your code is wrong and that's what these tests really should be testing hey when is the code actually wrong making some progress Forge coverage not a whole lot of great coverage here let's keep going so instead of me just kind of walking you through the rest of these tests you know how to write these tests in this file I'm not really going to show you any more unique tests right but like I said there is at least one glaring issue in our DSC engine. Soul there's a big issue in here right we definitely need some more getter functions as well so write getter function as you test but there's at least one giant issue so what I'm going to do now is instead of me literally walking you through the rest of these tests I mean it's you can see all the tests in here is I'm going to challenge you to write these tests yourself to get this Forge coverage up remember you can do Forge coverage to obviously see what's going on we're focusing on this one right now you can also do Forge coverage D- report to see oh D- report debug to actually see the exact lines that are missing right and all these things are just kind of line items line items whatever IC doesn't matter scroll scroll scroll scroll scroll okay these are the ones that are actually issues right what which one's this oh that's the that is the decentralized stable coin we want to write test for that as well but let's just focus on this massive list up here DSC engine focus on this list and write some tests for this because yeah the rest of these unit tests or staging tests we're not going to learn anything new this is just one of these things that you got to do that you got to get good at you got it right now you don't have to get it to 100% if you get it to like 85 90 that's pretty good some of these tests are actually very difficult to write but you should writing these tests should find a glaring bug in at least one of these functions and maybe if you find more than one glaring bug that's great make a PR an issue to the repo but I want you to pause the video and take some time right it might be an hour it might be 2 hours it might be 30 minutes right depends on how quick your AI buddy is how quick you are and write some more tests and sometimes actually you can even come to your contracts and you could do something like grab this go over to your chat GTP and say hey this is one of my solidity functions can you write some tests for it for it in Foundry and because it doesn't know what Foundry is it's going to totally bunk it up but you could use chat PT to help you write some tests as well help you get your coverage up but there's definitely one major issue in here you might even need to go back and refactor some code right I'm going to say keep that to a minimum though but there are some spots where maybe you need to refactor your code to make writing tests easier maybe you need to write some more helper functions right take this time to experiment and tinker and think what should I I do how can I make sure my code is safe and importantly how can I write enough tests to find this bug that Patrick is talking about right maybe you do some refactoring now don't write any fuzz tests yet we are going to go over fuzz tests in a little bit but yeah just try to write the rest of these unit tests rest of these pseudo integration tests and I'll see you when you come out the other side but when you finish writing the tests take a break take a minute I want this to sink in this is one this is the most Advanced lesson that you're going to take in this course and to be honest probably it's going to be one of the most advanced courses you'll ever take in solidity okay so I want you to take your time with this I want you to understand what's going on sometimes it might even make sense for you to go oh well what ises maker Dow do how can I learn more about stable coins where else can I go maybe I can ask chat gbt for questions right those of you who are going ah I really don't want to do that you can 100% just copy paste mine but recommend you go through this exercise okay lock off some time and I'll see you soon all right welcome back did you find the bug how are your tests looking if you run Forge coverage do they look something at least like this do they look better do they look worse so I copy pasted a whole bunch of my tests and we're looking pretty good here we definitely should be increasing the test coverage of our branches and we can definitely get these a little bit higher but for at least the DSC engine we have a much better code coverage going on here and I hope your code coverage looks looks like this too now additionally I did a little bit of refactoring writing these codes one of the main things that I added was I added this C calculate health Factor function reason I added this calculate health Factor internal function was so that I could have this public calculate health Factor function and then in my test what I could do is have an expected Health factor and that way when a function breaks Health factor I can pass that into the expected Health Factor error revert here in one of my tests right when we're testing to expect an event I added this new function to do that and having a public function like calculate health Factor might make it easier for people to see what their health Factor might be if they make some change right so that was one of the big ones I made and the bug was in the health Factor as well or at least the bug that I planned to be in there so in my calculate health factor which instead of in our underscore Health Factor function I'm just calling this calculate health Factor function right I'm getting the account information and then just passing it to this calculate health Factor factor and in this we needed to add a checker for if the total D cemented was zero and if it's zero then we said okay cool your health factor is going to be the max U and 256 or something like that right and the reason that we need this is if someone deposits a ton of collateral but has no DS cemented well their health factor is going to divide by zero which we can't have so calculating someone's Health Factor after they deposit collateral would result in an issue we'd break stuff we don't want to break stuff and then the final piece that I did was I added a ton of external view functions just to make it easier to read and interact with this protocol so those are some of the refactors that I did and then obviously we added a ton of tests there's nothing really new in here it's just you got to write the test right everything in here you've learned you can do and if you wrote some tests and you got this to a high level of coverage around 90% you should be incredibly proud of yourself this is hard to write test for this is very difficult project so you should be incredibly proud of yourself for just getting this far but guess what we're not even done because we want to make this code so freaking amazing we need to think a little bit about security and we're not going to go too deep into security however we should ask ourselves some questions right when we're working with a code base we we want to say hm we should always always ask what are our invariants /properties what are the invariance SL properties of the system and that way we can write some stateful and stateless fuz tests now I know we briefly went over one form of fuzz testing but now we're going to go a little bit deeper and I made a video on stateless and stateful fuzz testing recently and we're going to go ahead and watch that so you can have a better understanding of what stateless and stateful fuzz testing is and why it's so important especially for a project like this that has potentially a lot of money moving around so let's understand what fuzz testing is let's watch this video all right contracts are written and tested can I ship my code no I can easily break this with a flash loan attack a crap I didn't think about that let me fix all right how about now if I make a flash on on a I can use that loan to lock up a cdb on Faker Dow and I can exploit the Oracle by re-entering your dinner reservation at Chili's causing a bridge malfunction on the flux capacitor bypassing the possibility media can exploit your contract I exploit your contract most of the time hacks will come from a scenario that you didn't think about or write a test for but what if I told you that you could write a test that cannot check for just one scenario but every scenario let's get froggy fuzz testing or fuzzing is when you supply random data to your system in an attempt to break it so if this balloon is our system/ code it's us doing random stuff in attempt to break it this is chain link now why would we want to do all that let's say we have this function called do stuff it takes an integer as an input parameter and we know that no matter what we give it as an input our variable should always be zero should always be zero the fact that this variable should always be zero is known as our invariant or our property of the system that should always hold in our balloon example if we Market our balloon Bon as indestructible or unbreakable or unpoppable the invariant that would hold would this balloon cannot be broken and unlike this balloon in real life we can write a test that will call the do stuff function many times with random data and check to see that our should always be zero variable is always zero now a normal unit test for our code might look like this we pass a single data point we call the function and then we do our assertion to make sure that should always be zero is in fact zero and with this we might think our code is covered but if we look back at our do stuff function a little bit closer we can clearly see that if our data input is two should always be zero we'll end up being one this would break our invariant should always be zero will not be zero now this may seem obvious for this function but sometimes you'll have a function that looks like [Music] this it would be insane to write a test case for every single possible integer or scenario so we need a programmatic way to find this scenario now in our code we also see a second exploit but we'll get to that in a minute now there are two popular methodologies to find these edge cases fuzz test/ invariant tests and symbolic execution SL formal verification we'll save the latter for another video if we were writing our code in Foundry this would be our unit test writing a fuzz test in Foundry where we do all this random inputting is going to be really similar instead of us manually selecting our data right in our test parameter We'll add our variable comment out this line and that's it now when we run a Foundry test here Foundry will automatically randomized data run through a code with a ton of different examples this is as if they run with dat equal 0 data equals 1 data equals this number that's a t but whatever you get the picture now if I run my unit test you'll see that the unit test actually passes however if we run this fuzz test you'll see it actually gives us an output where it says assertion violated counter example gives us the call data and the arguments it was able to find out by randomly throwing data at our function call that two breaks our invariant AKA it makes it such that should always be zero is not zero now it's really doing semi- random data instead of purely random data and the your fuzzer picks the random data matters it won't be able to go over every single possible un 256 so understanding how your fuzzers pick the random data is an advanced thing that you should learn later on at the moment I think the trailer bits a kidna SL optic integration is probably the best fuzzer out there and it easily has the best logo of all time but ripped Jesus is a solid second so now that we have our counter example here we can use this to go back into our contract find out ah okay so we are doing this wrong delete this line and then run our test again and see that it does indeed pass what's important is this number down here the number of runs so this did 256 different random inputs to make our test run in Foundry you can change the number of runs in your Foundry tommo file by just adding a section like this rerunning your tests and now you'll see it did a thousand different examples the number of runs is really important obviously because more runs is more random inputs more use cases more chance that you'll actually catch the issue and now congrats that's the basic of fuss testing let's just do a little recap here before going further the first thing you need to do is understand our invariance or property of the system that must always hold and our example should always be zero was our invariant understand your invariant and then write a test that would input random data to try to break that invariant now if we go back to our example contract though you'll see with our fuzz test we were able to find this first use case however it didn't find this second scenario where should always be zero was set to one if hidden value was seven in order for this to revert hidden value would need to be seven and the only way to set hidden value to seven would be to First Call do stuff with 7 which would set hidden value down here and then call do stuff again with anything our fuzz test as written would never be able to find this that's because this fuzz test is known as a stateless fuzz test which is where the state of the previous run is discarded for the next run if we go back to our balloon example stateless fuzzy would be doing something to the balloon for one fuzz run then discarding that balloon and blowing up a new balloon for each fuzz run however instead of doing State less fuzzing we could do state full fuzzing stateful fuzzing is where the ending state of our previous fuzz run is the start starting state of the next fuzz run for example instead of blowing up a new balloon for each one of these runs we just use the same balloon to do multiple random things to it combined is considered one fuzz run so a single fuzz run on a stateless fuzz run would be having data be7 calling do stuff just using the same contract that we just called do stuff on and then call another function on it if this was a unit test we had we would of course see this get violated but as you can see with sufficiently complicated code coming with these very specific scenarios are going to be missed to write a F fuzz test and Foundry you need to use the invariant keyword and it requires a little bit of setup and don't get too confused by the invariant keyword here yes it's being a little overloaded WR invariant test and Foundry we first need to import this STD invariant contract and inherit it in our test contract then we need to tell Foundry which contract to call random functions on since we only have one contract with one function we're going to tell Foundry that my contract should be called and it's allowed to call any of the functions in my contract so we'd say hey the Target contract for you is going to be the address of example contract Foundry is smart enough to know okay it's going to grab any and all of the functions from my contract and call them in random orders with random data so it's going to call do stuff with random data and then it's going to call do stuff with random data and then it's going to call do stuff with random data since do stuff is the only function now we can write our invariant by saying function invariant test always is zero public and we can just add our resert CT our example contract that should always be zero is zero so it'll run do stuff with some random data if it happens across cross 7 it'll set hidden value to seven and then it'll call do stuff again with hidden value starting at seven which will trigger this conditional so now if we run this test we can see it does indeed find a sequence where our invariant or our assertion or our property is broken we can see first on my contract it's going to call do stuff with an argument of seven and then it's going to call my contract with an argument of some random number because it doesn't matter what the input is after it sets it to seven so now now that we have that we can go back to our code remove this come back to our test rerun our test and we'll find that our code is now safe and sound because our invariants hold up now an important aside on the term invariant founder uses the term invariant to describe this stateful fuzzing state less fuzzing is when you give random data to an input to a function to see if it breaks some invariant State full fuzzing is when you give random data and random function calls to a system to see if it breaks some invariance in Foundry fuzzing is stateless fuzzing and invariant are stateful fuzzing so when people are talking about invariance and Foundry they're usually talking about stateful fuzzing if they talk about fuzzing and Foundry they're talking about State less fuzzing even though they're both technically fuzzing there's an issue on the repo to potentially change the name but I digress so in a real smart contract your invariant won't be that a balloon shouldn't pop or some function should always be zero it might be something like new tokens minted is less than the inflation rate there should only be one winner in a random Lottery someone shouldn't be able to take more money out of the protocol than they put in and let me tell you what at this point congratulations you've learned the basics of fuzzing this is something that even some of the top protocols in this space don't use and this is something that we in cphon use to find High severity vulnerabilities in smart contracts hey I'm Alex ran co-founder at cyphon we use invariant tests during our audits to identify vulnerabilities that are often difficult to catch purely with manual reviews that's not to say they're a silver bullet they are in no way a replacement for experts manual review but they ser can Aid in the audit process this needs to be the new floor for security in web 3 if you're working with a protocol that isn't doing stateful fuzzing or invariance or fuzz tests red flag get them to use it make a PR number one understand what the invariants are number two write functions that can execute them do not go to audit without these don't let your Auditors let you get away with not having them so this video was just to give you the basics and if you want to learn the advanced fuzzing strategies and how to fuzz look Pro be sure to watch our next video on the topic CU that'll give you the keys to write professional fuzz and professional invariant tests come on gang let's make we three better and I'll see you next [Music] time all right so now we've learned a little bit about invariant tests or fuzzing tests and why they are so absolutely crucial especially for a project like like this so we're going to write some stateful fuzz tests or invariant tests in foundaries so we can have some more confidence that our code actually does what we want it to do and the method that we saw in that video that we just watched is kind of the most basic methodology out there if we go to The Foundry docs we can go on the left side go all the way down to fuzz testing or excuse me go all the way down to this invariant testing which invariant testing like I said is stateful fuzz testing and we can read more about some of the more advanced ways to do these fuzz tests or these invariant tests we're still going to do the target contracts but what we saw in the video was a type of open testing right where we just have function inv variant a and then the assert and what this does is it just calls all the functions on this contract to try to break that invariant now this is good this is great for an initial run of the code however we want to do for more advanced systems like ours Handler based testing sufficiently complex Protocols are going to have so many different random intricacies that we want to narrow down the random call so that we can have a higher likelihood of getting and catching actual errors so we're going to do this Handler based type of testing in this example here in this open testing it just calls any of the functions in the contract in any order and Handler B based testing if we scroll down we can kind of see this example here where we create a contract called Handler where we only call functions in specific ways for example when depositing tokens we need to make sure an approve happens beforehand if you just call deposit without approving that token that's kind of a wasted fuzz run and if we only have 200 fuzz runs and we're wasting them on failed fuzz runs well we're the chance of us actually finding a bug becomes smaller so if you think of the open fuzz testing like this where you have Foundry you call a whole bunch of functions on the protocol with the asserts Handler is going to call functions in specific ways is to the functions so that we have a higher likelihood of calling functions in orders that we want so we're going to learn about this Handler based methodology and we're going to build an incredibly verbose Buzz testing or invariant testing setup now in our founder. tol to work with these fuzz with these invariant tests we can do this in variant section here we can say the number of runs we'll say is 128 we can also say the depth which is the number of calls in a single run which we might do 128 and then one of the most important keywords you're going to run into is this fail on revert so let's talk about this fail on revert keyword and setting so to create some invariant tests let's create a new folder or Buzz test called fuzz or invariant or whatever you want to call it and in here we're going to need to actually create two different files we're going to do invariant in variance test. T.O and then Handler T.O this invariance file is going to have have our invariance AKA our properties of the system that should always hold right that we just learned from that video and this Handler this Handler is going to narrow down the way that we call functions this way we don't waste runs like I always saying again if we call deposit collateral in our stable coin without approving that stable coin that's kind of a wasted run and we don't want to waste runs so this Handler is going to set our code up set our contracts up so that we don't waste these runs and we're going to come back to this fail on revert in a second for now let's actually set this to false and we'll set it to True soon but so the first thing we always want to do when writing inv variant test when working with this is want to ask the question what are our invariants what are the properties of the system that should always hold well we can think of some right well one the total supply of DSC should be less than the total value of collateral the word wrap we the total supply of DSC which is essentially the debt should always be less than the total value of collateral great we have an invariant that we can test and we should throw a ton of random function calls to try to break this one okay what else what other invariants should we have maybe our getter functions our getter view functions should never revert and this is actually sort of an evergreen invariance most protocols can and should probably just have an invariant that looks like this getter view functions should never revert now we can probably think of more but because doing these invariant tests can be a little bit time intensive we're just going to focus on these two for now these are going to be the two invariants that we focus on and we try to work with so let's begin working and writing our invariant tests and we're also going to write our Handler to help make sure all the function calls that we're working with actually do what we want them to do okay let's do it so this is going to be another test file so spdx license identifier MIT pragma so oh oh that's nice that kind of just automatically added it for me let's put this to the top 0. 8.18 little carrot here contract invariance test like this and to do this we're going to say we're going have to import some stuff we're going to import test from forg TD test. soul and import STD in variant from Forge STD STD inv variant. Soul contract invariant test and then we're going to say this is STD invariant and and it's test so this STD invariant contract if we click into it it has all this stuff that we're going to need to work with the invariance one of the most important functions that it gives us is this Target contract where it says hey this is the contract I want you to call all these random functions on okay great now just like our normal tests we're going to have a function setup external like this and we're going to set up some stuff right a lot of this is going to look similar to our unit test so we're going to have to import Ploy DSC from do do script deploy dc. s.o import dsce engine from do do do SRC SL DSC engine. Soul like this and we'll say the deoy DSC deployer deployer deployer equals new deploy DSC and then of course DSC engine dsce dce equals deployer do run and this actually returns a whole bunch of stuff essentially stable coin dce and helper config so this is going to be we also need a DSC so we're going to import that import the centralized stable coin from do do SRC decentralized stable coin. Soul so we're going to do decentralized stable coin DSC and let's get the helper config as well import helper config config from do do script slh helper config dos. Soul config config right and so this turns the DSC dsce and config equals deployer run great and now if we were doing this open testing methodology right if we go back to the docs here we're doing this open testing methodology we could kind of finish this right now what we would do we would say Target contract address dce like this paste this in here and then just by adding this we're telling Foundry hey go ahead go wild on this right go absolutely wild in this and actually let's even rename this call this open invariant test. T.O open invariant test. tt. soul we'll say absolutely Go Buck Wild on this and now we can add our invariant right we'll say function inv variant variant underscore protocol must must have more value than total Supply and this will be a view function and what what we can just say is we want to get the value of the of all the ceral in the protocol compare it to all the debt or the DSC so we can do that pretty easily by using the collaterals itself right using our helper config we'll say helper config do Active network config we can get the what does this one do again let's open up the h config we can get these two tokens and just say okay well what's the balance of these two tokens in our DSC engine and then what's their value right so we'll just get those two tokens so we're going to do nothing nothing W Bitcoin nothing so we'll do blank blank we BTC nothing and then those are ERC 20s so we'll import import I erc20 from all right cool that looks good so we'll say erc20 we ic20 BTC this is wrapped BTC wrapped BTC oops sorry this is config Active network config we need to wrap this erc20 irc2 like this what am I messing up oh let's do do address we then address we address BTC like this all right cool so we're getting we in Bitcoin going be wrapped eth and wrapped Bitcoin and now what we can do is first we'll say un 256 total Supply equals DSC do total Supply so this is the total supply of all DSC in the entire world right and we know the only way to Mint DSC is through the DSC engine so through people depositing and withdrawing collateral now what we can do is we can say okay let's get the U 256 total total we deposited equals and this is where we can do ic20 we balance of address DSC so this is going to be the total amount of we deposited into that contract or just the total amount of we sent to that contract then we're going to say un 256 total BTC deposited equals ic20 wrapped BTC dot balance of address so we have the total we total Bitcoin now we can get those values we can say un 256 we value equals we have a function here called get USD value where we can get the USD value of any token of any amount so we're just going to use that we value is going to be dsce dog USD value we and the total we deposited un 256 wrapped BTC value same thing get USD value W BTC total BTC deposited and now what we can do is we can do assert the we Value Plus the wrapped Bitcoin value is greater than the total Supply and this is all we would need to do for this open testing this open invariance that's it we're done boom this is why this is the easiest type of invariant test but you'll see running this we won't get great results so let's do forg testm and now what this is going to do is it's going to call all types of functions on our dce and try to break this invariant so it looks like it was able to break this really easily so let's clear this and we'll add our Dash VV VV we'll see what's up yep yep violated we're having a hard time actually seeing the numbers so we're going to import console in here test console and we're just going to say console. log we value semicolon W value or that's w w BTC we we W BTC value console.log total Supply total Supply let's run this again now what do we get well we got our first issue is that these are all zeros right and if they're all zeros then this doesn't hold so we can do greater than or equal to this is kind of a bit of a copout right because if they're equal that makes us nervous but it's fine right we should always at least have more collateral in the system than total Supply so now let's try again run this test again run successful and we get hey you pass there's no way for us to make it such that the total Supply is lower so this is awesome right well it's not that awesome we didn't find any issues we're looking to find issues so maybe we need to bump up the number of runs we need to bump it up to a th000 and let's run this again now you're going to see this is going to take a lot longer because before I was doing 100 runs at 128 depth now it's do a th000 runs and each one of these runs has 128 so it took a lot longer and you can see that it took 14 seconds as opposed to what it do before with 128 we run that it did it in one and half seconds but if we look up here on this line this line is incredibly important we have calls and we have reverts so this made 16,384 calls and reverted 16,384 times so basically it wasn't wasn't even able to do anything right so what if we bump this up to a th000 clear run this we're going to have to wait few more seconds again oh so it did this many calls and it also reverted this many times and the reason that this is still saying pass though is because we have this fail on revert equals false and this fail on revert equals false has some pros and it has some cons the pro of fail and reverse equals false is that we can very quickly write open testing functions like this and we can very quickly write minimal Handler functions that aren't perfect but the downside is it's hard for us to make sure that all the calls we're making actually make sense right because this could be calling on our on our engine maybe it's just trying to deposit collateral but it keeps using random collateral addresses that don't make any sense so maybe it's calling this 128,000 times with 128 different collateral addresses but only two work right so doing like this is cool for kind of some sanity check and maybe it'll catch something but seems like it's not actually catching anything right and that's not a very good use of this so revert on false is fantastic for quick tests and often if I'm doing a competitive audit which you can learn more about in the security course coming out soon hopefully if I'm doing competitive audit a lot of times I will have revert on false be false just so I can write up in varant test quickly I will also write handlers as well like mini handlers just so I don't have to get every nook and cranny but I still will write a Handler so I can narrow down some of the functions but this open invariance seems to have this major flaw where it's probably making a bunch of silly calls so this is great for very small contracts but the more complex you get like our system here this open inv variant system it probably doesn't make sense for us to do because it's not going to catch anything it's just going to keep breaking now if we set this to true we open this back up we run this again you'll see exactly one of the calls it makes that breaks so it looks like it called redeem collateral for you for DSC this is the first function call it made which obviously doesn't make any sense because you can't redeem any collateral unless you have deposited collateral and and you can see the args it put in it put in some random address some random amount a random amount and then another random number right and you'll see we can call this many times and it'll keep giving us different places that it ran into issues when we say revert on false is true this can give us some peace of mind knowing that if this test passes that means all of the transactions that went through actually went through and it didn't make a bunch of of really dumb calls here right so here fail on revert was false we called liquidate first which obviously doesn't make any sense with this with some horrible random address some horrible random address some random amount right none of these make any sense we call it again we failed again it called deposit collateral mint DSC which is good all right so we're trying to deposit collateral but it used some random address that isn't approved some horrible amounts here and it just keeps failing right so we want to try to prevent and you can see here in the call summary it made one run one call and that call reverted right so we want to narrow this down to say to try to point our fuzz our random runs in a direction that makes a lot more sense right so this is cool not great open and variance I'm just now going to comment out this whole page because we're not going to use this anymore okay we're I'm going to leave the file in here though we're going to create a new file though we're going to call this invariance t. soul I am going to copy this whole invariance thing paste it in here and uncommon it and we're going to level this up so that this invariance file actually let's just call this invariance so that this new one is using this Handler method it's using this Handler method to narrow down the function calls and we'll do a mix of setting this to true and false and you'll see where some of the advantages and disadvantages are so so we have our invariance file we have our Target contract here but we want to make sure we call this in a sensical order for example hey don't call redeem collateral unless there is collateral to redeem right maybe we want to set this up so we're going to create a Handler which is going to handle the way we actually make calls to the dsce so it's basically going to instead of us just randomly calling redeem collateral we're only going to be able to call redeem collateral if there is collateral to redeem right cuz otherwise the transaction is just going to revert and that's a waste of function call so now we're going to create this Handler and instead of our Target contract being the dsce our Target contract is going to be this Handler which handles the way we make those calls okay so we're going to do spdx license identifier MIT as you already know fragma 0 solidity 0.88 a little carrot contract cont Handler like this and then we're going to say this contract Handler is going to be test as well and this is definitely some Advanced code here so don't get too discouraged if it doesn't make sense or if it's hard the first time okay so we're going to import test from forg STD test. Soul remember to ask questions and use the forms so what's one of the first things you want to do hey don't call redeem collateral unless there is even even collateral to redeem right we want to make sure that that's this is a valid run only call redeem collateral when there is collateral in there so this function this contract is going to do that for us we do need to make a Constructor though so that this Handler contract knows what the DSC engine even is right because it's going to be the one making the calls to it so we do need to import the DSC engine from dot dot slash do do slash srcds engine. Soul we also need to import the decentralized stable coin from the decentralized stable coin. Constructor and these are going to be the main functions these are going to be the main contracts that our Handler is going to call so we're going to say DS DC and then we're going to say decentralized stable coin DSC and in the Constructor here we're going to say DSC engine _ DSC engine and decentralized stable coin _ DSC and then we're just going to say oh cool I already added it dsce DSC engine and DSC isore DSC so because these are the contracts that we want the Handler to handle making the calls to Great makes sense so let's talk about this redeem collateral right let's just focus on on making this not revert so we're going to say okay call this when you have collateral so the first thing we probably need to do is what probably deposit collateral right so we'll create a function called deposit bilateral and this function is going to look a little different than the deposit collateral in the DSC engine right if we're looking here this is what it does we're going to set this deposit collateral function up in our Handler so that this transaction always goes through right it doesn't revert but we do want to keep the randomization right we wanted to deposit random collaterals that are valid collaterals so what we can do is we we can create a un 256 collateral seed and a u 256 amount collateral collateral and this is actually really similar to the fuzz test so in your handlers whatever parameters you have are going to be randomized so we're going to pick a random one of the valid collaterals to deposit and we're going to pick a random amount of collateral now I'm going to write this function without any guard rails and it's going to break and that's okay we're going to fix it as we go along but if we were to just not have any guard rails on this at all we would just say dsce do deposit collateral Co colateral and we would do you know collateral and an amount collateral we could actually just have this be address collateral and amount collateral and we'd say deposit this collateral and amount collateral and this of course is probably going to break a lot right because the collateral we're going to pass is going to be wrong this is a random address there are so many addresses and the amount of collateral could also break because deposit collateral reverts on zero right but I do want to show you what we're actually going to do in our actual contract here instead of having our Target contract be the dsce what we're going to do is we're going to say Handler is we're going to import this Handler so we're going to do import Handler from SL handler. T.O Handler Handler we're going to say Handler equals new Handler dce and DSC and now we're going to say our Target contract is just the Handler okay excuse me the address Handler now with this the Handler only has this one function so we're going to call deposit collateral through the Handler which is going to call our engine and since this is the only function for it to call this is all we're going to see if we see our invariance break so if I do Forge test- M paste this in we going to see it break almost instantly with an issue but it's only going to be deposit collateral because it's the only function that we have right we run it again it's still going to be deposit collateral because that's the only function the Handler has yes makes sense okay cool hopefully it makes sense in our Foundry Doo we could say fail on revert is false we could run this again let's make this a little bit lower 128 and let's see if we get any valid runs right let's see if we pick miraculously a valid address and we get success but oh it looks like we did do some valid ones but we've got a ton of reverts here we've got so many reverts here that almost half of these runs almost half of these calls were bad that's not a great use of our and this isn't really super helpful because of course of course our invariant here is going to hold cuz the only thing we've allowed our system to do is deposit collateral right ridiculous so if we turn this back to true we run this again we course going to break now because some of these deposits are going to fail right so it looks like if we call deposit collateral with some horrible address it fails right so that's one of the first things we want to to have our handler do we want to say hey you're only allowed to deposit valid collateral so what we can do in our Handler is we can set that up hey you're only allowed to deposit it valid collateral instead of passing any address as collateral we'll say U 256 collateral seed okay and what we're going to do with this seed is we're going to have it pick from our two collaterals we're going to have it randomly pick either we or BTC so we're actually going to create a function helper functions we're going to say function underscore get collateral collat from seed un 256 collateral seed and we're going to make this a private view function it's going to return an ER an I erc20 actually we're going to do an erc20 Mock and I'll explain why in a bit we got to import that import rc20 mock from at open Zeppelin contracts mocks slash is it mock ERC no erc20 mack. cool and so what we're going to do instead of this line is we're going to use this line this function to do it we're going to say if collateral collateral seed modulo 2 because we're only we only have two collaterals equals equals zero then return we we can get W by sticking at the top we'll say ERC 20 mock we ERC 20 mock WFT Bitcoin and right in our Constructor we can get all of our collateral tokens the I made a function way down at the bottom here called get collateral tokens which Returns the full array of collateral tokens if you don't have this feel free to pause and implement this what we can do we can say address array memory collateral collateral tokens equals DSC e. getet collateral tokens like this and we can say we is zero and R BTC is one that's how we can get those collateral tokens so we W BTC if collateral C divided by two is zero return We otherwise return wrapped BTC so now we have a function where we can only get a valid collateral type so instead of just depositing any collateral type we can say uh ERC 20 collateral equals get collateral from seed collateral seed and now we're still depositing a random collateral but this is oh it's got to be address but this is a valid collateral address so we're probably more likely to actually pass a transaction that will actually go through making us have more solid more good random calls so let's try to run this function now great success but we ran into an error right let's see what the error is so deposited collateral u u and 256 U and 256 with this huge collateral seed uh and nothing looks like we failed here it's clear let's rerun it with- vvvv so we can see a little bit output of why we actually failed okay we ran we still the only function we're calling is deposit collateral looks like this failed again we call deposit collateral with some weird args we could scroll up and see exactly why we failed oh we ran to this DSC engine needs more than zero so it looks like we tried to deposit zero collateral amount collateral was Zero yep okay yep so we tried to call was zero so amount collateral was zero so we know that this is going to fail so how can we make it so that this doesn't fail or maybe you're like hey like sometimes it will be zero like whatever I I just want a sanity check you can make fail and revert false right and we can run this again again and now we'll see how often this actually fails hopefully we cut down on the amount of times it failed oops let's remove those V's great it actually it does look like we cut down on the amount of reverts we got not a lot but we we did cut down the amount of reverts at least by adding this bounding of the collateral types but let's keep cutting down on these reverts and potentially even have revert on false be true right you're not always going to have revert on false be able to be true and sometimes it's quicker and just to have it false and write all your invariance and stuff but if you want kind of but is good to aim for this now the downside of always aiming for this is that if you make your Handler too specific maybe you'll actually narrow it down and remove edge cases that would break the system that are valid right so it's kind of this balancing game you have to play with these fuzzing tests and whether fail and rever to be true or false there's definitely a little bit of an art to this so the more you do it the better you'll get but in any case collateral seed amount collateral we need to now change it so that this amount collateral is bounded between one and some Max number right so we don't want this to be able to be zero so what we can do then instead is we can actually we actually can bound this so that in the same way we got a valid collateral let's get a valid amount collateral so we can say amount collateral equals bound this is a function that actually comes with STD utils and it bounds the result to an amount so we want to say okay this amount collateral we're going to bound our amount collateral to being between one we don't want to be zero and then some like really really big number what I like to do is up here in the state variables I'll do you in 26 Max deposit size equals and I'll do type uent 96. Max and this allows us to get the the max uent 96 value why are we not doing the max uent 256 well if we do the max un 256 and we try to deposit more collateral later if you do the max6 plus one you'll get a revert so this is going to give us a really really really big number but we're at least not going to hit the absolute top of amount of deposits we can deposit so we're going to say we're going to bound this amount collateral between one and Max deposit size Okay cool so let's put this back to false let's run this test again and let's see if we cut down on the reverse some more aha a couple more right only a few hundred but we did cut down on the amount of reverts why because we're passing valid well okay that one didn't go so well but we are cutting down the amount of reverts piece by piece we're able to bound the collateral but there's more if we do failon revert back to true we can see exactly why it's failing right we'll do- VV VV we can see an example that is indeed failing and whoa these are getting more intricate right before it was just a single call was breaking it oh okay so a single call still is breaking it but they are getting a little bit more intricate so looks like this one failed CU what we call deposit collateral we scroll up we're getting this insufficient allowance okay so that's why we actually weren't cutting down on the reverts at all because we're getting insufficient allowance of course we need to approve the protocol to deposit this collateral so of course this is breaking this is always going to break so let's do a little prank so we'll do vm. start prank we'll just do message. sender and we H will allow this message sender to Mint some of this collateral so that they can actually deposit it right so we can set this up so that whoever's calling deposit collateral actually has the collateral and actually will approve to deposit the collateral so and this is why I'm using this erc20 mock so that we can actually mint some of this collateral so we'll do collateral. mint message. sender amount collateral we'll do collateral collateral. approve address dsce for the amount col Al then we can deposit it and then we'll do vm. stop prank okay now let's clear this let's have revert on false to be false and let's see now if we cut down on the amount of reverts that we get oh and I added too many V's let's get rid of those let's run this again and yep there will be some brief delays in here of course whoa we cut the amount of reverts down to zero now all of our function calls are passing which means every single run was a valid run meaning we're using our runs much more wisely we're not wasting runs on failed reverts so now I can even set this to True run this again and we'll see this passes and none of our runs failed right so this means what does this mean from a security standpoint it means that no matter how how often we call deposit collateral no matter how much we deposit our collateral we will never make this invariant false which isn't saying too much because of course we're not even the total Supply is always zero of course this holds so this makes a lot of sense so let's actually keep writing more functions to do more with the system but set them up so that whenever we call them they're always going to be valid calls okay so now we were talking about redeem collateral right okay cool so now there's actually now we actually have a function a valid function to deposit collateral now let's actually have a valid function to redeem collateral so we're going to do the same thing function redeem collateral collateral we're going to do the same thing it's going to take a u 26 collateral seed for which collateral to redeem you 256 amount collateral so be a public and we're going to do something very similar here we're going to say we're only going to choose a valid collateral by saying erc20 mock collateral equals underscore get collateral from seed collateral seed and now we should only allow people to redeem the maximum amount they have in the system right so we're going to say un 256 Max collateral collateral to redeem equals DSC engine engine do get total get collateral balance of user do we have this function DSC engine so this is one that I added in it's going to get the collateral balance of a user if you passing the user in the token so if you want to pause and add this in feel free to do so get collateral balance of user where we add the address of the collateral and the message do sender so it's going to get the total balance of a user oh and this should be dsce then we're going to bound the amount collateral to this max amount that they have to make these always valid they should only be redeeming as much as they put in the system amount collateral equals bound amount collateral uh we're going to say redeem between one and the max collateral to redeem because we don't want them to redeem zero of course and then we're going to say oh this going to be public then we're going to say dsce do redeem collateral address collateral and amount collateral right so now we have two functions to randomly call so we're going to be depositing collateral redeeming collateral let's run this invariant it only has two functions it could call go to The Foundry DOL fail and revert is true oh and it looks like we found an edge case so now we can read this and see what it's doing so it's depositing some collateral when 381 and 82 and then it's Redeeming the collateral H not actually sure what's going on so let's add this Das vvvv to see more into the actual transaction that's failing oh my goodness we got an even bigger one here so what are we saying oh Max is less than the min oh looks like I'm messing up with my bounding so it's not even really an issue so if we go back to the Handler bound ma collateral One Max collateral to redeem ah okay so if Max collateral to redeem is zero this will break so we actually do need to keep zero in here and then we can just say if you know amount collateral equals equals z we could say if it's zero return or what we could do is we could use this keyword called assume like vm. assume which will say if the Boolean expression evaluates to false the fuzzer will discard the current fuzz inputs and start a new fuzz run so we're going to do if the amount collateral is zero just return don't call this function right because this is going to fail so let's go ahead and run this again now compiler run successful well would you look at that we are now passing again so people can if we go back to the Handler people can now redeem collateral and all of these redeeming are going to be valid and all these deposits are going to be valid right they can only redeem valid Redemption amounts now here's where this fail and revert equals true is can be a little bit deceptive let's say right now we're only letting you redeem the max collateral to redeem let's say there was a bug where a user can redeem more than they have this fuzz test wouldn't catch this it's because we have this fail and revert it's true if this fail and revert was false and we didn't have this line right and we just said this is the max deposit size this is a test where we might actually catch that bug right and if we run this now oh and with fail on revert is false we are going to get a whole bunch of reverts we are going to get bad transactions however and you can see we can see the number R verts over here and it actually is way less than it was before which is awesome and if we run it again still way less than 8,000 which is what it was before but if we have fail and revert false we can actually catch this so The Foundry team is actually working on allowing some tests to be fail in revert and some test to be not fill in revert so you can kind of pick which one for which functions instead of kind of having to blank it everything so just keep in mind the dangers here okay of always defaulting to fail on revert equals true okay they have their tradeoffs and if you do fail and revert equals false you can sometimes write these handlers a lot quicker but okay so we have some stuff here we can deposit collateral we can redeem collateral what else so we probably should figure out a way to get some total Supply right so what we're going to do is now we're going to finally make our mint function function mint DSC public like like this and what do we want to put in here well if we go to the DSC engine go to Mint DSC go to this mint DSC function it takes an amount of DSC to Mint so we'll do the same thing we'll say U 256 amount and that's it we'll mint a random amount so in here of course we can't have amount be of things right we can't have it be zero and they would need to not have their health Factor be broken so we're going to say amount equals bound amount one and let's say Max deposit size and then additionally this amount better be more than the value of the system right because we have this revert if Health factor is broken but maybe I don't even want to do that narrowing down maybe I just say screw it I'm going to make revert on false revert on fail on revert false and I'm just going to leave it like that because I'm nervous that I'm going to narrow it down too much so then maybe I just go screw it bm. start prank message. sender and we call in the DSC engine mint DSC dce do mint DSC and the amount then bm. stop Rank and this is where actually you'll see sometimes some people will have continue on revert and a fail on revert fail on revert see people some people can have two types of folders continue on revert is going to be the quicker looser test where it might look like this the fail on revert is going to make sure that every single transaction that you run your invariant test sued on is going to pass I personally think it's good to have both when I'm writing invariant tests I actually start with to continue on revert because they're faster often times you can find bugs as as long as you narrow down them enough so for now let's go ahead let's have this be false see if we can find any issues like this so we'll go up up so we'll run Forge test DM just going to run this invariant test boom let's see if we got any issues here we'll see how many reverts we get as well we got a similar amount of reverts which is good similar amount of calls which is all right and then actually if we do- VV we can even see the consant the logs at the end end it looks like it hasn't found a way to Mint more tokens than collateral in the system oh and even it looks like the last run it ended with a total supply of zero right but maybe I'm paranoid let's actually go back to true and let's just stay true for the rest of the rest of this but like I said I think it's good to have both types of test anyways Handler so this mint DSC we should only be able to Mint DSC if the amount is less than the collateral so what we can do is we can call this get account information which gets the total collateral value in USD and total DSC minted and make sure that we're always going to Mint less than the collateral value that we have so we can say we can actually just copy these two paste it in here equals dsce dot copy this function paste message. sender so we're going to get the total DSC minted B value in USD and what we can do is we can say we'll just have them always mint the max DSC they can mint so we'll say un 256 Max DSC to Mint equals collateral value in USD we could say the collateral value in USD divid by 2 minus the total DSC minted better be greater than zero right better not be a negative number so we can even do like an INT 256 and and then if this is negative then we're just going to return otherwise we're going to say amount we're going to equals bound this again say amount zero comma Max D to Mint and we're also going to say if amount equals zero we're going to return oops and then actually we need to grab this start prank put this down here that's all we need to do we should probably just grab these put them down here we don't need both of these so we just need this I think yeah we don't need both of these we only need one of these so we'll do un we'll convert this back to a un 256 if amount of zero return this looks pretty good to me let's see if we made this actually work let's run this and now we can mint DSC successful and bada boom so we have some Falls we have no reverts this is great but I keep getting total Supply is zero down here so we plenty of we plenty of WRA Bitcoin are we ever calling this function H we keep getting a total supply of zero down here why is that how could we figure out if our mint DSC is actually getting called let's first off see if this mint DSC is even being called we can use something called ghost variable to track this so in here up at the top we'll make a function called un 256 times mint is called make this a public variable and at the bottom of mint DSC we'll do times mint is called plus now back in our invariance we do a console.log Time min called comma handler. timesm called and then we'll run our test again oops with- VV and we can see oh mint is actually never called how is that possible well it must be because one of these returns is hitting and it's not finishing this call so we could keep moving this up to figure out where it's actually being called and to continue to debug this but I already know how to debug this of course because I've done this a while if you want take this as a challenge for you to answer the question why is this never being called why is times Min being called Never being called why is it never finishing so feel free to pause the video try to debug this yourself and find out and then I'll tell you the technique that I used to debug this and figure out why this mint DSC was never being finished all right welcome back did you actually pause the video did you actually try to figure it out if you didn't I'm giving you a second chance pause the video go find out pause the video and take this as your opportunity to try to debug okay why is this not getting hit why is this line not hitting all right welcome back now there was a couple different ways that I used to actually debug this one of them was having this times Min called plus equals 1 and then moving it up so I found the line that it was breaking on once I found the line that it was breaking on I console D loged all the values of the different variables around one of the most important variables that I dumped was going to be the message. sender so when you're working with invariance remember it's going to call this contract with a ton of different functions and a ton of different calls however it's also going to call them with random addresses as well so in order for us to Mint DSC we need to only mint DSC with an address that has actually deposited collateral because it's impossible for someone to Mint DSC without them depositing collateral now again if we restrict this function like this maybe there is a case where you can mint DSC without depositing any collat r that we don't know about this is again why it's important to have some open and variant tests some continue on revert and some fail on revert as well so if we want to have this be fail on revert we would need to only pick a message that sender that has some deposited collateral so what we can do is actually keep track of people who have deposited collateral and then when we go to Mint we just choose an address from somebody who already has deposited so how can we do that well we can just keep track of an array of addresses that have lateral deposited so up at the top well let's actually keep this times mint is called we'll put it at the bottom times mint is called plus plus and this way we know how to test this right if times myth is called increases we've known we will know that we fixed the actual issue so times myth is called plus plus at the top we'll do a address array public users with collateral deposited we'll copy this address and now in deposited collateral users with collateral deposited. push message. sender now there's some caveats here this will double push obviously some people so this will double push if the same addresses push twice but for now let's just keep it simple and let's go ahead and just leave it like this we probably should check to see if someone has already deposited collateral but whatever we're going to go with this for now because simple and then now in our mint DSC we can do something similar to what we did with collateral so we'll do a underscore U into 256 address seed and instead of bounding to message. Sender what we can do is we can say address sender equals users with collateral deposited it's going to be the index of the users with collateral deposited of Anders seed mod users with collateral deposited do length and now now instead of message. sender we're going to use sender in here same thing with down here we're going to use sender now let's run this and see if mint is ever actually called aha so this was very helpful redo it let's do das VV VV ah okay so at least we're getting something different here right we're getting an error division to module by zero ah okay of course we're getting module by zero because if the collateral length is zero then obviously sender is going to be zero so we can do if users with collateral. length equals equals z then we're going to return we're going to skip this one so let's run this again okay so we're getting some stuff passing let's actually just do a 2vs so that it's easier to read than all those events aha total times mint was called is now 31 and we're getting a total Supply so our mint DSC function in our Handler is now actually working we're now successfully calling mint DSC and it looks like our protocol is holding up all right fantastic so we're getting closer to building this Handler to actually have a solid Recreation of all the possible functions we can actually do in this system something I didn't show you was we should pretty much always use a given invariant called function invariant Getters should not revert like this and then we just put in here all of our invariant like dsce do get liquidation bonus dece do get Precision Etc put all of our Getters in here and oh and this could be public View and if any of these revert then this will fail this invariant test will call a ton of different functions on the Handler and if any of the function combinations break any of our Getters we know we broke an inar this is a layup and variant that everyone should always 100% include a way to make sure that you're including everything is you can run something called Forge inspect DSC engine methods and it'll print out all the different methods that this function has in addition to its function selectors so you can kind of use this as your checklist of all the different functions you can call on a contract and you can look for all the view functions in here this is additionally why it's great to have get in front of these words because becomes very easy to figure out which ones are Getters but it doesn't reflect the whole world right one of the other really fantastic things we can do with the Handler is we can both handle our DSC engine but any other contract that we want to simulate for as well and there's a lot of things we want to take in mind when writing these especially the other contracts that we interact with what are some of the other contracts that we interact with well one of them is going to be the price feed one of them is going to be the we token the wrapped Bitcoin token so our Handler should probably also show people doing random weird things with we and rap Bitcoin right because people are going to do random weird things with both of these tokens and we want to make sure our system can work with them appropriately now I'm actually going to skip them for now but I am 100% going to do one with price feeds because price feeds are definitely a system that can change and definitely A system that greatly affects our protocol so we're going to include price feed updates in our Handler so what we're going to do is we're going to go ahead and do import the mock V3 aggregator from slash do slash MOX mock V3 aggregator doso or where is this located oh just one like this okay and this mock V3 aggregator has some functions that allow just easily update an answer right which is what something that we want to do we want our protocol to be able to easily update answers so we'll take this Mach V3 aggregator and let's at least get the we price from our system so I have a view function dsce doget collateral token price feed and I'll pass the address with oops and I'll say eth and I'll make another variable mock V reator public eth USD price feed I'll say eth USD price feed equals this and we just got to wrap this up as a mock V3 aggregator this and great now we have an eth USD price feed and now we can add a new function in here so we have mint DSC deposit collateral redeem collateral we can add a new one called function update collateral price we'll do a un 96 just so that the number isn't too big new price and then we could also randomize the collateral but for now we'll just have it be the eusd so we need to convert the 96 to an INT 256 new price int equals int 256 new price because price feeds take int 256s oops s this should be in and to convert a u in 96 to an in 256 we actually have to wrap it as U 256 first and then to an in 96 do update answer or set price or whatever we want to do to this new price like this boom and now simple as that we have an update collateral price well an update eth price anyways so now now we can do three things in our system we can update the price redeem collateral deposit collateral and mint DSC so before we actually run this what do you think do you think we'll get n what do you think we'll go on let's run this well it looks like it found a sequence it found an issue the reason assertion violated which means means that our invariant here was broken the we Value Plus Bitcoin value now is no longer the total Supply so let's scroll up let's see what the issue is here all the way past everything and if we read the sequence we can figure out why this broke we can see exactly what happened okay so first it called deposit collateral Okay cool so we deposited some collateral and then we minted some DSC okay cool we minted some DSC with some stuff here and then we updated the collateral price to 471 so as we know our Handler update collateral price if we scroll the way to the bottom update collateral price 471 updates the eth collateral from $2,000 which is 2008 to 471 so this remember is 2 1 2 3 4 5 6 7 8 it went from this this to 471 so of course it reverted right because people minted a ton of collateral they deposited collateral they minted a ton of DSC right look at this input it's massive and the system broke and if we run this again with fewer V's right VV we'll be able to see that total Supply we scroll up we'll be able to see the we value W Bitcoin value and the total Supply here so actually it looks like in this one it set the new price to three so obviously the we value is probably zero or just about zero it let them mint DC because originally the collateral was wor was worth something and now it's worth almost nothing right so this is an important thing for us to take in mind in our system hey if the price drops or spikes quickly our system is screwed our system is busted and this is something we would want to know about and potentially go back in our code and fix hey what do we do when the price plummets in a single block right now we have kind of this assumption in here where we have this liquidation 10% bonus and the collateral always needs to be 200% over collateralized with this we're saying okay between 200% over collateralization and 110% overcollateralization as long as our system is within this it's still safe I mean obviously it's better if it's above this but as long as our system is within this it's still safe but if the price plummets of some collateral and let's say that's the only collateral maybe we get to 50% collateralization rate and that would break our entire system right that would break our invariant and our system will be screwed so we go back to the drawing board figure out how to smooth this out or we can say this is a known bug if the price fluctuates or explodes too quickly or too slowly this protocol becomes worthless and that's kind of not a great solution right so these are things we have absolutely want to keep in mind and these are things that we can find with invariant tests and this is why they're so important so for now in our Handler I'm actually just going to even comment this out because it does break our test Suite but I'm going to put a little comment here this breaks our invariant test suite and this would 100% be something that shows up in a smart Contra AIT saying hey if the price of an asset plummets too quickly the system's breaking because it breaks the invariant all right great now there's a few more things I want to teach only a few and then we're done with this section we're going to teach one some proper Oracle use and then two we need to write more tests which we're not going to do I'm going to leave that to you but we have a whole bunch of other contracts in here like the decentralized stable coin and then three some smart contract audit preparedness some smart contract audit preparation so let's start with some oral proper use so in our DSC engine we're of course using an oracle right we're using chain link price feeds now this is kind of an assumption that we have in our protocol right now hey price feeds are just going to work but price feeds are a system just like anything else and we should add some checks in our code here just to make sure that if this breaks or if something in here breaks our system isn't broken so what we're going to do is we're actually use that Library methodology we made years ago to write some checks on this price feed so I'm going to make a libraries folder and we're going to make a new contract in here called oracle. and what we want to do is we want to check to make sure that these prices aren't stale if we click on any one of these prices like eth USD let's scroll up to show more details more details you can see they have this heartbeat where a new price should show up at least every 3600 seconds I believe what this is right yes on theoa testnet we want to write some checks to make sure that this is actually updating every 3600 seconds and if it's not we should probably pause the functionality of our contract so we're going to make a spdx license identifier MIT pragma solidity like this we're going to do a library Oracle lib and let's put a little natat speec to explain what this is going to do say at title Patrick Collins oops title Oracle lib at author Patrick Collins at notice this library is used to check the chain link Oracle for St sale if a price is stale function will revert and render the esce engine unusable this is by Design so we're going to say hey if a chain Le price feed is stale just stop don't let anything happen because if a price is wrong if a price is bad our whole protocol is kind of bunked right so we want to just freeze everything so we want the DSC end to freeze if prices become stale so if the chain link Network explodes and you have a lot of money locked in the protocol too bad this is something that's going to be a known issue right if the chain link Network blows up and all the prices become stale H you're kind of screwed right and maybe this is something we want to account for but for now I'm just going to say that's a known issue and we're going to move on and this is where you'll see me start to get more and more partic particular about stuff this is where as we get more and more advanced this is where the details start to matter more and more right all those little little things that I kind of gloss over they become to they start to become more and more important as this becomes closer and closer to a real production product that should go to audit right so let's create a stale price check function so we'll create a function stale price check and we'll have this stale price check be on an aggregator V3 interface. Soul so I'm actually going to copy this place it in here toggle the word wrap and so as an input parameter it's going to take aggregated V3 interface price feed this will be a public view which will returns a uin 80 in 256 uent 256 uent 256 and a uent 80 the same return value of the latest round data function in an aggregator B3 interface function like this okay cool and in here what we're going to do is we're going to call Price feed dot latest latest round data and I'm even just going to cheat a little bit we're going to control click into this we're going to copy this line paste it here equals boom just so I don't have to type as much cool we have all those and what we're going to say in here we're probably not even to use all these we're going to have some stale check right so each one of these price feeds has their own heartbeat so we probably should ask them what their heartbeat is but I'm just going to hard code it for this one I'm going to say ENT 256 private constant timeout equals 3 hours and this is a constant in solidity it stands for 3 * 60 Minutes * 60 seconds equals uh this many seconds so looks like this heartbeat is actually much longer than the one that chain link should allow so 360 seconds is 3,600 seconds is just 1 hour right we're going to give it 3 hours so what we're going to say in here is we're going to say first we're going to do a un 256 seconds since equals block. timestamp and then we'll have uh excuse me minus updated app and then we'll say so this will get the current block Tim stamp minus this updated app so this should basically get us the seconds since this price feed was updated then we'll say if seconds since it's greater than our timeout then we're going to revert with a new error error or colore stale price this revert with stale price and then we're just going to return all of this stuff so return round ID answer started at updated at answer it around and I'm going to change this name to stale check latest round data now what we can do since this is a library on our price feed we can use this stale check latest round data to automatically check to see if the price is stale so now in our DSC engine anytime we call latest round data we just swap it out for stale check latest round data so long as at the top we go after our errors we're going to put our types after the errors we're going to put types so this is where we would do using Oracle lib or aggregator B3 interface we need to import Oracle lib let's import Oracle lib from going to be libraries libraries Oracle lib Soul like this and now yep any place we use latest round data we can now use stale check latest round data where we have this stale check baked in and cool now we did a ton of refactoring let's run Forge test just run this whole test Suite including the invariant test Suite okay and stuff's looking good here and you can see that it even took a lot of extra time to run this last bit so cool so we've got a little check here great we're not going to write some more tests this is something that you should 100% do we pull up our terminal here we run Forge coverage what do you think we get get this which you can see there's a whole bunch of contracts that we need to test this Oracle lib could probably use its own test Suite even though it's looking like a lot of it's tested we probably should definitely test this ourselves we need to write test for this we probably want to test our uh our DSC some more for sure so we should definitely write some more tests I'm going to leave that to you this little little finger here and then finally some smart contract audit preparation so we talked a little bit about what a smart contract audit is and we haven't covered a whole lot of security stuff yet we're going to do that later in the course but a solid place you can look is this audit Readiness checklist from the nent XYZ GitHub repo which has a lot of different things that you should and keep keep in mind when running your tests for those of you looking to be really serious about actually launching a protocol and really having the security mindset that you need as well be sure to get to this last section in the course about intro to security because this is where we're going to give you a lot of that lower level security stuff at least from a smart contract developer perspective we're going to give you all the basics that you need to be aware of in order to stay secure so we're not going to talk about it too much in this one but it is something that if we were to actually launch this we would need to keep in mind so I'll put a little soon Emoji here for coming very soon all right so with that all being said we've done an absolute ton here this is 1,000% a project you should push up to your GitHub repo and this is 1,00% a project that if you this far you should be incredibly proud of yourself this is the hardest most complicated most advanced project in this course and to be honest probably the most advanced project you'll work on in almost all of web 3 there's so much going on here we learned about defi we learned about advanced state-of-the-art modern fuzzing techniques we learned a tiny tiny bit about security we used Oracles in a safer way we wrote this crazy amazing test Suite we wrote deploy scripts for this we wrote We interacted with a couple different libraries we learned about this fail on revert runs depths and variance the only thing we didn't do was write a proper read me which you 100% should write a proper readme and if you want you can check out The Foundry defi stablecoin readme to see how it actually works of course even for me this was a long difficult project for me to build because because there's just so much to think about like I said this is a project that I am planning on getting audited so what you're going to see in this repo is you're going to see kind of this main branch which is what you're going to be working on but but I'm additionally going to make a new branch called like audited or post audit or something like that and if you want to follow and watch this GitHub repo you can see the progress and you can see the audit reports that come out on here so that you can be intimately familiar with this code base already because you wrote some of the code and then also see as it progresses through its security journey and for those of you who are looking to actually release production code you definitely need to be at least aware of how security works and the security paths that your code should take but all right with all of this being said you know what time it is it's time for you to get a break you deserve it you should 100% go take a lap push this code base up to GitHub and actually clean it up a little bit I'm going to be cleaning this up a little bit before I push the rest of it to this GitHub repo so you should clean it up a little bit make it yours make it the way that you want to make it maybe even improve on it right we saw with the invariant test that there is at least one other glaring issue with this protocol if the price of the assets collapse too quickly our protocol becomes insolvent so maybe you come up with a method to fix it and then maybe you launch your own stable coin why not right in any case good luck to you take that break we only have we're getting so close we only have one two three more lessons and these ones are actually easier than the one we just did we're going to learn about upgrades and proxies we're going to learn about governance and then we're going to do an introduction to Smart contract security these are much easier than everything you've done so far so take the break give yourself a pat on the back be incredibly excited celebrate this win this is a huge achievement getting this far and I'll see you very soon three more left and as a bonus piece of content here another one of the reasons that I absolutely love the a protocol and the a team is that they're just shipping protocols and shipping amazing products and features and services for for the web 3 Community one of those protocols is something called lens protocol which is a decentralized social layer or a decentralized social platform for building social medias so to give us some information about this we have the head of devr for lens protocol and The A Team n dbit to talk a little bit more about lens hi my name is Nat dbit I wanted to give you a quick introduction to lens protocol and why it might be interesting to you as a smart contractor solidity engineer lens is the social layer of web 3 it allows developers to build social applications or to implement social features into their existing applications there are 4.9 billion people in the world today already using social applications so these types of apps provide a use case that people already know understand and value they also present a wide variety of value propositions and opportunities for developers to take advantage of and build on and with web 3 features like native payments ownership and composability also provide a lot of Primitives to build on that were not available with traditional social applications or infrastructure lens allows developers to extend the core smart contracts by building out their own custom modules this would be similar to as if Twitter Instagram or other social applications allowed developers to send pull requests into their backends and apis this opens the door to a lot of interesting and Powerful functionality that we're seeing developers integrate into their applications build out new different ideas but also integrate into other parts of web 3 like defi in addition to that you can call Lens smart contracts from other smart contracts so if you'd like to build out something that is composable with the web 3 social graph lens is a great place to integrate if you want to get started building on lens check out the docs at docs. lens. XYZ and be sure to check out how to deploy the protocol on your own so you can check out the smart contract code and play around with it and also look at how to build out and create your own custom modules thanks for checking this out Okie doie all righty welcome back you may have noticed that my voice has got slightly higher and less caramelly and that's because I am Kira not Patrick and I am going to be taking you through the next section of this course so for this project we are going to be exploring Merkel trees and signatures to build our very own airdrop contract let me take you through the code and what we are going to be learning very quickly before we get started so first of all what is an airdrop so essentially as you can see from my awful drawing here an airdrop in the context of blockchains is where a token development team send or allow people to claim tokens these tokens can be any type of tokens so ERC 20s ERC 11 55s ERC 721s but in this section we will be creating an erc20 airdrop these tokens are gifted or given to usually for free aside from the gas fees certain wallets so normally there's some kind of Eligibility criteria such as having developed on their protocol on GitHub or maybe they're part of the community or the like and this helps to bootstrap the project so usually there is going to be some kind of list of addresses which are able to claim tokens let's walk through this code base very quickly so if you head inside source then you'll be able to see the bagel token and this is the erc20 token that we are going to be airdropping and it's a very minimal ERC C 20 token similar to what we have done before and then back in Source you can see this Merkel airdrop contract and this contract is going to be using Merkel proofs to prove that an address is eligible to claim it's going to implement a claim function to allow people to receive the air drop but it's also going to allow anyone to call claim so that allowed addresses can receive the airdrop without paying for the gas fees but we are also going to implement signatures to prevent people from receiving airdrops that they actually didn't want to claim so we're going to finally learn what this VR and S mean how to validate signatures how to create signatures and everything to do with signatures we also going to create some scripts to generate our Merkel tree to generate the proofs and the root hash and also to deploy the contracts and interact with them we'll be taking a small segue into of course Merkel trees and Merkel proofs signatures ecdsa what the heck does that mean and also transaction types so buckle up because this is going to be a big one I'm going to show you a brief demo on a ZK sync local chain running in Docker however you're not expected to run a local ZK sync Docker node if you don't want so I'm going to run this script just to show you what we are going to be building so I'm initializing a ZK sync local node I then deploy my bagel token contract I deploy a Merle airdrop contract I then sign a message to allow someone else to be able to call claim for me and give them permission to be able to call claim so I can receive the airdrop tokens I then create some initial supply of my tokens I send it to the airdrop contract to be able to issue to all of the claimers I then claim the tokens on behalf of the claiming address so the function is called by another person so that they can pay for the gas using my signature that I created and then the address receives the airdrop tokens and we can see a nice little balance here now that might sound confusing but as we walk through things I hope things will become more clear so now that we are airdrop experts and we know exactly why we are going to want an airdrop our tokens let's go ahead and make a project to airdrop our special tokens to some users that we specify so the first thing that we need to do is to create a repository to create our project into so I'm going to do a little mkd Merkel and you might be thinking right now what does this word Merkel mean you may have seen it in the project overview but we will explain what this means in a second so then I'm going to navigate inside this repo and then I'm going to make sure that I am on the regular version of Foundry rather than the ZK version of Foundry by running a Foundry up Okie doie okei and now we're going to open this up in our vs code now you can see that we've got an empty repository and we can run Forge in it to initialize an empty Foundry project in our repo we can go ahead and delete these usual files as we have done done so or Patrick has done so every other time so delete delete and delete and then we are going to make a new file we're going to call it Merkel airdrop dool oh air drip and then we're going to do the usual spdx license identifier MIT pragma solidity .8 point and as I'm recording this the most recent is 25 but I'm going to use 24 and then contract Merkle airdrop like this so what do we want to do in here so I want to have some list of addresses and then I want to be able to allow someone in the list to claim tokens so I'm also going to need to create a token contract so I am actually going to create a token called Bagel token because I don't know about you but bagels are pretty good I am a big fan of bagels so the very first thing we need to do is we need to create these tokens for people to be able to claim so we're going to do the very very same we can go again spdx license identify MIT and then we can use pragma litery 8.24 and then I'm going to do contract Bagel token and then I don't want those comments this time so what we're going to do is we're going to use open Zeppelin to create our ERC 20 token to air drop to our list of addresses so these want to be ERC 20 tokens first of all I'm going to just run a forge import oh sorry Forge install so the next thing I need to do is I need to install open Zeppelin so I need to run Forge install open zeppin open open zein slash openin Das contracts no- commit in The Foundry tummel we can just create a remapping remappings equals open Square brackets and then we can do at open then SL contracts slash equals lib oops lib SL contracts SL contracts and I think I did a back tick here I did that needs to be a single quote okay so let me just check that remapping yep that's all good so now we have our remapping in place we can head back to Bagel token and now we need to import erc20 from P Zeppelin contract toen erc20 er20 dool thank you very much copala and then we are also going to import the ownable Oops I did have it there for a second we're also going to import ownable from open Zeppelin as well because we want our contract have an owner so they can mint tokens to whoever they choose Etc so our Bagel token is erc20 and ownable again thank you co-pilot now we need to have our Constructor and we do want it to inherit from erc20 like it's saying we actually also do want a mint function so that we have the ability to Mint but actually we don't want this initial Supply so we do want a mint function so we do want to be able to Mint tokens to people like the owner to be able to Mint tokens to whoever they choose but we don't want this initial Supply so we can remove that and so here we need yes we do need to pass some Constructor prams to the erc20 Constructor and then we also need to pass the message sender to the ownable Constructor and this is just saying that whoever deploys the contract is going to be the owner of this contract and so that is it we have now our very very simple Bagel token contract and so if we head back to our airdrop contract now in our tests or when we're deploying we'll be able to use this Bagel token and actually what we're going to probably do is we're going to pass it through to the Constructor of our airdrop contract we're going to want this contract to be adaptable for any erc20 of our choosing so we want to be able to pass in whatever erc20 we choose let's say I was the owner of usdc I want to be able to airdrop usdc to my trusted loved followers or maybe I'm an artist and I have my artist token and I want to aird drop my artist tokens to the holders of my nfts I'm going to want a contract that I can pass this cc20 through so I'm not going to hard hardcode it but before we do that let's just have a think about how we're going to airdrop our tokens to our list of addresses now you may think maybe I'm going to have some kind of address array and these going to be like my claimers and then I'm going to say Yep this is my address and then I'm going to make some function claim which is going to be external and then it's going to do something like for I and then it's going to be like blah blah blah like claimers do length check some past and address address um some account and I'm going to check the account is in the claimers however there's a problem with this the problem with this is that each time someone claims we're going to have to Loop through this array now what happens if this array is super super long what happens if I've got hundreds of claimers you can imagine that the gas to call this function is going to be extortionate I'm going to have at some point some kind of dos denial of service where someone calls this function and they're going to run out of gas because they're going to be looping through a mahive array so in order to solve this problem we are going to use Merkel proofs now what are Merkel proofs essentially Merkel proofs allow us to prove that some piece of data that we want is in fact in a group of data so if we've got some group of data like a group of addresses all with an lowed amount is my address in that group of addresses Merkel proofs enable us to do this and Merkel proofs come from Merkel trees and Merkel trees are the data structure that is used here and now in the next video we are going to explain this in a little bit more detail because that sounds super duper confusing so you're going to have to hold tight with me for a second and we will come back once you understand what Merkel trees and Merkel proofs are and then we're going to implement it have you ever heard the terms Merkel tree Merkel proof root hash what the heck do all these words mean Merkel trees are a data structure in computer science Merkel trees are used to encrypt blockchain data more securely and efficiently it was invented by Ralph Merkel in 1979 he also happens to be one of the inventors of public key cryptography in order to understand what a Merkel tree actually is it's easier to just see a visual representation this is a Merkel tree here you can see at the base of the tree there are four distinct pieces of data these are known as the leaves or Leaf nodes of the tree and each one represents the hash of some data and at the top or the root of the Merkel tree is the root hash and it's created by hashing all of the individual nodes together as Leaf node hashes so adjacent nodes a hashed together and then the output hashes are also then hashed together in a tree like structure a miracle proof is a way for someone to prove that some data is in one of those leaves to someone who only knows the root hash for example if we had some data which we could hash to produce hash one we could prove that that data was in the Merkel tree so for example let's say we had a club where there were different tiers or levels to the club maybe we had like a bronze silver gold Platinum situation or something like that and for each of those levels you have a password to prove you're part of the club you could create a Merkel tree and then a Merkel proof for someone to be able to prove that they are in a club so in order order to prove that the data in hash one was present in the Merkel tree or if someone wanted to prove that they were part of a club all we need to do is provide hash two and hash 34 so the proof would simply be the array of these two hashes since we can compute hash one we can then hash that with hash two to produce hash one two and given that hash 34 is in the proof we can then hash that together with hash1 two to produce the root hash which we can then compare with the expected root hash and this provides the root verification note here that for a successful Merkel proof you need to provide all sibling nodes at every tree level which since we were able to calculate these values we have done since secure hashing functions like kak 256 are used to create the hashes it's practically impossible to create a hash Collision so the likelihood of two different messages two different pieces of data two different inputs creating the same hash is practically impossible and won't happen in practice therefore if you receive a matching root has in the Merkel proof you know the item really must have been in the Merkel tree and part of the original root has calculation Merkel trees are used in lots of different circumstances most notably proving smart contract state for example they are used in rollups to prove State changes and verify the order of transactions they are also used in efficient airdropping to prove that a potentially claiming address is part of an allow list of addresses which are able to claim using Merkel trees we can enable some addresses to claim and others not by including the addresses that we want to be able to claim as Leaf nodes as part of a Merkel tree now you might be thinking hang on a second Kira why would I need Merkel proofs for my airdrop can't I just use an array of addresses and so if we look at this example where we are in fact using an array of addresses you can see that every time someone calls airdrop they would have to Loop through all of these allowed addresses now imagine if this allowed addresses array is extremely along maybe thousands tens of thousands hundreds of thousands of people are in this allowed address array at some point the gas to cool this airdrop function is going to exceed the gas limit and it's going to become extremely expensive to cool and Loops through unrestricted arrays can lead to a denial of service in which someone is unable to claim the airdrop therefore we need to use Merkel proofs instead the Merkel proof. Soul smart contract from open Zeppelin is an easy way to implement Merkel proofs into your smart contract let's take a look quickly at how they Implement that the verify function in this smart contract takes the proof the Merkel rout and the leaf that we want to verify as inputs typically the rout is stored in the smart contract somewhere and the proof will be created off chain this then calls process proof which then iterates through each element in the proof array provided we start by taking each Leaf node and then the computed hash is updated at each step by hashing it with the next element in the proof note here that hashing two hashes together it will always take the smaller of the two hashes first and open Zeppelin uses kak 256 for the hashing algorithm here you can see that they are in fact using assembly but this is essentially the same as ABI encoding the two values together and then hashing that output process proof then Returns the computed hash and this is a calculated route which is then compared to the expected route to determine whether the provided Leaf was in fact present in the Merkel tree and that is a very brief summary of Merkel trees and Merkel proof Merkel trees are just a cryptographic data structure using hashes and Merkel proofs are just a way of proving that some data is in fact in the tree and they are often used in airdrops and also verifying State changes in smart contracts and in rollups and that was a very quick video on Merkel trees and Merkel proofs okay now you understand all about Merkel proofs and Merkel trees let's go ahead and implement this into our project now so like I was saying earlier we are going to want to have a Constructor which you can pass in your erc20 token now the other thing that we're going to want to pass in is the Merkel rout because we're going to need it to be able to compare the proofs and the calculated root hash from the proofs for each user when they try and claim and when we deploy the contract we're going to want to specify what that list of address is what the amounts are that each address can claim and that is going to be defined by the Merkel route so we're going to Define our Constructor right now so we got const drug door and then I'm going to have in here byes 32 Merkel rout then I'm also going to pass in IR ERC 20 and oops that's not spelled right I erc20 drop token and then in here I'm going to want to save these values as storage values so I'm going to have byes 32 private immutable Merkel route and then because this is immutable I'm want icore and then in here I can go icore Merkel root equals Merkel root and then actually icore a drop token which we need to Define equals airdrop token so then I've got ioso 20 private immutable I airdrop token and then the other thing we need to do is we need to import the ic20 interface from open Zeppelin so that we can use the functions on this airdrop token now we need to create a function in order for our users who are in this allow list which is defined in our Merkel Tre to be able to claim so we're going to create a claim function so we've got function claim external this function is going to take as parameters the address that wants to claim and this allows other people to be able to claim for us and pay for our gas U into 56 amount and this is the amount that we want to try and claim byes 32 call data because we need to specify where we want to be saving this because it's a byes 32 array and arrays you need to Define where they are stored we're saying this is co data and we're going to name this Merkle proof Okay so we've passed through the account that wants to claim the amount that they want to claim and then also an array of the proofs the intermediate hashes that are required in order to be able to calculate the root and then we can compare that to the expected root or the actual root so next we need to calculate using the account and the amount the hash which is going to be the leaf node and this is because this is what our Merkel tree is actually going to look like and you can see here these are the values in the Merkel tree so you have an address and an amount to claim and in our claim function we provided an address that would like to claim and an amount that they would like to claim as well so we need to calculate the leaf hash so that we can use the leaf hash alongside the proofs provided to calculate a root hash which we can then compare to the expected root hash which we provided in the Constructor of the smart contract ract so let's make that right now so we've got bytes 32 Leaf equals kak 256 ABI and code packed we don't want packed we just want to a encode them account and amount okay cool so what does this mean so we've we've encoded the numbers together we've mashed them together and then we have hashed them so we've made them into one value and then we have hashed them together okay that makes sense and looks like it should work but actually when we're using Merkel proofs we need to do something very particular and I'm going to show you that right now we actually want to Hash it twice so we're going to do a kak 256 again but also before we do that we need to do bites. concat first now why do we do this why do we do both of these hashes and why do we concatenate the bites when we are using Merkel proofs and Merkel trees we want to Hash it twice and this avoids collisions so if you have two inputs that produce the same hash then that's going to be a problem so if we hash it twice then we are going to be avoiding that problem and this is known as a second pre-image attack I will leave some resources in the GitHub repo associated with this section if you'd like to learn more about second pre-image attacks now kak 256 is actually resistant to clashes for the most part so it shouldn't be a problem but it's standard to do this twice so you can kind of just think of this is just like the general way that we encode and hash Leaf nodes and you'll see this again in a second so now that we have the hash we have the leaf we now need to verify the proof so to do that we are going to use open Zeppelin's Merkel contract so if we head into lib open Zeppelin contracts contracts utils cryptography and then Merkel proof this is the contract that we're going to want to be using and we're going to call this function verify which takes in as parameter that byes 32 array of proofs which we passed as a parameter to our claim function the root which we've stored in the contract already when we passed it through as the Constructor and the leaf which we just calculated and so then it will call Process proof as we were looking at in the other video and then it computes this computed hash which is going to be the expected route and it will compare that back up here we'll compare that to the route that we provided so if we head back into our airdrop contract we can now import Merkel proof and use it to verify our leaf so now to verify it we need to First verify that the leaf provides a route that matches the expected route and then if it doesn't we want to revert and then we want to say if the Merkel proof fails so not Merkel proof do verify then we want to be reverting now I am actually not going to use this revert message I am going to revert with a custom error so we're going to go ver revert Merkel airdrop because it's customary to do the name of your contract first and then we're going to say invalid proof which basically says if this fails then revert with this error message and we need to declare this at the top of our file so we need to First say down here before we declare our storage variables we want to have our error and I need to have the keyword error here and add a semicolon oky doie so cool this now succinctly verifies our Leaf if they have fact pass this then we want to continue with execution and we want to be able to Mint them the erc20 tokens now before we actually send the tokens to the claiming account we first want to Emmit the event so we're going to emit claim account amount we need to add this in as an event event claim address account u56 amount and then we want to be transferring the tokens and yes copilot you are correct we want to take the erc20 token we want to call transfer account amount now what happens if this account doesn't accept erc20 tokens what's going to happen well nothing really is going to happen and the execution is not going to revert so instead what we are going to do is we are going to use safe transfer which means that up here we need to import safe erc20 from open Zeppelin now actually we need to change this import because we're not going to be importing from the ic20 file we are instead going to be importing from safe erc20 which does also contain this interface and this is going to be utiles so if we now click into safe erc20 you can see here that it Imports the I erc20 which means we can we can import it from this contract like we are so you can import it from here and then also we have this Library safe erc20 and it says here that it's a wrapper around erc20 operations that throw on failure so we are going to be using this safe transfer which transfers the value amount of tokens from the calling contract to two if the token returns no value nonreverting calls assumed to be successful so it basically just means if we can't for some reason send tokens to the address then it'll handle that for us going to say using safe erc20 for I erc20 and this means that we can call the functions defined in here on any variables of this type so if we scroll back down here so now rather than transfer we can do a safe transfer great now let's see if that compiles let's run a little Forge build and that was successful now our smart contract takes as argument the Merkel route to compare to and the airdrop token the token that we wish to airdrop to our users or anyone in our Merkel tree we then have a claim function for people to call where they pass an account that they would like the tokens to be aird dropped to an amount and the Merkel proofs it calculates the leaf hash which it hashes twice to prevent collisions it ABI encodes together the account and the amount and then it uses this Leaf alongside the route and the proofs to calculate an expected route and Compares that to the actual route to see whether this Leaf was in fact in the Merkel tree if it wasn't it will revert and if it was it will safe transfer the tokens to the account with the value of amount now you may be thinking hm Kira there's a little bit of a problem with this smart contract can you think about what that problem might be so what happens if my account is in the Merkel tree I'm allowed to claim I call this function one and then what happens if I call it again now there's nothing to stop me continually claiming over and over again until I drain the contract of all the funds so what we need to do is we need to keep track of who has already claimed to stop them claiming more than once so the way we're going to do that is we're going to declare a mapping of add dress to Boolean to say whether the dress has claimed or not so we're going to say mapping of address user or claimer to Bull claimed oops and this is going to be private and this is a storage variable so we're going to say sore has claimed and now you may think that after we've transferred the tokens oh we can just update this mapping so we can say that sore has claimed account equals true now this would be wrong not not just because I've spelled it wrong now this is incorrect because it doesn't follow the checks effects interactions pattern which means that it could be vulnerable to a re-entrancy attack where the function is called continually and the state is not updated to prevent the account from claiming so what we want to do is we actually want to do that before we emit the event or transfer the tokens now this is great it says it's true cool but there's no check to see whether they have actually claimed or not so now we need to implement a check to say whether they have claimed or not so we can say if has claimed revert with not invalid proof this time already claimed so we're saying if they have already claimed this passes as true then revert with this error message so now we need to add this error message to the top of our smart contract like that thank you co-pilot great now we are preventing people from claiming multiple times so go ahead and build that again just to check that everything is going as smoothly as we would like and it compiles great now before we start testing our smart contract the other thing we want to do is we just want to add some quick getter functions because we have some private variables here that we want to actually be able to read so I'm going to add in a function function oops get Merkel root that's correct thanks ciler and then we're also going to want another one which is going to be the function get airdrop oops token so that we can see what the airdrop token address is fastic now let's go ahead and start testing so if we create a test file we're going to call this Merkel airdrop oops T dool and then we're going to do spdx license identify MIT pragma solidity 0.824 we need to import the Tex test contract from The Foundry standard Library so Forge stood SL test s and now let's actually add in the remapping in The Foundry tommel so we can go in here do a little comma and then we can go forg stood equals lib SL forg slsrc SL and now we can make a little contract so we can go contract Merkel airdrop test is test and we're going to write a very quick test to test that our functionality works as expected now in order to be able to do this we need to set up our Merkel tree and we need to be able to calculate the proofs and The Roots so we need to create two scripts the first script needs to create the input file and now this is going to look like this file input. Json so we're going to create a Json file which includes these types so this is the data types inside the Merkel tree so we've got address which is the address is going to be able to claim and uint which is like a u 256 so it's the amount that the person is going to be allowed to claim so we have a count of four which means that there are four leaf nodes and then the values inside those Leaf nodes so we will be hashing these values well first we'll be encoding together and then hashing these two values together and we've got four different nodes so these are the different addresses they're allowed to claim and then their Associated amounts now the second file that we are going to need to produce is going to be this output. Json and this output file is the Merkel tree so it contains all of the leaf nodes all of the proofs and the root hash you will have the input and then the proofs associated with that input the root hash and then the leaf hash so this is the hash of these two pieces of data and then this is the root hash and you'll see that for all of the different Leaf nodes all of the different inputs the root is the same because obviously they are part of the same Merkle tree therefore they're all going to be hashed down into the same route for that Merkel tree so let's go ahead and create those two scripts to produce these two files now to do that we are actually going to use murky from dmfx y z so what we're going to have to do is we're going to have to import this into our project and then we're actually going to be using a script in here and I'm going to have modified this so we'll walk through this in a second what this does but we're going to modify this very very slightly and I will have already done this you can get this from the GitHub repo associated with this course and you can just copy and paste it in and we'll walk through it in a second so the very first thing we need to do is we need to do a forge install and let's just check what the path was dmfx y z DMF XY Z SL murky D- no- commit because we're going to be using this repo in our script and our script is going to be producing our proofs and our root now the next thing that we need to do if we close out our lib is we need to create a script file so we're going to make a script called make Merkel s dool and also in script here I'm going to create a new folder called Target and this is going to be the target files this make Merkel script is going to hit so we're going to have a new file called input Json and then a new file called output Json so this input file is going to contain as it sounds the input for our Merkel tree so it's going to have a list of addresses with an Associated list of amounts that those addresses can claim and it's going to be in the Json format and then this file which is going to be created by the way using a script which again we are going to be copying from the GitHub repo associated with this course which is going to be called generate input this input file is then going to be used by make Merkel to create the output Json file the output Json file is going to contain all of the leaf nodes so the hashes of the information in the input file and for each of those Leaf nodes it will have the associated proofs so the intermediate nodes that are required to create the root and then also the expected root hash and now there's one final script that we are going to be copying which is going to be generate input. s.o which again we can copy from the GitHub repo and I will walk you through very quickly so let's first do the generate input if you head over to the GitHub repo then you can get this generate input file and you can copy and paste it in there so all this is doing is it's setting the amount that we want our addresses to be able to claim we've got this types array which is just the types of the values in the tree so for us it's going to be an address and an amount account which is the number of addresses that are going to be able to claim Whit list which is just an array of addresses that we're going to be setting as the addresses which we going to be able to claim we are going to be looping through it but because this is a script which is not going to be executed on chain then we don't need to worry about dos or gas or anything like that the input path which is going to print the Merkel tree too which is going to be input. Json script Target which we just made earlier and then inside the Run function we set the type of the first type to be addressed the second type to be uint and then we have four addresses which the addresses that I am saying that I would like to air drop my tokens to the count is the number of addresses so it's the array the length of the array and then I'm going to call this create Json to create the input file which basically just concatenates a load of strings together with the variables such as the addresses the amounts and creates the input file structure so we set that to the variable input and then we write file to the input path the input that we just created using this cheat code write file and it concatenates the strings together and then this is just the root of my project and then this is the specific file that we want to be writing to and then we log that we have done this so if we save that we can then run it so if we run for script generate input s. s colon generate input if we've done it correctly then it should work and it won't work because I haven't put said the the path correctly so this is going to be script SL generate input. s.o and you will now see this little error okay the path script Target input. Json is not allowed to be accessed for write operations huh that's annoying how come we can't write to files now this is easily rectified if you just head into The Foundry tml then you can just set in here the fs permissions so FS permissions per missions equals and then we do an array and then we say in here and we want to say be able to say we can read and write and then we the path of all of the files that we want to be able to read and write to is just the root of our directory and now we're saying that we can read the scripts are able to read and write to anything in our directory so now if we go ahead and run the script again we have an issue what's the issue we forgot our equals sign need little equals in there now if we run our script again done the output is found at so if we head to input and then we go control shift p format document then you can see that we've got the types in the Merkel tree the count which is four the values which is the addresses with all of the different amounts we now have the structure for our Merkel tree now if we head back to make Merkel s. and we copy the make Merkel script from the GitHub repo associated with this which has been modified from that murky GitHub repo and actually we are using murky in this file so we've got this Merkel from murky and you'll see that we've got some squiggly lines under murky which basically means we need to add it to our remappings as per usual so comma and then we've got murky equals lib SL mky and now if we head back to our make Merkel these should go away so we've added the remapping into our Foundry tummel I'm not sure why it's still squiggly but if we run Forge build then there's no issue so far so we're going to ignore it for now because sometimes VSS code just screws up and shows a squiggle even though it can actually find the file so we're going to explain this first and then we'll run the script and see if it works I have added in some comments which are just my thoughts of why we need to do things so first of all it ises this using J stood Json for string which enables us to use the Json cheat codes for Strings which we'll do shortly we then create a new instance of the Merkel contract from murky so if we head into murky Merkel then we can see that what it's doing is it's creating these hash Leaf pairs so it creates and as it says here it creates the proofs and verifies so the first thing we need to do is we need to then Define the input path which is where we just made our Merkel tree and then the output path which is where we're going to print the proofs and also the root and then this elements basically just reads that input file when then getting the types from the Json using the cheat code read string array which is why we needed this stood adjacent and then we are reading uint to get the number of leaf nodes so this is count we then declare some arrays we've got bytes 32 leaves we've got a string array inputs and a string array outputs and then this string output which basically just enables us to save all of the intermediate variables to retrieve the output file now we've got some helper functions here get values by index which just enables us to format the data so that we can print it to the output file and then create Json entries again just formats some of the data into Json format the majority of the logic is inside this function run so what we are going to do is we're going to Loop through all of the leaves we're then going to declare some arrays again so the stringified data and then the actual data so this would be like an address and an amount in a string but then this would be the actual address and the amount in bytes 32 and then what we're going to do once we've looped through each of the entries is we're going to Loop through for each entry the address and the array so this types. length is like the number of variables in so if we had like an address and two uints then it would be three and J would go from not to two because it's j less than types. length so when we see an address we're going to do this read address to the to get the value so we get the value of the address and then because you can't cast straight to bytes 32 for an address you first need to cast to a u 160 and then a u 256 and finally a b 32 this is just a standard thing for if you're casting an address to a by 32 and then we save that in the jth element of data and then we will store the input as the stringified value because this is the actual data in by 32 whereas this is the stringified data and then for all of the others so the uints then we want to pass uint to get the value and then we can bytes 32 that value because it was a u 56 of course because we said it was a uint so then we saved that byes 32 value which is the amount in data J so this is going to be one for the uint because it's the second value or zero for the address because it's the first value and then we stringify that amount and have it in input and then down here as my notes were saying we create the hash for the Merkel tree leaf note so this is like address and amount this data in here we ABI encode the data the helper from murky lrim 64 Returns the bytes with the first 64 bytes removed and this is because the offset of the encoded bytes and there's an offset because the array is declared in memory this is an array so we need to trim that off then we hash the encoded address and amount together this then turns the bytes 32 to bytes and then we hash it again we need to kak 256 hash the value twice to prevent Collision then we convert the string array to string using this script helper from murky which basically means that we can have all of the corresponding value inputs for each Leaf node and then finally once we've done that for each leaf and we have stored the leaf data and also the input then we can Loop through those so each address and amount and we can get the proof so we can use the m contract to get the proof for each Leaf so this takes the whole array of leaves all of the values and then this is the specific one that we want so for instance the first value so this would be zero and then we also calculate the root hash so we on the murky contract the Merk murky contract we call get root which calculates the root hash for all of the leaves and then we get the specific Leaf data and we get the stringified input so the address and the amount again and then then we generate the Json output file so this is akin to if you've used open Zeppelin The tree. Dump so it generates an output for each of the elements all of the leaves so each address and amount and then we get all of those string arrays and we make it into array string so we stringify the array of strings into a single string and then set it to output and then we write that to the output path finally now that is a little bit complicated ated and some of that you don't you don't really need to understand 100% how this is working essentially it's just taking in all of the inputs and then using this Merkel contract to get the proofs for each of the leaves get the root and then store the actual Leaf hash and then also the input and then printing them to the output file so if we run this by running Forge script script slash make Merkle s.o colon make Merle make Merkel then it says here generating Merkel proof for this input done the output is found at output. Json so if we head in here we go control shift p format document then you can see here as we said before you print the inputs so we've got the address and the amount the actual values this is what we were saying to this input is that address and amount you've got the proof for that specific leaf for those inputs and that's this proof we've got the root which we calculated here which is going to going to be the same you can get it it's going to be the same all the way through the file and then the leaf hash which is going to be this Leaf which is just the specific leaf that you're working on the inputs hash together twice as we said earlier and that's it so if you want to modify which addresses are going to be allowed to claim you modify the addresses in this generate input you'll run generate input and then you can run make Merkel to produce this output file to get the proofs for each of the addresses and to get the rout and now finally we can use this in our test to test that things actually work and to check that these addresses can in fact claim now let's continue with writing our test so if we just get rid of our terminal for a second so that we can see what we're doing so we're going to want a function to test that users can claim so function test users can claim can me with a eligible address claim the airdrop so the first thing we're going to want to do is we're going to want to deploy both our token contract and the airdrop contract so we're going to need to store those in variables and we're going to need to import the files so we can import Merkel airdrop from Source Merkel airdrop and we also want to import The Bagel token cuz you know everyone wants more Bagels so I'm going to air drop some people some bagels already tidy now we need to save them in some variables air drop and token and I'm going to make these variables public that's not Public public and public and then we're going to have a setup function function setup which will run automatically when we run our script and this is not going to be the correct route so we've got this token new Bagel token to deploy our Bagel token contract and then airdrop equals new airdrop token to deploy our airdrop contract and we need to have this root so let's save that in a variable which we are going to call we're going to say about 32 public root equals and then if we go into our output file then you can copy this root here so if we go back in here then we can say that the root is that paste it in and then also I very cleverly if I do say so myself made the first address this one the address that was generated from doing make adder and key of the string user what do I mean by this basically I created a an address user so we got address user and then we're going to say o and then we've also got un 256 user key and then in our setup function we're going to say oh you can also pass through the root here now that we have it we're going to use a little function that we get from Foundry we're going to say user and user Riv key equals make adder and key of user now what this will do is it will create an address and a private key but the way that it does that is it actually uses this to create the address it's predictable so because this user address is the address that's going to want to be claiming we're going to need to add the user address to the generate input file and then recreate our input and output Json files so we can get the proofs and the expected route and we're going to want them to be able to claim so they need to be in the Merkel tree so to do that all I am going to do is make sure that I've imported the console from the forge standard library and then I'm going to do a console.log the user address then if I open up my terminal and I just run Forge test and I make sure I add- VV then you'll see that I've got this user address which I can now copy and then if I head into generate input I can put that in my array of addresses which are able to claim now because I have sneakily already done this the address is going to be the same but I'm going to run through the motions just in case you have an a different address that needs to be able to claim and you want to know how you're going to add that to the Merkel tree so I've added it to the array in the generate input file and then I need to run these two scripts so I need to run the generate input script and then I need to run make Merkel to create first the input and then the output file to add it to the Merkel tree and generate the proofs and the root so I need to run Forge script script SL generate input. s.o to generate the input file and then I need to run Forge script script slake merkl dos dool to generate the output file now if we head in here we can do a command shift p format document and you can see this address is in the in file and then if we head to the output file we do the same command shift p format document you can see we now have again the address with the amount that they're able to claim we've got the leaf so the hashed these two values hashed together the proofs that we need the root and everything that we need to add into our test file so now the address that we're using to that we want to be able to claim is this user and it is in fact in the Merkel tree great now the reason I've used make add and key will be obvious very shortly right now when not actually going to be using the private key but I think it's important to show that you can create an address and a private key because the other one that we're going to use is just going to be make Adder but we're going to do that later and that just makes an address rather rather than creating the private key as well so now in our test users can claim the first thing we're going to do is we're going to store their initial balance just to double check that it is in fact zero and we're going to get the balance of the user and then we're going to use the cheat code vm. prank to you prank that the user is calling the function say airdrop do claim user amount to claim and then here not root we need proof so now we need to Define these two values and this is going to be capitals and this we're actually going to name amount and they're going to be magic numbers so we're going to say un 256 amount equals 25 Bagel tokens and because the number of decimals is 18 that's why I've got this here and then I'm going to say bytes 30 to array public proof equals and then I'm going to have an array here and what I'm going to do is I'm going to go into this output and then for this input I need to copy these two proofs and put them into my test file right here and then I'm going to coper separate them go back in get the second one copy that in paste that in there save and now I have my proof and now what we can do is we can get the ending balance now remember that vm. prank just pranks the next line so now all have already stopped there's no need to do stop prank we can get the ending balance and then we can console log it just because that's nice to do and we need to make sure that we get the console from for standard Library uh just double check that that's an export yes it is cool we can console log the ending balance like this and then we're going to say it here so that we know what we're looking at do a little comma there and then finally we're going to assert equal so assert that these two values that I'm going to type type in our equal so it's going to be ending balance minus oops minus starting balance is equal to amount so I want to check that this amount was in fact transferred to my user great now we haven't used just a script to deploy the token and the airdrop contract but we can do that and we can modify it soon now when we run this contract so if we go Forge test- VB we have an issue here this is because we first need to store these values as intermediate bytes 32 and then pass them through so we'll do that right now so we go byes 32 proof one and then we got same thing equals that and then we can pass through oops proof one and proof two let's run this again and it failed so interesting how come it failed it says erc20 insufficient balance so the reason this is failing is because our Merkel airdrop contract needs hold tokens to be able to send them to the user because if we head inside our Merkel airdrop contract we're doing a safe transfer from this contract to this account so once we have deployed these two contracts the first thing we need to do is we need to do token. mint to create the supply the token dot to the owner of the token and then we're going to send them amount Time 4 which we're actually going to save in a variable so now we're going to do you 256 cuz we don't like to have magic numbers inside function calls so we're going to say this in amount to send equals and then four * amount let's change this amount to claim to make it nice and verose and then whenever we've used amount we can do hold options and then click to do select both of them amount underscore 2core claim save and then here I can do amount oops amount to send and then once I've minted to the Token contract owner which is going to be this contract then I can do token dot transfer to the airdrop the amount to send so now the airdrop holds all of the tokens needed for all of the addresses to claim so now if I save this and I run the test again I haven't declared amount because I renamed the variable so amount to claim and then we run it again ah and then because airdrop is of type Merkel airdrop we need to cast this to an address to make sure that is the right type for this function call amazing our test has passed and we have successfully airdropped the user Bagel tokens yay now that we have written our test let's make a deployment script so that we can deploy our Bagel contract also our airdrop contract and then we can use them in our test so let's create a new file in script if it's going to work for me new file we're going to go deploy Merkel airdrop s.o now you could make this so it just deploys as the medical airdrop and then you pass through hard code and address for what you want your token contract to be if it already exists but for this example I am going to deploy my bagel token contract and then I'm going to pass it through to the air drop contract and that's just how I'm going to do it for this but it would be pretty easy to modify it so as per usual we go spdx license identifier MIT pragma sity 8.24 and then we need to import the contracts that we want to be deploying import mer airdrop from mer airdrop we also need to import import The Bagel token and then we need to make sure we are also importing script from the forge standard Library I'm not sure why this is complaining at me but we'll see if it runs and if it does we can just ignore it and then also we're going to need the I C20 because we're going to have to make some transfers like we did in the test so we can go I ERC 20 from open Zeppelin contracts cool now we have all the Imports we need we can go contract deploy merker airdrop o airdrop is script as we do normally when we create a deployment script going to create a function run which needs to be external and it return turns both of the contract contracts that we deploy so mer airdrop and also the bagel token and then in here this is not return this is returns and then in here we are going to return deploy mer airdrop which we are going to implement now so if we make a function deploy Merle airdrop it's going to be public returns both of those contracts the Merle air drop contract cont and the bagel token contract and then in here we need to deploy those contracts so as before as normal we do vm. start broadcast we're going to deploy The Bagel token then we're going to deploy the airdrop contract now here we are going to need the Merkel root so we're going to save this in a storage variable Merkel root and we're going to declare that up here right set two Merkel root equals that and this you can retrieve from your output file as before and we pass through the bagel token then we need to Mint the deployer amount to airdrop so we need to do token do mint token. owner which is going to be whoever called this contract and then we send them amount to airdrop which we need to Define u 256 amount to airdrop is 25 Bagel tokens and we need to actually send them we need to send the contract four times this because there are four people who are going to be claiming so this actually shouldn't be amount to airdrop it should be amount to transfer let's change that to transfer cool cool and then once we've minted it to the contract owner we need to transfer it to the airdrop contract so that it is in the contract to be able to be claimed by the claimers and then we can stop the broadcast vm. stop broadcast and then we can return the contracts and that's it that's how we write our deployment contract so now if we go back into our test we can use this in here now but what we're going to do need to do in order to be able to do that is we need to install Foundry devops so we need to go Forge install and let's just check the path of it so it's cyphon Foundry DDE Ops so Forge install cyphon slf Foundry dasde Ops no- commit and this enables us to get the most recently deployed contract and also means that we can do some ZK sync special stuff okay now in our setup we now need to check whether the chain is a ZK sync chain if it is a ZK sync chain we still want to be doing all of this if it's not that we want to be using our deployment script because as of recording right now you can't use scripts to deploy in ZK sync environments so ZK sync local nodes ZK sync sepolia or ZK sync mayet now the other thing I want to briefly mention here is that it is completely optional to work on ZK sync if you didn't want to work on ZK sync you would simply not implement the if else statement and everything in the if you would just put in your setup function this will make sense in a second you won't have to have the if ZK sync logic you can just purely use your deployment script in your test so within Foundry devops we have this nice little helper ZK sync chain Checker from the this path and this basically just checks whether the chain that you're working on is ZK sync or not and then we can just inherit that from our test so we can go ZK sync chain Checker and test and then in our setup we can say if not is ZK sync chain oops so if you're not working on ZK sync then deploy with the script else we want to be we're on a ZK sync in chain and we want to deploying as we were before so to deploy with the script we need to import this script to this contract so we need to say import deploy Merkel a dropped from script mer a drop. s. and then we can say deploy Merkle airdrop deployer equals new deployer Merkel airdrop and then we can say drop token equals deployer do deploy merel air drop to call the function and that's it so now if we run our test again we are not working on a ZK chain we're currently just testing in a normal environment in the test environment and our test passes amazing we have now tested our deployment script this contract you may have noticed allows other people to call claim for another account I could call claim with Patrick Collin's address and he would receive these tokens whether he wanted to or not so maybe we want a way for these accounts to be able to say yes I want this airdrop or no I don't want this airdrop now what we could do is we could remove this account and just use message sender throughout which would mean they would have to call with their own account and they would have to pay for their own gas fees and everything and that would work and would mean that no one else can claim for them they can't receive anything that they don't want but maybe we still want other people to be able to pay for our gas maybe we still want other people to be able to call claim for us and we want to be able to receive the airdrop so we need a way to be able to say for me to be able to say hey Patrick here you go here's permission to call claim for me you can pay for my transaction fees thank you very much and I will receive the airdrop because my account is in the Merkel tree I'm allowed to be able to claim but I don't want to claim myself so I don't want message sender to be in here but I still want to be able to receive the airdrop and I want you to pay for me so the way that we are going to do that is by using signatures we are going to have a message which essentially says yes you can claim for me and I'm going to sign it with my account and my private keyy to say here you go Patrick here's this message that I've signed using my very own signature to say that you can claim for me and then he can call claim and then claim will check is this signature originating from the account that you are wishing to claim for if yes are they in the Merkel tree if yes then they can claim the airdrop so to understand how to implement this we need to backtrack a second and we need to understand what are signatures and how do we Implement signature verification into our smart contract how do we check that the signature was signed by the intended signer by this account so let's explain that very quickly now in this video we are going to go through everything that you need to know about signing and verifying signatures by learning about and understanding ethereum signature standards we will be going through EIP 191 EIP 712 and how you can verify your signatures in your smart contract let's jump into it in order to understand signature creation signature verification and preventing replay attacks EIP 1 191 and 712 must be understood first let's quickly go through why these ethereum Improvement proposals were introduced when signing transactions we needed an easier way to read and understand transaction Data before before these standards were created the following message was displayed in metamask when signing a transaction pretty ugly right difficult to understand whether what I'm signing is correct not what you want to see these standards meant that the transaction data could be displayed in a nice readable way additionally EIP 712 is key to preventing replay attacks spoiler the data to prevent replay attacks is encoded inside the structured data so let's go through these standards now step by step let's first start with simple signature verification and implement it into a smart contract so if we create a function get simple signer which takes a message to sign and this can be any data at all preferably the string c is awesome but it's up to you notice here the VR and S arguments these are components of the signature that we're providing this function get simple signer hashes the message and then retrieves the signer using the pre-compile EC recover and then Returns the result as I said EC recover is a pre-compile so it's a function that's built into the ethereum protocol and retrieves the signer from any message using the v r and s components of the signature we then create a function verify signer simple which then compares the retrieved signer to the expected signer and then it reverts if they're not the same this is how signatures work at a fundamental level take some hash message plus the signature of the message retrieve the signer and check that the address was as expected there was an issue with this though there needed to be a way to send transactions using pre-made signatures AKA sponsored transactions there will be a future video on account abstractions so remember this as this will be important this was already possible outside of smart contracts however there needed to be a way to build this into functions in smart contracts for example Bob signs a message AKA a transaction and gives that signature to Alice Alice then uses that signature to send the transaction meaning that Alice pays for Bob's gas fees and so EIP 191 was introduced EIP 191 is the signed data standard and it proposed the following format for signed data first off ox19 this is the prefix and this just signifies that the data is a signature the decimal value of ox19 is 25 and this was chosen because it wasn't used in any other context and due to how ethereum transactions are encoded it ensures that the data associated with the sign message cannot be a valid ethereum transaction next we have the one bite version this is the version that the sign data is using and this allows different versions to have different sign data structures the allowed values are 0x00 which is data with an intended validator the person or smart contract who is going to validate the signature is provided here 0x01 which is structured data this is the one that's most commonly used in production apps and is associated with EIP 712 which we'll discuss shortly and finally 0 x45 personal sign messages you then have the version specific data this is data associated with that version and it will be specified for instance for 0x01 you have to provide the validator address the next section is the data to sign and this is purely the message we intend to sign such as a string K is awesome let's now modify our code for EIP 91 the following get sign a 1 191 function demonstrates how to set up an EIP 191 signature so you can see here we have the bytes one prefix which is that ox19 you then have the bytes one EIP 191 version and we're using version zero then we have the version specific data so the validator address which we're saying is this smart contract and then we have the application specific data so Su message and we can see it follows that format that we said just a second ago we then AB encode this data we hash it together to produce a hashed message we then use the EC recover pre-compile with the hashed message and the signature to recover the signer as you can see here retrieving the signer is much more aose now as before we can then compare this calculated signer with the expected signer however what if this data to sign the message is a lot more complicated we still don't really have a nice way to display this information for instance in metamask so we needed a way to format this data that could be more easily understood so we needed to standardize this which was done in EIP 712 EIP 712 structured this data to sign and also the version specific data this made signatures more easy to read and that we could display them inside wallets and also that we could prevent replay attacks so now the signature has the following structure we again have the prefix from before and the version we now have this domain separator and this is the version specific data Note that we're working with here with 0x01 and this is the version that associated with EIP 712 the domain separator is the hash of the struct defining the domain of the message being signed and in the case of EIP 712 the EIP 712 domain looks like this so you have a struct that has the name the version the chain ID and the verifying contract this means that smart contracts can know whether the signature was created specifically for that smart contract because the smart contract itself will be the verifying contract and it will be encoded in the data so we can rewrite the data as ox19 0x01 the hash struct of the EIP 712 domain and then the hash struct of the message now we need to Define what hash struct is the hash struct is the hash of the type hash plus the hash of the struct itself so the data the type hash is a hash of what the actual struct looks like so what are the types involved here what is the name of struct and what are all the types inside that struct and then we hash that together to create the type hash we then create a domain separator struct by providing all of the data necessary and then we hash together the type hash with all those individual pieces of data by first ABI encoding them together to create some bytes and then hashing that data but the hash struct is basically what does the data look like and what actually is the data hash together now we have the hash struct of the message and this follows very similarly so what is the type of the message and then what is the message itself so we have a struct message which has the member number so then the message type hash will then just be the hash of the type message un 256 the hash struct of the message then becomes the ABI encoded type hash alongside the actual message struct data encoded together and then hashed and this is the hash struct of the message so we can think of this EIP 712 data as just ox9 ox1 who verifies the signature and what the verifier looks like a hash of the sign structured message and what the signature looks like putting this together we then create a get signer EIP 712 function which first takes the prefix the EIP 712 version which is ox1 the hash struct of the domain separator which we created by hashing together the type hash and the domain separ struct data we then encode together the prefix the version hash struct of the domain separator and the hash struct of the message and this combined together is known as the digest the definition of a digest is just any data resulting after a hash and you often see it referred to when talking about signatures after you have hashed the message and combined it with all of the other data associated with EIP 712 so don't be confused if you see digest in another context we then call EC recover with this digest and the signature to retrieve the actual signer we can then compare that to the expected signer as before in this verify s of 712 function this may sound extremely confusing but using open Zeppelin a lot of this can be done for us all we need to do is create the message type hash and hash that together with the message data to create the hash struct of the message we can then pass this as an argument to the function undor # type data V4 and then this will add the EIP 712 domain and the domain type hash and hash it all together to create the digest so we pass our message through to get message hash to do all of that for us do all of the hashing for us and get the fully encoded EIP 712 message and then we pass that through to our get signer open Zeppelin and this does the same as what we were doing before so when we were using EC recover directly but instead it uses ecdsa do TR recover from open Zeppelin try recover then checks the S value of the signature to check for Signature malleability and then uses the EC recover precompiled to retrieve the signer it then also checks if the signer returned is the zero address because if the signer is not valid then EC recover will return the zero address and we'll retrieve the expected signer which we can then compare to the actual signer that we had to verify the signature so as mentioned earlier EIP 712 is key to preventing replay attacks replay attacks are where the same transaction can be sent more than once or the same signature used more than once the extra data in the structure of EIP 712 prevents these replay attacks so that is a lot of information and it may sound super confusing but I encourage you to try and use this in practice because this is where the knowledge is really going to be solidified and so to summarize EIP 91 standardizes what the sign data should look like EIP 712 standardizes the format of the version specific data and the data to sign so to implement signatures and signature verification into your smart contracts it's imperative to understand these two eips so now we're well on our way to writing secure smart contracts this is super confusing stuff and it took me a long time to get my head around so don't worry if you're a little confused this is confusing stuff now before we go ahead and implement this into our smart contract let's take a little segue into ecdsa signatures what are those VR RNs components that we passed through we said that they were components of the signature but what actually are they let's go into that now have you ever heard of ecdsa and ecdsa signatures before and what are these v r and s values where do they come from everyone just says ecdsa is just some math magic and don't worry about it and that V RNs are basically just the signature but like what are they really I'm going to take you through that right now but don't worry you don't need to have some crazy in-depth math knowledge you don't need to have a Math's degree to understand this I'm going to be taking you through things from a high level so we can understand ecdsa signatures how they work and what the heck vrns are let's get into it ecdsa stands for the elliptic curve digital signature algorithm bit of a mouthful and it's based on elliptic curve cryptography don't worry we'll go through what that means in a second but it's used to generate Keys authenticate sign and verify messages but first of all what actually are signatures let's do a brief explainer signatures provide a means for authentication in blockchain technology allowing operations such as sending transactions to verify that they have originated from the intended sender proof of ownership in ethereum is achieved using public and private key Pairs and they are used to create digital signatures signatures are analogous to having to provide ID to withdraw from the bank they're kind of like a digital fingerprint and they are unique to you the user this public private key pair is used to verify that the sender is the owner of the account this is of course known as public key cryptography and involves asymmetric encryption which sounds confusing but more on this later the private key is what is used to sign the message and is used to derive the public key the public key is used to verify the owner knows the private key it is extremely difficult and we can assume impossible to derive the private key from the public key even for a computer ignoring Quantum Computing but don't worry about that right now and this means that knowledge of the public key does not Grant access to the account this is why if you share your private key that is a big problem because you can access the account but if you share a public key then you're fine if I give Patrick Collins my address he can't steal anything these public and private key pairs Define ethereum externally owned accounts or EAS and they provide a means for interacting with the blockchain by signing data and sending transactions without others being able to access accounts they do not own an ethereum address is used as identification and is the last 20 bytes of the hash of the public key but how do we create public and private Keys how do we create signatures and how do we verify signatures let's now dive into ecdsa how it works and what it is ecdsa is a signature algorithm based on elliptic curve cryptography and it is the cryptograph graphic algorithm used to do those operations we were talking about create Keys create signatures and verify signatures and we need to understand how they work from a high level in order to be able to implement these things into our smart contracts and ensure that they are secure the specific curve used in ecdsa in ethereum is the setp 256 K1 curve and it was chosen for its interoperability with Bitcoin its efficiency and security and as with all elliptic curves it is symmetrical about its x-axis therefore every coordinate on the curve there exists another coordinate at the same X point and each point on the curve is your v r and s they are the coordinates of the points on the curve each point is a unique signature now for every X coordin on the curve there exists two valid signatures which means that if a malicious actor has access to one of those signatures even without the private key they can compute the second one this is known as signature malleability which is a form of Replay attack resources will be left down below if you're watching this on YouTube or in the GitHub repo if you're on updraft if you would like to learn more about replay attacks now there's a couple of constants that we need to quickly Define associated with the secp 256 K1 curve the first is the generator Point G and it's just we can assume random point on the elliptic curve it's purely a constant the second one is n which is the order of the subgroup of the elliptic curve points and it's generated by G and all you really need to know about n is that it defines the length of the private key and it's a prime number now it's not crucial to understand what these constants mean we purely just need to remember that they are constants they are just constants that are going to be used in subsequent calculations ecdsa signatures contain three integers and they might be familiar to you v r and s therefore signatures can be denoted as VR and S R represents the X point on the elliptic curve based on some random Point capital r on the curve but it's just the x coordinate s serves as proof of the signer's knowledge of the private key and is calculated using a random constant K which ensures that the signature is unique every time V is used to recover the public key from R and represents the index of the point on the elliptic curve whether the point is in positive y or negative y this is known as the polarity let's now go through how public and private keys are generated the private key is generated as a random integer within the range 0 to n minus one where n is again the order the public key is an elliptic curve Point calculated by timesing the private key with the generator point but how do we know the ecdsa private keys are secure this is because of the complexity of the litic curve discrete logarithm problem which basically says that if we times two big integers together the output being a giant integer using just the output we cannot feasibly calcul calate the inputs since Point arithmetic in a finite field does not support division a computer would instead have to use root Force to determine P even though G is known and this involves trying every possible value of P to find the correct value which is not feasibly possible imagine I have two large prime numbers and I times them together and I give you this output do you think you could calculate the inputs unless you're a quantum computer I don't think so so we can assume this is possible even for computers now how are signatures created signatures are created by combining a hash of a message with the private key this combination is done using the ecdsa algorithm firstly using the sh 256 hashing algorithm we hash the message then secondly we generate a securely random number K the nons we then calculate a random number capital r which is the nons times the generator point and take its x coordinate this is R lowercase R VSR this is the r part of our signature using the following formula we then calculate s using the nons the hash of the message the private key the r part of the signature and the order n v then defines whether we are using the positive part of the y axis or the negative part of the y- axis finally how are ecdsa signatures verified the ecdsa verification algorithm takes the sign message the signature from the signing algorithm and the public key and outputs a Boolean representing whether the signature was valid or not whether the recovered signer matches the provided public key this works in Reverse of the signing algorithm we convert the S coordinate back to an R coordinate and verify that the provided R coordinate matches the calculated R coordinate this is done using the following formula which is essentially just a reverse of what we did when we were signing the evm precompile EC recover does this for you in smart contracts it enables us to retrieve the signer address of a message that has been signed using their private key using ecdsa and this is what allows smart contracts to verify the Integrity of his signature and retrieve the signer using EC recovered directly can lead to some security issues so the first as we discussed is signature malleability where because the curve is symmetric about the x-axis there are two valid signatures for each value of R so if an attacker knows one signature they can calculate the other one this can be mitigated by restricting the value of s to 1 half of the curve if s is not restricted the two valid signatures exist and therefore the smart contract can be vulnerable to Signature malleability attacks however if you're using open Zeppelins libraries such as the ecdsa library to verify signatures then you are protected against signature malleability attacks as long as you're using versions greater than 4.7.3 for example as you can see in the code from this lava Labs code for arena audit you can see the EC recover is being used directly without any checks on S so there is no restriction and both signatures would be valid you shouldn't Implement EC recover directly therefore open Zeppelin's ecdsa Library should be used to validate signatures aside from signature malleability the other issue with using EC recover directly is that if the signature is invalid EC recover will return the zero address now if this is not handled correctly in the implementation in the smart contract then this can lead to issues so there should be a check in the smart contract if EC recover is returning the zero address and then the smart contract should revert if you're using open Zeppelin's ecdsa library then this check already exists and you're protected against this vulnerability now this was a lot of information and this may be overwhelming so well done give yourself a pass on the back for getting through this if this was confusing to you or you need to rewatch this video go read some other articles immerse yourself in some Math's magic then go ahead because this is extremely complex stuff and you're probably not going to get your head it the first time but well done cuz now you understand ecdsa signatures we know that ecdsa is used to generate public and private Keys generate signatures and verify those signatures and we have walked through step by step how this is done so thank you for watching now that we've learned all about signatures EIP 712 EIP 91 ecdsa and Merkel trees and we have implemented that into our smart contract there there is one last concept that we have not talked through yet and we now have all the tools to be able to understand do you remember when we deployed our contract to ZK sync and the transaction type was 113 Patrick gave a brief explainer of what this means but let's go into this and what the transaction type means and what's actually going on here if you don't remember not to worry we're going to go through it right now okay here we are over in remix and I have a smart contract that I wish to deploy this is in fact the simple storage smart cont cont ract back from solidity 101 now this could be any smart contract that you want to deploy but if you remember before we are going to use the ZK sync remix plugin to deploy our smart contract and then we need to make sure that our environment is set to wallet and that we connect our wallet to the site so that we can deploy using our metamask so the first thing that we need to do is we need to hit compile to compile our smart contract using the ZK compiler click accept and then when we hit deploy something very interesting is going to happen here we have a signature request we are in fact not sending a transaction which we would normally do when we deploy a smart contract instead we are signing a message sign this message so here we have the information to do with the message and it's broken down all nicely for us what does this kind of tell you the fact that we have all of this lovely amazingly laid out information for us it kind of tells us that it's EIP 712 message and here you can see that the transaction type is 113 hey that's pretty cool huh how come we were in remix and we expected to do a transaction but instead we're signing a message so if we hit sign then you can see here the information in the terminal that we just signed so how was that possible in order to understand this let's go through some transaction Types on ethereum and ZK sync so that we can understand this type 113 transaction here when sending transactions throughout this course you may have noticed something called transaction types for instance when we deployed a smart contract on ZK sync using remix we signed a message which contained the transaction type 113 in the message additionally we added the -- Legacy flag when we deployed our smart contracts with Foundry ZK sync you may also notice on ether scan or ZK sync block scanners that attribute transaction type on all of your transactions and in this example it says transaction type 2 let's go through and break down all of the different transaction types and what this means ethereum and ZK sync share four transaction types first transaction type zero Legacy transactions when we added that-- Legacy flag we were specifying transaction type zero this was the ethereum transaction type before ethereum transaction types were even introduced and it was the very very first transaction type secondly we have transaction type one 0x01 there was some contract breakage risks associated with EIP 2929 and EIP 2930 optional access lists solved this in introduced transaction type one and this contains the same Fields as Legacy transactions with an additional access list parameter which contains an array of addresses and storage keys and this enables gas savings on Cross contract calls by pred declaring the allowed contracts and storage slots the next transaction type was introduced by EIP 559 and this is transaction type 2 or 0x02 and it was introduced in ethereum's London fork and this transaction type aimed to tackle High Network fees and congestion and it was all around gas fees Legacy transactions had the gas price parameter and this was instead replaced with a base fee which was modified for each block it also added the following parameters Max priority fee per gas which is the maximum fee the sender is willing to pay the max fee per gas which is the maximum total total fee that the sender is willing to pay so like how much extra are they willing to pay to have priority plus that base fee is the max fee per gas it should be noted here that ZK sync does support type two transactions but it does nothing with the max fee parameters because Gas Works a little differently on ZK sync and finally we have type 3 or 0x03 transactions and this was introduced in EIP 4844 Proto Dan sharding or blob transactions and this was introduced in ethereum's denen fork and provided an initial scaling solution for rollups while their usage was still low or is still low depending on when you're watching this and it introduced a couple of new parameters alongside those introduced in type zero and type two transactions it introduced Max blob fee per gas which is the maximum fee per gas the sender is willing to pay for the blob gas so this was a separate Market from regular gas it's like the maximum extra fee for the blobs and and then also it had blob versioned hashes which was a list of The versioned Blob hashes associated with the transaction blobs The Blob fee is actually deducted and burned from the sender before the transaction executes which means in the case of transaction failure it's actually not refunded and in a second we will go into EIP 4844 Proto Dan sharding and blobs in more detail in Patrick's video so wait a second for that but we have two more transaction types to go through and these are ZK sync specific transaction types so first we have EIP 712 transactions on ZK sync and these are those type 113 transactions or 0x 71 transactions and it defines typed structured data hashing and signing as we know EIP 712 introduced a way to standardize the version data and also the data to sign so that it could be decoded and understood in applications like metamask type 113 transactions enable us to access ZK sync specific features like account abstraction and pay masters and smart contracts must be deployed with these type 1113 transactions the fields for type 1113 transactions are the same as standard ethereum transactions plus a couple of additional Fields gas per Pub data which is a field denoting the maximum gas the sender is willing to pay for a single bite of Pub data Pub data is simply the L2 State data that is submitted to the L1 the data that they are sending custom signature which is a field for the custom signature for when the signer's account is not an EOS pay Master params these are parameters for configuring a custom pay master so a smart contract that is going to pay for the transaction for us and also Factory depths so this should contain the bite code of the smart contract that is being deployed now finally we have type five transactions or 0x FF and these are priority transactions and they enable us to send transactions from the L1 to the L2 directly in ZK sync and so now we know all of the different transaction types before we head back back to remix here's Patrick who's going to explain to us all about blobs Protank sharding and EIP 4844 type three transactions in a normal transaction all your transaction data is stored on chain forever that shitcoin that you bought you thought would Moon and went to zero yeah everyone can see you did that forever blob transactions a new transaction type AKA type 03 however give you a box to cram and data that will eventually be deleted once the transaction is included in a block it stores everything per usual but after a short delay maybe 20 to 90 days we delete whatever you put in this box this is known as The Blob which is sort of an acrm for binary large objects a lot of people have been using the sidecar analogy with a blob being the side car of a motorcycle the motorcycle being the transaction and we eventually light the side car on fire and throw it away blob transactions were included in the ethereum denune upgrade on March 13th of 2024 and rollups have been absolutely loving it these blob transactions came from EIP 4844 AKA Proto dank sharding which is a really cool name but it was actually just named after the researchers who came up with this so why do we give transactions this optional box for them to dump this temporary data well it goes back to ethereum's biggest issue today that's sending $1 cost me$ twoing dollar ethereum right now is crazy expensive this is due to the blockchain trma problem and some other stuff Link in the description rollups are the solution that we've come to know to help scale ethereum so that our transactions aren't this expensive you can go to ZK sync arbitror optimism and you can send that $1 for substantially cheaper than you could on the ethereum main chain and we as a community have essentially settled on rollups being the way we're going to scale ethereum for the next few to several years the way they work is they essentially execute a bunch of transactions on their own chain bundle up and compress the transactions into a batch and submit that batch back to ethereum with many l2s processing transactions you can get a lot more transactions for a lot cheaper because you're compressing all these transactions on all these rollups or all these l2s now when these l2s submit these batches back to ethereum ethereum has to do a little work to verify that the batch of transactions is actually good and that right there is where the issue is when the L1 when ethereum verifies that a transaction is actually good it only needs the compressed batch of transactions once to verify that it's good and then it doesn't care about the data anymore but before this upgrade when you submitted this batch of compressed transactions you had to submit the whole chunk of transactions and permanently stored on every single ethereum node on the planet you see the issue there we needed this data for like a second and then every single node would have to hold on to it even though nobody ever cared about that data ever again it would be like if every single time you pass an exam in school you had to carry that exam around with you at all times what's more important than the state loow is actually the gas costs if you store a ton of data on ethereum or nl1 that means every single node has to store that data as well which requires them to go out and buy more Hardware or do more computation and so if you want to store more data on ethereum you have to pay more gas and since this compressed batch of transactions is still a ton of data that before this upgrade we were permanently storing on ethereum rups had to pay a ton of gas so uh the rollups were kind of pissed they didn't love this and neither did the ethereum community so these rollups essentially said hey so like where the future of ethereum scaling but this call data is super expensive what if we just like deleted it after we validated our transactions were good we'll post our compressed batch we'll check that it's good and then we'll dump it that way we don't have to pay the cost of storing that data forever and then we as the ethereum community went that sounds like a pretty good idea and so the blob transactions were born so how are blobs used in practice embrace yourself we're going to get a little technical here for a second this is an example of a transaction on the ethereum main chain where ZK sync actually sent its batch of compressed transactions to the ethereum L1 if you scroll down in here on ether scan you actually see this new section here called total blobs and if we click into this which if we scroll down in here and we click one of these blobs here we can see this massive chunk of data like literally absolutely massive that is not being stored on ethereum because it was instead sent as a blob and will eventually be deleted what's cool too is ether scan gives us this little blob gas used and blob as call data gas here where it shows you how much more expensive this data would have been if it was submitted as call data as opposed to blob data here obviously it's way way cheaper for rollups to submit this data as a blob than as call data which is what they previously would have had to have done getting more technical here what's interesting is that the L1 ethereum smart contracts have to validate that this batch of transactions is actually good they have to validate essentially that this blob is good good however if they get access to the blob and they do computation with The Blob they would have to have access to the blob which means they would need to store it on chain which we can't do so what the hell and this is where the Proto Dan Charters were actually smart enough to see this coming and actually created a new OP code and a new pre-compile to do some math magic to verify these blobs they created a new blob hash op code and a new Point evaluation pre-compile and with these two new tools that was all we really needed to do math cryptography magic which there's a lot of that in web 3 The Blob hash will instead essentially grab that whole blob and hash it using some math magic and we can use this hash actually combined with some proofs that we submit in a function to actually verify that these blobs are good for example if we actually open this up in tenderly and we scroll down we can see there's this function here called verify block blob information that gets called which does exactly what it says it's going to verify the blob information looking at this function we can see it takes some bytes call data called Pub data commitments this is essentially going to be some cryptographic proofs that we generate offchain and some other data and then the list of blob hashes which we access with that blob hash op code and in this function we eventually call this internal function called point pre-compile which is where we send all that data to that pre-compile to help make sure that this data is actually solid the exact function that's actually called with this ZK sync transaction in specific is this commit batches where it sends a ton of data including these cryptographic proofs that's going to combine with these blob hashes to make sure that the blob is actually solid and boom with this information here we can now verify this blob this batch of transactions is actually solid without having to store that massive chunk of data on chain and bankrupting these l2s which are definitely not making a ton of money right now and we're able to do a lot of this due to the beauties of cryptography and that's how blobs work so a quick recap of what blobs are blobs are a new transaction type that allows us to store data on chain for a short period of time we can't access the data itself but we can access a hash of the data with the new blob hash op code and blobs were added because rollups wanted a cheaper way to validate transactions now we showed you a quick example of ZK sync but in essence this is how a lot of these rollups actually work quick summary of how the rollups actually validate these transactions you submit your transaction with a blob along with some type of proof data the contract on chain accesses the hash again of The Blob with The Blob hash op code it will then pass your blob hashes combined with your proof data to that new Point evaluation op code to verify the transaction batch using some math magic and boom to demonstrate how to send your own transaction using a blob I've actually created a little GitHub repo Link in the description showing us how to send one of these transactions first thing you're going to want to do is set up a connection to the blockchain per normal and then just create some encoded text for example we're using this as our blob data now the thing is blobs have to be at least 4,096 words of 32 by words combined so we actually have to take this encoded text and combine it with a ton of basically zeros so that we can create this this blob you cannot have a small blob they are all big then what we do is we actually create our transaction object as you normally would one of the big differences is we're going to change the type of transaction to a Type 3 transaction normally you'll see normal type 2 transactions which is that EIP 1559 transaction and is the default transaction now additionally we want to add some blob gas feed parameters to our transactions as well one of the other really interesting implications of adding blobs is that we've essentially created a new type of gas market a gas market for blobs which has a whole bunch of interesting Downstream effects video for another time and then finally we set up a gas estimate we sign our transaction and all we do is we add our blob data to a little blob compartment of our transaction we sign it and then we send it if I wanted to run this on a local blockchain you go just set up Anvil set up my Anvil chain to run for this I'm using Ry which is like a python thing I would do Ry run send blob actually run this and we can see two responses here we can see a transaction receipt right here and then if we scroll up we can see the actual blob that we're sending and yes I'm I'm scrolling up this whole time it's this massive object that we send EAP 4844 AKA Proto Dan sharting is this intermediate step in the ethereum's longtail scaling road map and is a prerequisite to dank sharding which includes a lot more cool features cooler than the name dank sharding too but Roll-Ups are happening now and we said hey Roll-Ups are happening now we need them cheaper now so the ethereum community implemented dank sharding the ethereum docks actually do a phenomenal job of EXP exping dank sharding where it's going what it's going to look like in the future so now you understand blobs Proto Dan sharding if you want to try out sending your own blob transaction check the link in the description thanks for getting froggy with us and we'll see you next [Music] time let's go back to remix and have a look and see if we can understand what was going on there okay so now that we understand both about EIP 712 signatures and transaction types what actually is the mechanism or format that allowed remix to be able to send a transaction for us in Remix by signing a message now what happened here was it used something called account abstraction and ZK Sync has native account abstraction which means it's built into the blockchain account abstraction enables users assets to be stored in smart contracts rather than externally owned accounts this means that users can use Smart contracts as their accounts rather than something like metamask on ethereum there are two types of accounts externally owned accounts where you have a public and a private key and a user has to initiate and sign transactions and then also contract accounts where the smart contract itself is the account and any arbitary logic can be implemented so you can have things like multiple signers or the ability to have other people pay for your gas and send transactions for you accounts in zky sync era can initiate transactions just like an EOS but can also have arbitrary logic implemented in them and so they have account abstraction natively and since smart contract accounts are fully programmable this allows various customizations such as signature schemes having multi-sig capabilities you can set spending limits Etc and this is the mechanism that allowed remix to be able to send our transaction for us by us signing an EIP 712 message and since ZK Sync has account abstraction natively my ethereum address on ZK sync is automatically a smart contract account and so remix was able to send the transaction for us do not worry if you do not understand this because Patrick is going to be going through account abstraction in depth in the next section so now that we understand all about signatures how they work and how we can verify them let's Implement some signature verification into our smart contract right now so the first thing that we're going to want to do when implementing this into our smart contract is we're going to want to pass the signature through to claims so that we can check it I sign a message to say that yes you can claim for my account so that I can receive the airdrop so we are going to want to pass through the v r and s components of our signature so the types are uint 8 V bytes 32 R and A byes 32 s first thing we're going to do is obviously check whether they've claimed or not already because otherwise we don't want to check anything else and then if they have we want to check the signature so if the signature is not valid then we are going to want to revert with an invalid not proof Signature Custom error so let's copy this and then declare that at the top so now we have this custom error so if the signature is not valid then revert with this custom error so how do we check whether the signature is valid let's create a function is valid signature it's going to be an internal function so I'm going to start with the leading underscore is valid signature and then we're going to want to pass through the account some message which we'll Define in a second the VR and S components of the signature and then also we only want to revert if this is false so it's not a valid signature now what is this message so this message needs to be the digest which we were explaining in the video earlier we are going to create this message message digest using a function and we're going to name it get message and we're going to pass in here the account that we are wishing to claim for and the amount that they are wishing to claim so that is the specific information about their function call so let's Implement that function now those two functions so we've got function get message to create the message digest and this is going to take the address account and U in 256 amount and it is going to be public so that we can use it later to get messages so that we can sign them and it's going to be View and it's going to return the bytes 32 digest and then we are going to return underscore hash typed data V4 which we need to get from open Zeppelin and then we are going to kak and code hash together ABI and code to glue these pieces together the message type hash with the account and the amount and here we need to make sure that this is a struct just to be extra verose you don't need to do this but we are going to do so so that it's nice and clean so first of all we need to declare a struct so let's create a struct and we are going to name it airdrop claim if I can spell and in here we're going to have address account and amount and then additionally we also need to declare the message type hash which is going to be this hash of the type so we've got the type hash now amazing so now we can use that in here so instead of this we are actually going to say we're going to say air drop claim and then in here we're going to do named components and then now we have the struct so we have the message type hash and the message we are encoding these together and then we are hashing them and then we're passing that as an argument toore # typ data V4 which we need to get from open Zeppelin so this uncore # typ data V4 is from the EIP 712 contract from open Zeppelin so if we scroll down here then we can see this hash type data V4 so what this function does is it Returns the hash of the fully encoded EIP 712 message for this domain so it sticks on all the extra information to make it EIP 712 compatible so if we head in here into domain separator feed 4 and then we go build domain separator we can see that it's encoding together this type hash with the hash version the address which is because we're inheriting from this remember that the address this is going to be this contract so we need to inherit from it is EIP not 721 712 so that we're using it so that we are now inheriting all of these functions and we can use them in our smart contract so now we have the version and the version specific data tagged onto our message and it is fully EIP 712 compatible we now need to make sure we are calling the Constructor of EIP 712 and this takes a name and a version so I'm just going to call this something like Merkel airdrop and I'm going to say it's version one something like that and now we can use all of the functional so this function should behave as expected now there's something wrong here I think I might have too many brackets nope I'm just missing a semicolon right so now the next function that we need need to implement is going to be is valid signature and this function needs to take the account that we want to check that the signature was signed by the bytes 32 digest and the signature so uint 8 V byes 32 R and yes all of the rest is correct apart from this line this is going to be slightly different because we don't want to be using EC recover directly internal view returns this is actually going to be pure because it's not going to be modifying anything returns Boolean whether it is valid or not so now we are going to be using ecdsa try recover so we're going to have some parentheses going to go address actual signer that we have recovered and then we don't need the error and we don't need the signature length equals EC DSA recover from from open Zeppelin and we pass through the digest the V the r and the S and then we return actual signer equals equals this account so now we need to import EC the ecdsa library from open Zeppelin so that we can use this function and all this function is doing again it's recovering the sign up from the signature and then it calls this internal try recover and then what try recover does is it checks the signature malleability which we talked about earlier so checks it that the the S is in fact restricted and then it uses EC recover to get the signer and checks that the signer is not the zero address like we were saying earlier we want to make sure we not returning some erinus zero address that we will need to check for we need to then return the signer so we' returned the signer here which is the actual sign up of this signature and then we compare it against the account so if we scroll back up here and here we've got an message error because I've done 721 rather than 712 as for always so if we scroll back up here we now do check if the signature is not valid by getting the message digest passing it through with the account and we check whether this account is the same as the one recovered by the signature using the digest and then if it's not valid we revert pH that was a lot let's try and implement this back into our test now don't worry if this seems a little bit confusing I'm hoping that by going going over things in the previous lesson and then seeing this again implemented this might be starting to come together and make some sense but what we've basically done is we've implemented a signature so that someone else can call claim with our address and we part we give them a signature to say yes you can claim I would like to receive this airdrop but I don't want to pay for my gas fees myself and it enables someone to be able to call this function for us to pay for our gas fees with our permission so let's implement this into our test right now okay so now we're back in our test user wants someone else to be able to claim for them so we're going to create another address which is going to call claim and then user is going to sign a message using their private key remember I said earlier this is why we're going to be using make adder and key because we're going to use the private key to sign a message to say yes you can claim for me so we need another address just going to put it up here address we're going to call it gas payer cuz we're Super Creative like that and then we're going to use make Adder gas payer equals make Adder which is again just one of those helpful things that comes with Foundry and we're going to call this gas p and then in our test function we want to prank the user to sign a message which then the gas payer calls claim using the sign message to send the transaction for them and pay the gas so we prank that the user signs a message first so the first thing we need to do is we need to get the message digest so we got bytes 32 digest equals and then we can because we made it a public function we can call the airdrop contract we can say get message hash I think it was called did we call it get message hash no we didn't but let's go guess get message hash it's more clear user is the address that we want and amount to claim so now we have the digest we can then sign the digest to do this and get the V the r and the S which is going to be a uint 8 V bytes 32 R bytes 32s equals we can use the cheat code vm. sign which will take the private key so we've got that user proof key from before and the digest so now we have this V at the r and the s now when we call claim we can pass through the V the r and the S now we need to prank this vm. prank gas payer to make them the person that's calling this function and now this will all be the same as before we want to check that the user's balance has in fact increased so if we save this open up my terminal again let's run the test ah we now have an incorrect identifier because I changed the name of the function but then when I used it I didn't change the the name accordingly so let's run the test again see if there are any errors cannot overwrite a prank until it is applied at least once we don't need to prank the user because this is just signing we don't really need them to call it we've got their private key let's run the test again and it passed we have now used signatures to say that someone else can claim the airdrop for us they can pay for our gas fees and we don't have them sending these transactions without our permission we are giving permission for them to do that by implementing signatures into our Merkel airdrop contract this is massive we have gone through a lot we have understood Merkel trees and Merkel proofs and we have implemented them into an airdrop contract we have then done the same with signatures understood transaction types we have then implemented signature verification into our smart contract and we have tested it so now before we make an interaction script and we start deploying to anvil and to a ZK sync local node and to ZK sync sepolia I think this is probably a good time to go and take a break as Patrick would say go get a drink go get a coffee go get some food go get some ice cream and let this information marinade if you have any questions leave them in the discussions tab of the GitHub repo associated with this course and shoot us with all of your questions so we can answer them and I will see you very shortly this section is optional if you don't want to be working on ZK sync now before before we continue let's just test that all of this works as expected on ZK sync so to do that we are going to run Foundry up- ZK sync and this is going to install the ZK sync Fork of Foundry and once that is done we can run Forge build-- ZK sync to compile our smart contracts using the ZK sulk compiler which works a little bit differently than the S compiler so we need to double check that everything builds correctly for when we're going to be deploying to ZK sync amazing we've got some warnings here which normally you should not ignore warnings but essentially what it's saying is that we shouldn't really use EC recover unless we're sure that the signature comes from an account with an ecdsa private key attached as ZK sync era has native account abstraction so there may be other accounts which have other signature schemes rather than ecdsa so we need to make sure that these accounts on ethereum are not smart contract wallets they are in fact OAS and then they will have a smart contract account on ZK sync because ZK Sync has native account abstraction but that's fine as long as it implements ecdsa signatures and it has an eoa associated with it on ethereum and it's not a smart contract wallet on ethereum then everything should work fine so we can safely ignore all these warnings and we are in fact using an interface like erc2 I ERC 20 so this warning is also fine right so now if we run forg test-- ZK sync - VV to test on ZK sync and it passes so our tests now pass on ZK sync as well amazing Okie croaky so the next thing that we are going to want to do is create an interaction script so that we can claim the airdrop and what we're going to need to do is we're going to need to sign a message using one account who is in the Merkel tree to say that another person can claim the airdrop for them and then in our script we are going to use that signature to claim the airdrop for another account that is in the Merkel tree to do that we need to create of course an interaction script so let's create a script inside the script folder called interact. s.o and then we shall do the regulars so spdx license identify MIT pragma solidity 0.824 and then we're going to import script from the forge standard library and then also we are going to want to get the most recently deployed airdrop contract and to do that as per usual we are going to be using the devops tools from Foundry devops so we can go import Dev Ops tools from not the forge stand library from the foundary ddev SL Source slev Ops tools cool so the other thing I noticed earlier was that we had a little lib slash here like this and I just went ahead and removed it and then in my Foundry Tom I just added this line to say Foundry devop SL equals lib Foundry Dev op SL so that I didn't have to say lib every time you could have left as is and added lib here but I just I wanted to do it like this and the other thing we're going to need is we are going to need our Merkel airdrop contract so that we can call claim we need the ABI so we're going to need it I'm going to call it claim airdrop is script so we have all the script functionality then we can create a function run to run the script make it extern and then in here we are going to want to get the most recently deployed Merkel airdrop contract so we've got an address most recently deployed same as usual equals Dev Ops tools. get uncore most uncore recently uncore recent uncore deployment and then in here we need the name of the contract which is just Merkel airdrop and then we need the chain which is going to be block dochain ID and then we need to pass this contract address through to a function which we're going to create in a second so I'm going to call my function claim airdrop and I'm going to pass through the address let's now create that function so we can do function clim airdrop not with a capital the lowercase C which is going to take an address we're going to call this airdrop make this public and then in here we're going to want to call claim so we need to wrap the address in Merkel airdrop the interface so that we can get the function we get the function signature so we know what things to pass through and we can call claim and then in here we're going to need the claiming address which is the address who's going to be receiving the airdrop the claiming amount the proof array and the V the r and the S components of the signature we're also going to want to do a little vm. start broadcast as per usual and then vm. n broadcast let's try and declare some of these variables so so we're going to do an address claiming address equals and I am going to make this script work for Anvil you could switch out this claiming address for whoever is going to be signing the message but I have in this input file made this second address the default Anvil key so that we can sign the message and run the end to end flow on Anvil you could switch this out for whatever dress you have that you want to be claiming the airdrop and then in your interaction script you're going to want to put that address there but we are using the default Anvil address so now we have the claiming address now we need to have the claiming amount which is going to be 25 Bagel tokens and it has 18 decimals and now we need this bytes 32 array proof so as before we need the bytes 32 proof one and then we also going to need the bytes 32 proof two and both of these things again like with the test we can get from the output so if we find the address input it's this then these are the two proofs so if we copy the first one Chuck it in there and then we copy the second one and then we Chuck it in there great now we need to set them to proof so we need to put them inside the array so we're going to have proof one and proof to inside the array and now we can pass this through great okay so what about this vrns okay so to get the vrns we need to sign the message using this account the account that we want to claim they are going to be in this demonstration different from the account which is going to be calling this script is going to be running this script and calling claim this account the default envel account can receive the airdrop for free so we need to give them permission so that means we need to sign a signature there are a couple of ways with Foundry that we can sign signatures the first one we have already seen and that was when we use this vm. sign and we could create another script in which you do another vm. sign and that would work perfectly fine on Anvil or any chain in which Foundry scripts run correctly so it wouldn't work for ZK sync for instance at the time of recording you cannot run scripts correctly on ZK sync and the other reason is because maybe you don't don't want to be creating a script maybe you're just interacting with a protocol and you just want to be able to create a signature quickly so I'm going to show you another way that we can create signatures and that is using cast wallet sign and what this command is going to do is it's going to create us a signature which is going to have the VR and S components all together it's going to be one byes object and then we're going to have to break it down into the VR and S components so let's go ahead and first create our signature Okie doie let's create a signature using the default avable key to say that the second default account who is going to be running this script can in fact claim for us so firstly to do that we are actually going to want to get the data to sign so I'm hoping that at this point you have an anvil running an anvil local node and you have deployed both the bagel token and the airdrop contract to it but in case if you have canceled your Anvil node or whatever let's run it again the first thing you're going to want to do is a little Foundry up to make sure that we're on the vanilla version of Foundry not the ZK version of Foundry and then you can copy the make file associated with this course so that we can run make deploy and what this is going to do is it's just going to run our script nope first I need to start my Anvil local node and then once that's done I can run make deploy and then up here you can see we have the Merkel airdrop token and the bagel token successfully deployed so now what we can do is we can copy copy this Merle airdrop token and we can call on this contract get message hash to get the data to sign so let's do that now we can run cast call paste in the address of the airdrop contract get the function signature which is get message Ash and this takes an address and a uint 256 then we need to put in those two variables so we copy the address and the claiming amount and then we need the RPC URL which is just HTTP colon loost colon 8545 and now we have the data to sign so now we can use cast wallet sign to sign this message and the other thing that we're going to add is we're going to add D- no dash has so that so that this command doesn't hash the message again because sometimes you can use this to sign a message that is purely a string like Kira is awesome and you can sign however because we already have bytes we don't need them to Hash that again so we can just add this D- no hash and then we paste in the bytes to sign then we're going to do-- private key and then we're going to paste the first default Anvil key private key now if you were doing this on a testnet or and using an actual address an actual account then you are not going to be doing private key here you're going to instead do-- account and then you're going to use your key store account to sign the message so you're not going to be using private key the reason I'm pasting my private key in here is because it's not mine it's the default Anvil key that is public so if we scroll up here in the terminal in our Anvil terminal we can get the first default Anvil key we can paste that in there and we can sign the message now we want to copy this message apart from the O and the X so that we can use this signature we can break it up into the vrns components and pass it through to claim when you use cast wallet sign you create one one single signature however what we need is we need a v an r and an S broken up individually because that's what our API is taking we could have designed this just to take a simple bytes signature which had all of the this information the VR and the S packed together and the way we would have had to do this is when we verified the signature using this TR recover so you could instead use this TR recover from open Zeppelin which takes just a signature and then splits up itself into the V the r and the s and it does this using assembly so it takes the first 32 bytes and sets it to R the second 32 bytes and sets it to S and the final Bon sets it to V and then it uses the regular version of TR recover that we were using before that takes the V and R and S individually so it's up to you how you want to design your protocol do you want your users to be having to provide their VN RNs separately or just one signature different signing methods output different things so some including C wallet sign output just the bite signature whereas if you use vm. sign it gives you the V the r and the S separately so it's up to you how you want to implement it but we have chosen to design it with v and RNs separately and then I will show you how we can unpack a signature into the individual components and how we're going to create signatures in a second but I just thought it was worth noting that you can do either or and it's a very easy swap out let's split up the signature into the VR s components now so the first thing we want to do is we want to save this bite signature as a variable and the way we do that is use the keyword hex and then you have quotations and then you plunk the data in there without the ox and let's just make this private because we don't want inheriting contracts inheriting scripts to to use it right so now in order to be able to pass this through we need to break it up so let's create a function that will do that so we've got u in 8 V bytes 32 R and bytes 32s equals now you might think that you could do like an ai. dcode however the signature is not created using ABI en code but instead it's an ABI en code packed so all of the v r and s well actually in this case it's going to be R then s then V are packed together they're concatenated together instead you've just got this whole thing is literally just the V the r and the S the first one is R which is the first 32 bytes the second part is s which is the second 32 bytes and the final byte is V so we purely just need to break this up to find them so instead of doing Abid code we're going to make a little function called split signature then we're going to pass through that signature let's create that function now so we've got a function called split signature which is going to take a bytes object call it Sig let's make it public returns uint 8 V bytes 32 R and byes 32s and then in here we are going to do something very similar to what this co-pilot code is saying so we first need to require that the length of the signature is equal to 65 bytes and that's because 32 + 32 + 1 is 65 and then that's the length of v r and s alog together and otherwise we will return with this string invalid signature length now we need to do the exact code that it says here so we are using assembly to break up the signature into vrns now weirdly when you have signature which is combined together the VR and S R is actually first so it goes R then s then V however when you're using functions so like when you're using open Zeppelin or you're interacting with an API of some description it usually follows the format V then R then s it can be a little bit confusing but if you're using a function typically it's going to be v r and s and then if you're looking at signature you're breaking up you're packing it together it's going to be R then s then V so what this assembly code is doing looks kind of scary but don't worry too much we don't need to worry specifically about what all these words mean this will be covered in depth in a later part of the course there is actually an assembly and formal verification course and it'll be covered in depth there but from memory we are loading the first 32 bytes and then setting it to R then we are getting the second 32 bytes and setting it to S and then we're getting the final bite and setting it to V and returning it so actually rather than doing a require here I'm going to do a custom error so we're going to say if the signature length is not equal to 65 bytes then we're going to revert with not invalid signature I'm going to do underscore underscore claim ER drop script so that we know where the error is coming from underscore invalid signature l L and then let's copy that add that to the top of our script contract so we can say error that and then we can also restrict this to Pure so if you see here the required statement instead of the if and then revert in the rest of this recording or you see the contract without this error message just note that I had to make this modification afterwards because I wanted to save the gas so you should be doing this not a required statement and you should have this error at the top of your script now we have used cast call to get the message to sign and then we've used cast wallet sign-- noash to sign the message and then we have split up the message into the V the r and the S so now if you ever need have a signature to interact with a protocol that requires you to have a signature you can do it both if it's the full signature or even if you need the V and the r and the S split up separately you know how to do both which is amazing right so now that we have done that we can safely run our script and hopefully it'll work as expected so we can run Forge script and then the path script SL interact. s.o colon claim airdrop D- RPC URL HTTP codon Local Host 8545 private Dash key again this is going to be D- account if you're working on an actual test net or main net chain not on like a local node however I am actually going to use this second Anvil key so that I can claim and pay the gas fees for this first one so the second Anvil key is the one that's going to be calling claim so that the first address is the one that is going to receive the tokens and then we need-- broadcast and I think that is everything that we need so we can run this command and we have an error I've been silly this is an end broadcast it's stop broadcast no matter how many times I run scripts I always forget what the API is like okay let's run it again remember chain ID not found have I spelled it wrong yes I have missed an i and then let's run again and I've also SP spelled deployment wrong deployment there we go again and we have successfully completed the claim however we're going to want to check this we want to check whether the first address has in fact received the airdrop so we can run cast call on the token contract so if we just scroll up we can retrieve this token contract address so that we can get the balance of that first default Anvil address we need balance of and this takes an address and that is the function signature of the balance of function on the token contract and then the address that we are going to want is the first Anvil address and if we execute that then we get this horrible looking piece of data so we now need to do cast --2 D deck to convert this data into decimals and you can see this is in fact the amount that we aird dropped to them they have received the airdrop fantastic our script worked we aird dropped 25 Bagel tokens to the default Anvil address using the second default Anvil address to pay for the gas by using a signature created using the first default envil address they said yep go ahead use my signature and you can claim so that I can receive the drop and it all worked as expected amazing this section is optional if you don't want to be working on ZK sync let's now do the same thing but on a ZK sync local note so the first thing that we want to do is we want to run Foundry up- ZK sync to get the ZK sync Fork of Foundry and we also want to kill this Anvil node now things are a little bit more tricky and difficult on ZK sync and ZK sync local node because we cannot use scripts at the time of record recing so I have gone ahead and made a bash script to run all of the commands and what we're going to do instead is we're going to run through what the script looks like I'm going to walk you through what commands it's running and then we're just going to go ahead and run it and it's going to be one command it's going to be super pretty and lovely instead you're just going to understand exactly what commands you are using and you could then go and do it from scratch yourself but I don't expect you to write this bash script from scratch instead I want you to copy this from the GitHub research associated with this course we're going to create a file called interact zk. sh and then you can paste in the script which is called the exact same thing on the GitHub repo so in here we have different variables that we need so we've got the default ZK sync local key this is the private key for this address which is the default ZK sync account and this is the account which is going to be calling claim it's going to be paying for the gas so that the default Anvil key the same address as before is going to receive the airdrop so as before we need the private key so that we can sign the message and we're going to do that the exact same way as before then we also have the root and two proofs we have the proofs for the default Anvil key so we've got the root and the two proofs same as before as we're going to need to deploy The Bagel token contract and also the airdrop contract so we need to pass through the route to The Constructor so the first thing this does is it starts a ZK sync local node using the ZK sync CLI so to be able to run this command you actually need to have Docker installed and running so make sure pause here if you need to do that and then it deploys the token contract The Bagel token contract and just prints that to the terminal so we can see what's going on then it uses that to deploy the airdrop contract and it passes through the route and the token address as the Constructor arguments and then it prints out to the terminal again then we get the message hash by calling get message hash using the default Anvil address and the number of tokens that we want them to be receiving we get the message hash then we sign the message again using C wallet sign we get the private key for the default envil key the one who wants to be receiving the airdrop and then we clean that signature by again removing that Ox at the start and then we print that clean signature to signature. txt we then run a script called split signature and that is going to do the same as what we did before when we used assembly to split the signature into vrns and it's going to take the signature from the signature. txt file and then it will output the V the r and the s to the terminal we will go ahead and create this file in a second I will loop back to it so then we need to send tokens to the Token owner so we are creating an initial Supply and we can do that because we are in fact the deployers of the token contract therefore we are the owner and then we need to transfer those tokens to the airdrop contract which again we can do because we are the owner of the bagel token contract so we created an initial Supply then we sent them to the airdrop contract then we call claim on behalf of this default Anvil address but using the default ZK sync address and we pass through the proofs and the signature as well as the address that we want to be claiming and the amount then we get that hex balance by again doing cast c to get the balance of the default Anvil address on the bagel token contract and then we output this to the terminal in a very nice way using cast-2 deck the same as before and then we just clean up by moving that file the temporary file that we did to put the signature into so that we could read it in our script let's create that script very quickly now so we're going to call it split signature. s.o and then again because we've already run through this you can just go ahead and copy and paste this from the GitHub repo and this is doing the exact same thing as before it's using assembly to get the first 32 bytes setting it to R the second 32 bytes and setting it to S and the last bite and setting it to V and then in run we are reading this signature. txt file we're passing the bytes to get it into byes form from string and then we are splitting it into vrns using that split signature function and then we are logging that to the terminal so that interact can read from the terminal the V the r and the S so that we can then use them when we are claiming so make sure you have Docker running and then we are going to run CH mod plus X interact ZK and and Dot interact. sh and what this is doing is this part makes the script executable then we've got andand to say we've got another command and then do slash which runs and then the file which is interact zk. sh to run the file let's enter that so we're creating a ZK sync local note deploying the token contract with the address deploying the Merkel air drop contract with the address we're now signing the message so we're calling the function to get the message hash and then we are running cast wallet sign to sign the message getting the V and the r and the S and then we can pass it through to claim we claim the tokens and then we can see that the balance of the claiming address has in fact increased it worked amazing let's finally deploy to ZK sync seoa so that we can wrap all of this up and then we will be all finished here let's do that now here we are going to be deploying to ZK sync ofoia but feel free to deploy to whatever roll up of you're choosing okay finally let's deploy to ZK sync sapoia how exciting we're going to have to do everything from scratch not using scripts which I don't actually recommend I recommend when you're deploying even to a testnet you don't want to be getting things wrong and wasting funds so you ideally want to be using a script so feel free to go ahead and choose another chain where you can literally just run this deploy merel airdrop script to deploy the contracts and then also this interact script to interact with your contract you can do that from another chain that supports vanilla Foundry and you can run scripts but as of as of recording you cannot do that on ZK sync so I'm going to be doing everything using my terminal instead so first of all we need to deploy the token contract so we can run Forge create ah there's actually something I wanted to explain very quickly now the first thing I want to explain is that I'm going to be doing everything using an already imported wallet I have two wallets in my metamask and I have named them updraft and updraft 2 as key stores so I can do D- account and then I can say updraft or updraft to like this so what I'm going to do is because I've already put my account address for updraft 2 that is in my wallet key store in the input here so this address is actually mine so it's already saved in my key store so that I'm never going to be using-- private key and then the other account that I'm going to be using is updraft who's going to be deploying all the contracts and calling claim for updraft 2 which is this address so for create let's deploy that token contract then we need the path Source SL Bagel token do s.o no it's not a script we've been doing too many scripts do Soul Cod on Bagel token then we don't have any Constructor ARS so I can just do-- RPC URL dollar curly brace ZK sync suppo RPC URL now make sure that in your EnV file you already have this and you've run source. EnV to make sure that your command line can see these variables and you're going to want to use this RPC URL here as of recording the Alchemy RPC URL is not working 100% correctly maybe when you run this it could be up and running and work completely fine but I was having issues so I using this RPC URL and then we are going to add-- account and for me it's going to be updraft that's what my updraft and that's what my key store wallet is called it's called updraft and yours might be default or default key or something like that and then we're going to add D- Legacy to make it a type zero transaction and then D- ZK sync now maybe I didn't actually run source. EnV and let's run it again and now I need to enter my key Store password for updraft I'll go ahead and do that now so we have now deployed The Bagel token contract to this address now let's save that as a temporary local environment variable by using the keyword export and we're going to call it token address equals and paste it in there so that we can use that later now let's deploy our airdrop contract so again Forge create sources SL Merkel airdrop do s colon Merkel airdrop and now we need the Constructor ARS D- Constructor ARS then we need the token contract token address then we need that root hash which we can get from our output file root copy it paste it in there we don't need to save this as enir variable because we're only going to use it once and actually this needs to be the other way around so let's remove that swap them around because it's the rout first and then the token contract so dollar token address D- rc- URL ZK sync sepolia RPC url-- account updraft D- Legacy to make it type zero D- zase Sy enter your password again by the way we don't need to worry about These Warnings here I think I mentioned that earlier but it's fine because we all we need to do is make sure that these inputs these addresses are not smart contract accounts on ethereum and also because we are using EC recover the other thing we need to do is make sure that the smart contract account which is native on ZK sync is using ecdsa signatures other signature algorithms can be used so just be careful on on ZK sync and make sure that the addresses you are airdropping to do use ecdsa signatures and not some other signature algorithm so we have successfully deployed our contract to this address so let's again save that to an environment variable so we can run export airdrop equals and then paste it in there so the next thing we need to do is we need to get the message to sign and then we need I need my account to the one that's in the Merkel tree this ox2 EA blah blah blah to sign the message so we can run cast call airdrop address function signature is get message hash and it takes an address and the U 256 then the address that we want is going to be this one this is the one which is going to receive the airdrop and the amount is this 25 Bagel tiens D- RPC URL dollar zking RPC URL and that's it so now we have the message to sign so now we can use C wallet sign using my second wallet in my key store my second account on metamask to sign the message so we can go cast wallet sign then we need D- no hash like before then we need the bytes to sign then I'm going to use D- account and I'm going to use updraft two to use my second account the one who is in the Merkel tree and is going to receive the airdrop so I need to enter my password so now I have the bites I can go ahead and copy that and then I can go into split signature and I will need to make a little file called signature. txt and I need to paste that in there and remove the ox so I'm just kind of doing what the script was going to do for me and then that means that split signature can use the signature. txt file to get the signature and split up into the V the r and the S so let's run this script now so we can run Forge script script SL split signature s dool colum split signature and now we have the V the r and the S components let's save them into variables so export b equal 27 export R equals copy this paste it in there export s equals copy this paste it in there and now we can run claim so we can claim on behalf of account two but first we need to create an initial Supply and we need to transfer the tokens to the airdrop contract so let's quickly do that now so we're going to run cast send we need the token address we need to Mint tokens which takes an address and a u 256 and we are going to Mint to my address in my metamask the one who deployed the contract the owner and then the amount which is going to be four times the amount that each person can claim so that the contract holds the entire amount that needs to be aird dropped oops don't know why I press enter and then we need Das Dash account and then this is going to be first account CU they are the owner of the contract then we need D- RPC URL ZK sync sepolia RPC URL and the transaction has been successful so now we need to send those tokens to the airdrop contract so that it can perform the air drops so we can run cost send we're almost there we need the token contract we want to run transfer which takes an address and an amount un 256 then we want to send to the airdrop address and we want to send them four times the amount that each person can claim there are four claimers again and then D account and then it's going to be for me called updraft but this is whoever you have been deploying all the contracts with and the person who's going to call claim D- RPC URL ZK sync polio RPC URL and we' now transferred the tokens to the airdrop contract so let's call claim let's use our first account to claim for our second account where the second account is in the Merkel tree I know it sounds like I keep repeating this but I feel like could be a little bit confusing so just want to keep repeating right so we've got car sent we're calling the airdrop contract we are calling claim which takes us parameters and address the U 256 byes 32 array which is the proof U 8 which is V byes 32 which is R byes 32 which is s now let's put all those parameters in so the first one is the address that wants to claim which is my second address then the amount then the proof array so we've got an array like this and then in here we want to be putting the proof so let's get those proofs for my account so we need to find that address this is my address so I need to get those two proofs number one and number two and then we can get v r and s then we need-- account updraft D- RPC D URL ZK sync sepolia RPC URL into my password and it says we have successfully called claim but let's check that let's run cast call on the token contract to check the balance of my second address so we need balance of an address function signature and then the address is my second account so let's copy that address put it in there -- RPC URL so is the last time I'm going to have to do this ZK sync sapoia RPC URL you can see it's nonzero let's do a little cast d-2 deck amazing you can see that on ZK sync we have in fact claimed 25 Bagel tokens for my second account using my first account to pay for the gas by signing a transaction with my second account to say yes my first account can call claim and have the tokens aird dropped to my second account let's have a look at this on ZK sync scanner so you can see in here we have in fact got a transaction 25 Bagel tokens were sent to my account it has worked we haven't yet processed on ethereum so this is not completely final but we can consider this as final cuz we're on ZK sync and it's amazing that was so cool so now we can just wrap things up and give a brief summary of everything that we have learned okay so in this module we have learned what an airdrop is what a Merkel tree is and the fact that we can use Merkel trees to prove that some data is in a group of data we can use it to verify that they are in fact in that data we can use this to airdrop token without having to Loop through an array we have learned how to use signatures how to create them using both vm. sign and cast wallet sign we've learned how to use signatures inside our smart contracts and verify them using open Zeppelin which implements EC recover and we've done this in a safe and secure way we have tested our smart contract we have created a script to deploy our smart contract and interact with it we have then done that on anvil on ZK sync Lo node and then finally on ZK sync aolia we have learned what different transaction types are how signatures work and how ecdsa works there was a lot of information here so don't worry if you feel a little bit confused don't worry if you're completely confused feel free to watch the whole thing again to read up some more as always as this was a lot of information and it was a lot to take in but with that said it's done so as always time to take a break let this information solidify and come back to have some more Patrick fun and I will see you very shortly and enjoy the rest of your course all right and welcome to lesson 13 boundary upgrades where we're going to learn about upgradable smart contracts the pros and the cons now I've actually done a couple different versions of this type of video in the past so we're going to go through an old video explaining the concept of this then we're going to move over to remix and we're going to explain an important subl lesson and then we're going to go to our vs code and we're actually going to do all of this in Foundry upgradable smart contracts are something that I'm going to go ahead and just say right out loud we should deploy as little as possible we should not be defaulting to upgradeable smart contracts it sounds like a good idea in theory but we've seen time and time again whenever a protocol has a centralized control over contracts issues Happen full stop so when going through this course and when learning about this keep this in mind what are the downsides of upgradeable smart contracts and then you can begin to ask questions have we seen examples in real life where these downsides have come to a fruition and I'll say right now 100% the answer is yes so keep that in mind when watching this and use this knowledge to make yourself be an even better smart contract Dev so let's learn now I'm editing this video much later after I filmed it hence why I have a beard so I'll be jumping in from time to time updating some of the sections when deploying your smart contracts on chain we all know that those smart contracts are immutable or unchangeable but what if I told you that they were mutable well technically I wouldn't be correct however smart contracts actually can change all the time when people transfer tokens when people stake in a contract or really do any type of functionality those contracts have to update their balances and update their mappings and update their variables to reflect this the reason that they're immutable is that the logic itself never changes and will be onchain like that forever so technically yes once they are deployed they are immutable and this is actually one of the major benefits of smart contracts in the first place that nobody can tamper with or screw with our smart contracts once we deploy them however this can be an issue if for example we want to upgrade our smart contract or protocol to do more things or we want to fix some glaring bug or issue that we have now even though we can't change the specific code that's been deployed to an address we can actually do a lot more than you think and in this video we're going to explain the different methodologies behind upgrading your smart contracts and then we're going to show you how to do it with hard hat and open Zeppelin huge shout out to a lot of open Zeppelin and trailer bits articles that helped me put this video together uh and a number of other sources as well links in the description so let's get to it now at first glance you might be thinking if you can upgrade your smart contracts then they're not really immutable then and in a way you'd be right so when explaining kind of the different philosophies and patterns that we can use here we do need to keep in mind the philosophies and decentralization implications that each one of these patterns have as they do all have different advantages and disadvantages and yes some of the disadvantages here are going to affect DEC centrality so we need to keep that in mind and this is why it's so important that before you go ahead and jump in and start deploying upgradeable smart contracts you understand the tradeoffs so we're going to talk about three different ways to upgrade your smart contracts the first one being the not really SLP parameter ties way to upgrade your smart contracts the social migration method and then the method that you probably have heard about which is proxies which have a ton of subcategory like metamorphic contracts transparent upgradeable proxies and Universal upgradable proxies so let's talk about the not really upgrading method or the parameterization method or whatever you want to call it this is the simplest way to think about upgrading your smart contracts and it really isn't upgrading our smart contracts because we can't really change the logic of the smart contract whatever logic that we've written is there we also can't add new storage or state variables so this is really not really upgrading but it is something to think about upgrades is just parameterizing everything whatever logic that we've deployed is there and that's what we're interacting with this function means we just have a whole bunch of Setter functions and we can update certain parameters like maybe we have a reward parameter that gives out a token at 1% every year or something like that maybe we have a set of function that says hey update that to 2% or update that to 4% it's just a Setter function that changes some variable now the advantages here are obviously this is really simple to implement the disadvantage is that if you didn't think of some logic or some functionality the first time you deployed their smart contract that's too bad you're stuck with it you can't update the logic or really update anything uh with the parameterization AKA not really method and the other thing you have to think about is who the admins are who has access to these Setter functions to these updating functions if it's a single person guess what you a centralized smart contract now of course you can add a governance contract to be the admin contract of your protocol and that would be a decentralized way of doing this so just keep that in mind you can do this method just need a governance protocol to do so another example of this might be a contract registry and this is something actually that early versions of AA Used before you call a function you actually check some contract registry that is updated as a parameter by somebody and you get routed to that contract and you do your call there again this really doesn't allow us to have the full functionality of upgrades here you can argue that this registry is a mix of one of the later versions but for all intents and purposes this doesn't really give us that flexibility that we want for our upgrades but some people might even think that upgrading your smart contract is ruining the decentral and one of the things that makes Smart contracts so potent is that they are immutable and that this is one of the benefits that they have so there are some people who think that you shouldn't add any customization or any upgradeability you should deploy your contract and then that's it Trill bits has actually argued that if you deploy your contract knowing that it can't be changed later you take take a little bit extra time making sure you get everything right and there are often less security vulnerabilities because you're just setting it forgetting it and not looking at it again now if I wanted to upgrade a smart contract with this philosophy in mind the philosophy that I do want to keep my smart contracts immutable we can instead use the social migration method which I previously called the Yeet method and now I think it's less funny so we're just going to stick with social migration the social Yeet method or the migration method is just when you deploy your new contract not connected to the old contract in any way and by social convention you tell everybody hey hey this new contract this new one that we just deployed yeah this is the real one now and it's just by Convention of people migrating and over into using this new one that the upgrade is done hence my slang name of social Yeet because you Yeet the first one out of the way and you move to the second one I think I'm funny this has the advantage of truly always saying hey this is our immutable smart contract and this is our new this is really the truest definition of a mutable because since you give it no way of being upgraded in place then if somebody calls that contract in 50,000 years in the future it'll respond exactly the same another huge disadvantage here is that you have to have a totally new contract address so if you're an erc20 token for example you have to go convince all the exchanges to list your new contract address as the actual address keep in mind that when we do this we do have to move the state of the first one over to the second one one so for example if you're an ERC token moving to a new version of that ERC token you do have to have a way to take all those mappings from the first contract and move it to the second one obviously there are ways to do this since everything is on chain but if you have a million transfer calls I don't want to have to write the script that updates everyone's balance and figures out what everyone's balance is just so I can migrate to my new version of the contract so there is a ton of social convention work here to do trailer bits has actually written a fantastic blog on upgrading from a V1 to a V2 or Etc with this Yeet methodology and they give a lot of steps for moving your storage and your state variables over to the new contract so Link in the description if you want to read that now let's get to our big ticket item so in order to have a really robust upgrading mentality or philosophy we need to have some type of methodology or framework that can update our state keep our contract address and allow us to update any type of logic in our smart contracts in an easy way which leads us to our big ticket item the proxies what's our big ticket item proxies people proxies proxies are the truest form of upgrades since a user can keep interacting with the protocols through these proxies and not even notice that anything changed or even got updated now these are also the places where you can screw up the easiest proxies use a lot of low-level functionality and the main one being the delegate call functionality delegate call is a low-level function where the code in the Target contract is executed in the context of the calling contract and message. sender and message. value also don't change so you understand what delegate call means now right great and in English this means if I delegate call a function in contract B from contract a I will do contracts B's logic in contract a so if contract B has a function that says hey store this value in a variable up top I'm going to store that variable in contract a this is the PowerHouse and this combined with the fall bang function allows us to delegate all calls through a proxy contract address to some other contract this means that I can have one proxy contract that will have the same address forever and I can just point and Route people to the correct implementation contract that has the logic whenever I want to upgrade I just deploy a new implementation contract and point my proxy to that new implementation now whenever a user calls a function on the proxy contract I'm going to delegate call it to the new contract I can just call an admin only function on my proxy contract let's call it upgrade or something and I make all the contract calls go to this new contract when we're talking about proxies there are four pieces of terminology that we want to keep in mind first is the implementation contract the implementation contract has all of our logic and all the pieces of our protocol whenever we upgrade we actually launch a brand new implementation contract the proxy contract proxy points to which implementation is the correct one and routes everyone's calls to the correct implementation contract you can think the proxy contct contract sits on top of the implementations the user the user is going to be making contract and function calls through the proxy contract and then some type of admin the admin is the one who's going to decide when to upgrade and which contract to point to in this scenario the other cool thing about the proxy and delegate call is that all my storage variables are going to be stored in the proxy contract and not in the implementation contract this way when I upgrade to a New Logic contract all of my data will stay on the proxy contract so whenever I want to update my logic just point to a new implementation contract if I want to add a new storage variable or a new type of storage I just add it in my logic contract and the proxy contract will pick it up now using proxies has a couple of gotas and we're going to talk about the gachas and then we're going to talk about the different proxy contract methodologies because yes there are many proxy contract methodologies as well and this is why TR bits doesn't really recommend using upgradable proxies for your smart contracts because they're fraught with a lot of these potential issues choose not to mention again you do still have some type of admin who's going to be upgrading your smart contracts now if this is a governance protocol then great you're decentralized but if this is a single group or entity then we have a problem the two biggest gotas are storage clashes and function selector clashes now what does this mean when we use delegate call remember we do the logic of contract B inside contract a so if contract B says we need to set value to two we go ahead and set value to two but these smart contracts are actually kind of dumb we actually set the value of whatever is in the same store's location on contract a as contract B so if our contract looks like this and we have two variables in contract a we're still going to set the first storage spot on contract a to the new value this is really important to know because this means we can only append new storage variables in new implementation contracts and we can't reorder or change old ones this is called storage clashing and in the implementations we're going to talk about they all address this issue the next one is called function selector clashes when we tell our proxies to delegate call to one of these implementations it uses what's called a function selector to find a function the function selector is a 4 by hash of the function name and the function signature don't worrying about the function signature for now now it's possible that a function in the implementation contract has the same function selector as an admin function in the proxy contract which which may cause you to do accidentally a whole bunch of weird stuff for example in this sample code in front of you even though these functions are totally different they actually have the same function selector so yes we can run into an issue where some harmless function like get price has the same function selector as upgrade proxy or destroy proxy or something like that this leads to our first out of the three implementations of the proxy contracts this is called the transparent proxy pattern in this methodology admins are only allowed to called admin functions and they can't call any functions in the implementation contract and users can only call functions in the implementation contract and not any admin contracts this way you can't ever accidentally have one of the two swapping and having a function selector clash and you running to a big issue where you call a function you probably shouldn't have if you're an admin you're calling admin functions if you're a user you're calling implementation functions so if you're an admin and you build some crazy awesome def5 protocol you better come up with a new wallet address because you can't participate the second type of we're going to talk about is the universal upgradeable proxy or the [Music] UPS this version of upgradeable contracts actually puts all the logic of upgrading in the implementation itself this way the solidity compiler will actually kick out and say hey we got two functions in here that have the same function selector this is also advantageous because we have one less read that we have to do we no longer have to check in the proxy contract if someone is an admin or not this saves on gas of course and the proxy is also a little bit smaller because of this the issue is that if you deploy an implementation contract without any upgradable functionality you're stuck and it's back to the Yeet method with you and the last pattern or methodology that we're going to talk about is the diamond pattern which does a number of things but one of the biggest things that it does it actually allows for multiple implementation contracts this addresses a couple different issues for example if your contract is so big and it doesn't fit into the one contract maximum size you can just have multiple contracts through this multi- implementation method it also allows you to make more granular upgrades like you don't have to always deploy and upgrade your entire smart contract you can just upgrade little pieces of it if you've chunked them out all the proxies mentioned here have some type of ethereum improvement proposal and most of them are in the draft phase and at the end of this explainer we will do a demo of showing you how the delegate call function works and the end of the demo is right now so let's look at delegate call now we're going to learn about how to actually build these proxies how to build these upgradeable smart contracts and to do this we first need to learn about this delegate call function and it's going to be really similar to the call function which we learned much earlier if you haven't seen that be sure to go back to our hard at nfts we have a subl lesson in there about evm op codes and coding and calling and we'll give you all the context for delegate call like I said in the explainer it's very similar to call however the way that I think about it is one contract says oh I really like your function I'm going to borrow it myself and we're going to be looking at solidity by example I'll leave a description in the GitHub and all the code for this will be in the GitHub associated with this lesson as well now we have two contracts we have this contract B that we're going to be deploying on remix and it looks like a real minimalistic real simple contract we have a couple of storage variables here and then we have a function that updates our values we have a function called set bars and it updates our ENT public num now as we learned before whenever we have some type of contract with storage variables they get stored in in this storage data structure that's index starting from zero right now our uint public num is at index zero our sender is at index one our values at index 2 Etc now we're going to deploy a contract a and now this contract is actually going to use the delegate call function now in contract a this is going to look a little bit different but it's still going to have this set bars function except it's going to make a delegate call function call to our contract B the difference here is we're doing contract. delegate call what this call does is something very similar to call normally if we did contract. call on this contract we would just call this we would just be calling this function set bars which would update contract B's storage but instead we're saying hey call that set bars function and then pass this as an input parameter but call it in our contract cont call it on contract a we're kind of borrowing a function for our contract and so instead what we're going to do is we're going to borrow the set bars and run the set bars function over here now the difference is instead of num equals num the variables could be named different than the variables on contract a so instead of num equals num our contract is going to say hey whatever that storage of Zero have that equal to whatever we pass as an input parameter and if that's a little bit confusing just stay with me let's go ahead and let's see this in remix so I'm going to copy paste this code into remix here so we can kind of test and see what this looks like again there's a link to this in the GitHub repo associated with this course feel free to pause the video to grab this link it's solidity hyphen by hyphen example.org delegate call or you can just grab the code directly from Lesson 16 hardhead upgrades so let's compile this code and let me show you what I mean so I'm going to compile it and we'll go to the Run tab and first let's deploy this contract B hit deploy we now have a contract num sender and value or all blank we'll update the number to something like 777 we'll hit set vars set bars we'll change the storage variable num to 777 and then we're changing the sender and the value sender and value is zero now let's deploy contract a so we'll scroll back up contract a deploy of course we're on the JavaScript VM now we have this contract a with num value and sender are also all blank but when we call set bars it's going to borrow this set bars function from contract B and run it in contract a you can almost think of it as if we're copying set bars and pasting it into our contract a just for one run and then immediately deleting it again that's what this delegate call function does so when I call set vars I'm going to pass it this contract address as an input parameter so it knows to call this contract said vars function when I pass it the address and I pass 987 since we're borrowing the function we're not going to update this numb on contract B we're going to update the num on contract a so when I hit set vars we see num now has 987 we see sender and we see value still being zero here because again we're borrowing this function and running it here now the way that this works is it actually doesn't look at the names of our storage variables it looks at the storage slots so when we borrow this function using delegate call so we could have this these variables we named anything instead of numb we could call this first value sender we could call something else and then value we could call woo or whatever you want here and when we borrow this function using delegate call instead of us grabbing the actual names of the variables our contract will swap out these variable names with the storage slot so it says oh okay well in contract B your a assing the numb variable which is which is at storage slot zero so when we borrow set bars in contract a with delegate call we'll say storage slot Z is going to equal that uncore num which for this contract storage slot zero is first value so we'll say first value equals uncore num something else is going to be storage slot to so it's going to say okay storage Slot 2 we're going to update storage Slot 2 to mess. Sender okay value here is storage slot three so whatever is in storage slot three will update with message. value like this so that's essentially what's going on behind the scenes so let's go ahead let's delete those and redeploy redeploy them so we'll deploy contract B we'll deploy contract a right now in B once again if we do 1 2 3 for set bars we have 1 2 3 and then cont contract a now even though these variables have different names we could grab contract B's address paste it in do 654 hit set bars and first value is now 654 so delegate call allows us to borrow functions and then just transposes whatever is in here to the storage location equivalents and the other thing that's interesting is that even if you don't have variables it'll still save to storage slots so when contract if we didn't have any of those variable names storage slots 0 1 and 2 would still get updated now here's where things can get really interesting let's delete our contract a again and let's change the type of our contract A's first value to from a uint to AB Boolean let's save that and now let's deploy contract a now when we call set vars on our contract a it's still going to use the set bars function of contract B which takes say u in and assigns the first storage slot that number we pass it but our first storage slot is now a Boolean so what do you think's going to happen now well let's try it out let's copy contract B's address paste it in here we'll pass we'll do 22 two as our input parameter we'll hit set bars our transaction actually does go through and now when we look at first value it says true huh that's really weird what if we change set bars to zero and hit set bars and now first value is false in storage here when we add a number with set bars it's going through because it's just setting the storage slot of the Boolean to a number and when solidity reads it it goes oh well first value is a Boolean so if it's anything other than zero it's going to be true so this is how you can actually get some really weird results if your typings are different or if your storage vars are different what if we made this an address so this is where working with delegate call can get really weird and really tricky really fast all right now with all this being said let's turn up the heat and let me show you a small proxy a minimal proxy example that shows how a contract can be used as a singular address but the underlying code can actually change and all the code we're going to be working with once again in the hard Hut upgrades FCC subl lesson small proxy doou and you can go ahead copy paste this code if you want to follow along so you don't have to code along with me here but you absolutely can if we want now I will say this is going to be one of the most if not the most advanced section of the entire course so feel free to go ahead and skip over this subl lesson if you want to just move on to learning how to actually build these proxies without really understanding what's going on behind the scenes however it is still really powerful if you do understand what's going on behind the scenes so I have this minimalistic starting position right here I have small proxy is proxy and I'm importing this proxy do thing from open Zeppelin open Zeppelin has this minimalistic proxy contract that we can use to actually start working with this delegate call now this contract uses a lot of assembly or what's something called Ule and it's an intermediate language that can be compiled to bite code for different backends it's a sort of inline assembly inside solidity and allows you to write really really lowl code close to the op codes now we're not going to go over Ule but I'll leave some links to the Ule documentation if you want to learn more even if you're a really Advanced user you really want to try to use as little Ule as possible because since it is so much lower level it is much easier to screw things up however like I said for this example we are going to be using a little bit of Ule now in this proxy that we're going to be doing we have this delegate function which inside this inline assembly which is Ule it does a whole lot of really lowl stuff but the main thing that it does is it goes ahead and it does this delegate call functionality if we look here we can see it's using a fallback function and a receive function so whatever it receives a function it doesn't recognize it'll call fallback and fallback calls our delegate function so anytime a proxy contract receives data for a function it doesn't recognize it sends it over to some implementation to some implementation contract where it will call it with delegate call in our minimalistic example here we have a function called set implementation which will change where those delegate calls are going to be sending this could be equivalent to like upgrading your smart contract and then we have implementation here to read where that implementation contract is now to work with proxies we really don't want to have anything in storage because if we do delegate call and that delegate call changes some storage we're going to screw up our contract's storage the one caveat though to this we do still need to store that implementation's address somewhere so we can call it so EIP 1976 is called the standard proxy storage slot which is an ethereum improvement proposal for having certain storage slots specifically used for proxies and in our minimalistic example here we set byes 32 private constant implementation slot to that location in storage and we'll say okay whatever is at this storage slot is going to be the location of the implementation address so the way our proxy is going to work is any contract that calls this proxy contract if it's not this set implementation function it's going to pass it over to whatever is inside the implementation slot address that's what we're going to build here so we have this small proxy is proxy and we'll create a real minimalistic contract so we'll say contract implmentation a and we'll just give it a u 256 public value and then function set value U 256 new value public we'll say value equals new value and so this is going to be our implementation so now anytime somebody calls small proxy or small proxy contract it's going to delegate call it over to our implementation a and then save the storage in our small proxy address so we're going to call our small proxy with the data to use this set value function selector so let's make it a little easier just to figure out how to get that data by creating a new helper function we do function get data to transact and we can get the data using the ai. encode with signature that we learned in an earlier lesson so function get data to transact we'll pass it to you and 256 number to update so we'll give this the number we want to call a new value we'll have this be a public pure that's going to return a byes memory and we'll just say return ai. encode with signature set value U 256 comma number to update so you'll remember this from our call anything section and if you don't remember how to do that remember to refer back to our nft section to learn how to call anything and use ABI do encode ai. encode with it signature and call anything with its raw bytes we're going to get the data to transact and we know that when we call implementation a from our small proxy we're going to update our small proxy storage so we'll create a little function in solidity just to read our storage in small proxy so we're going to say function read storage this will just be a public view we'll do returns returns un 256 value at storage slot Z and we are going to use a little bit of assembly here since we are doing all this lowlevel stuff and we're going to call the SL load op code to read the value at storage slot Z we'll say value at storage slot Z and we're going to set it and then in assembly this is how we set things we're going to set it equal to SL load of storage slot 0o and then it will return this value here so we're reading directly from Storage oops and then we need a little parentheses here sorry so now so let's go ahead and deploy our small proxy and let's deploy our implementation a now our small proxy has a function called set implementation so we're saying okay anytime we call this proxy contract we're going to delegate call the function over to here so we're going to grab implementations A's address paste it into set implementation 777 so this is the data of set value un 256 with that number to update and code it in it so if we call our small proxy with this data our proxy contract is going to go oh okay this is a function uh I don't I don't see that function here we're going to call our fallback right which again is coming from open Zepp and our fallback is going to do this delegate which is this lowle stuff but it's basically just doing a delegate call we're going to call our fallback function and then we're going to get the function in the implementation a we're going to borrow this function and we're going to use it on our on ourself so if I copy this the implementation has been set to being this address down here so all the logic is going to be down here so when I go ahead and I grab this I paste it into call data and I hit transact looks like it went successfully went through if I read storage now we see that it is indeed 777 which is incredibly exciting now this is incredibly beneficial because now let's say we want to go and update our code right we don't like contract implementation anymore so let's go ahead copy contract implementation a and we'll make a new one called implementation B now let's say whenever somebody calls set value we do value equals new Value Plus 1 or plus two let's go ahead let's save this let's compile this and let's deploy implementation B we'll grab implementation B's contract address we'll call it on set implementation in our proxy and essentially we have now upgraded from implementation a to implementation B now if we use this same data here we're still going to call set value with 777 but instead we're now delegate calling to implementation b instead of implementation a so if I call if I put this data into the lowle call data and I hit transact it looks like it went through now I read storage and now is 779 since doing value equals new value + 2 so this is a minimalistic example of how upgrading actually works now this is incredibly beneficial because we can always just tell people hey make all your function calls to small proxy and you'll be good to go but like I said before this all also means that the developers of this protocol can essentially change the underlying logic at any time this is why it is so important to be sure to read contracts and check to see who has the developer keys and if a contract can be updated if a contract can be updated and a single person can update it well guess what you have a single centralized point of failure and technically the contract isn't even decentralized now something else I was talking about in the video is function clashes function selector clashes right now whenever we call set implementation the proxy function set implementation gets called because we don't trigger the fallback because we can see the function is here however if I have a function called set implementation in our implementation this one can never be called whenever we send a function signature of set implementation it's always going to call the one on the proxy this is where the transparent proxy that we're going to be working with can help us out here and the up Universal upgradeable proxy can help us too and I'm not going to go too much deeper into these now but we've left some link in the GitHub repository to teach you more about these selector clashes and how those two proxy patterns that I just mentioned the transparent and Universal upgradable can get around these if you're confused by anything in here go into this discussions thread and make a new discussion about proxies make a new discussion about the assembly about the Ule set implementation this is a great time to connect with other people taking the course and ask questions here CU I know that this is a really Advanced section and requires you having gone through a lot of those subl lessons that we've gone before and if it takes you a couple times of playing around with solidity and playing around with remix I definitely recommend you do so this is a section where seeing really is believing and I want you to jump into remix and I want you to test this and I want you to play around with this and see what you can break and Fiddle with all right so now that we've learned all about this delegate call function and what it can do and the power of it let's actually put it to use let's actually build an upgradeable contract example so we can really see this power so let's go ahead and let's start doing this of course all the code that we're going to be going over with is available in the GitHub repo associated with this course if you want to follow along so let's go ahead make a new directory boundary upgrades f23 let's code boundary upgrades f23 or file open folder you know the drill now I know in that video we talked a lot about this transparent proxy pattern versus the uup UPS we're actually going to be teaching The UU PS proxy in The UU PS proxy the upgrade is handled by the implementation and can eventually be removed and this is incredibly important especially if if we want to heed my warning I made at the beginning where we want to really do this as little as possible and this is kind of a crutch to get started and we've seen issues where if you have upgradeability and you have a centralized entity that can upgrade and change your contracts those are often exploited so the U UPS proxy allows us to eventually remove the upgradeability so that the code is truly a mutable and also U ups proxies are technically a little bit cheaper to deploy you can read more about about the differences between the two proxy types in the documentation for open Zeppelin and additionally if you go to the contract wizard in open Zeppelin most of these types in here have a upgradeability option with up apps that we could even open in remix and see exactly what some of these might look like so we're going to be going through that with our own example here so we're going to go ahead we're in our folder we're going to do Forge knit of course and we're going to go and delete these once again goodbye goodbye goodbye delete with the trash I held down command so I could select all three and let's create a very minimal contract that we're going to actually upgrade so we're going to say a box V1 soul and this is going to be what we're going to upgrade so in this box V1 we're going to do spdx license identifier MIT you know the drill fragma solidity 0.8 rate team with a little carrot here contract box V1 like this cool now so since we're using the U UPS proxy we're actually going to need to add all of the proxy upgradeability into this contract as well so we can actually borrow from open Zeppelin kind of like what we were seeing here because they have all of these contracts already created for us but let's actually just write out what our what we'd want our box to do first and then we'll go ahead do that so it will say a un 256 internal value or number a little bit less confusing we'll have a function get number public view or better yet external external view returns un 256 turn number all of this is something you all get because you did the stablecoin video which was a monster of a project version external your returns un 256 return one and that's it this is all our box is going to do now let's copy this box let's go to our source we'll create a box v2. Soul paste all that in here and let's change this a little bit let's have the version return two get number will still return number but let's add a function function set number un 256 number this be external no like this but so here's oh and this rename this to box V2 Okay cool so now we have our box V1 we're going to deploy box V1 and then at the contract address of box V1 we're going to upgrade it to box V2 now remember though if we upgraded it changed some storage VAR we would mess it up right so if you go to the open Zepp documentation let's actually reopen this back up in remix here we can see kind of what's going on here so this token example that they have they say it's initializable upgradeable ownable and uu PS upgradeable they say it's all this stuff so for us we're going to go ahead and we're going to install this open Zeppelin contracts upgradeable package and this is actually at a different open Zeppelin repo we look open Zeppelin contracts upgrade GitHub there's this open Zeppelin slopen Zeppelin contracts upgradable repository that we can use and this is the one that we're going to want to install so we're going to copy this that Forge install this this D- no- commit all right great we've installed it now we can start using these contracts upgradable code in here let's just go in here do a re mappings equals we'll say at open Zeppelin contracts upgrade a equals lib SL open Zeppelin and let's do a toggle word wrap Zeppelin contracts gradable SLC contracts hopefully that looks right let's go to lib opens up a contracts ofg gradable yep that looks right okay cool so now we can start using this so in this remix example it can be a little bit confusing because there's a lot of imports going on right so let's kind of break this down so the first thing that we're going to need is going to be this U UPS upgradable contract and I'm just going to copy this line feel free to copy this line as well or you know write it out yourself and I'm going to toggle the word wrap here of course we're going to do named Imports because we're good Engineers uh what did I mess up oh I don't need this versioning okay cool and if we control click into this or we command click into this or we just open this we can see exactly what is in this upgradable code here we have this uu PS upgradeable contract it's initializable it's some proxy stuff you know yada yada yada we scroll down down got some modifiers it has this function upgrade to address new implementation upgrade to and call and it has this Gap at the bottom so let's talk about these so this upgrade 2 function this is the function that gets called when we want to upgrade our box so we're going to say our box is u u ups upgradable and then it's going to say hey uh should be marked abstract because we don't have all of the functions defined in here and this contract is actually known as an abstract contract abstract contracts have some functions defined and some functions undefined and they expect their child classes to implement those functions so for example at the bottom here we have this authorized upgrade function which isn't defined so an abstract contact basically says hey you better Define this authorized upgrade function because I'm not going to do it you need to do this and this can be helpful for a lot reasons right for example let's say you want to make sure to not forget to add some function so this is something that we're going to need to Define these are how we're going to actually do the upgrades we see that this is you know obviously the function that we're going to have to Define so we can add authorization parameters in here such as who can actually do the authorization so if I toggle the word wrap we can see function that should revert when message. sender is not authorized to upgrade the contract so for example if you wanted your proxy to be owned by a dow you would update this to be ownable or only owner or something like that but then they call this upgrade to and call U UPS which if we control click into or we just go to where it's defined uh we toggle the word wrap here we can see this performs the implementation upgrade with Security checks for ups proxies and additional setup so if we scroll into here this is the code that's actually doing the upgrade and it's really low level right so we call this function set implementation which now routes all contract calls via delegate call to this new implementation address that we set and then it does a couple of checks in here and then it calls upgrade to and call which which calls upgrade two which calls set up implementation which mainly just sets the implementation slot which basically like I was saying before it says okay all contracts are going to be routed to this address now right but if we go all the way back all the way back that's kind of the long of what this upgrade to is going to do right so it's going to change where we route all of our delegate calls and then if we have any data we want to send it'll call this as well the data is obviously going to be none uh if you just call upgrade to anyways I'm getting kind of in the weeds here right this is the function that it has set up to to do the proxy stuff we showed before right this changes the implementation address so we obviously need this we also need to implement our own authorizer upgrade function so we can just go ahead and copy this and in here we'll paste it in here and for us uh we need to make this override instead of virtual I'm just going to leave it blank because I don't want any I don't really care I don't want any authorization stuff in here right but this is where I put like you know require or excuse me if you know message. sender does not equal owner you know revert right right but for us I don't really care so I'm just going to leave it blank right and so this is going to say anybody can upgrade this so this is why this is going to be the most important one right this U UPS upgradable is doing all that proxy upgrade stuff all right cool so what else now you'll also notice here at the bottom there's this Gap thing now you can read the docs here this empty reserve space is put in place to allow future versions to add new variables without shifting down storage in The Inheritance chain what what what what the heck what are you talking about storage gaps the reason these proxies work is that they point to the slot number instead of the name of variables so if I were to upgrade from box V one to box V 2 and I put in another other number here guess what if I did this upgrade whatever number was in box V one is now set to other number instead of number this is because proxy's point to storage slots they don't point to variable names they point to storage slots if we upgrade to V2 other number is now in storage slot zero whereas number was in storage slot zero over here right so what is the best practice to do is to have this Gap at the bottom so a u into 256 you can put really whatever number you want here which basically just says hey we're going to save 50 storage slots in storage for adding new variables in the future you could have this be you know 100 you know whatever whatever amount you want right and this is just so that in the future if you need to add more storage slots you don't collide with other places that storage is already being reserved so it's really important that there have this Gap especially for U UPS if this doesn't make sense definitely 100% be asking questions about it and you'll see a lot of people will ma even manually add their own gaps sometimes so sometimes you'll even see somebody go you know like Gap two or whatever they want right so that they have additional gaps whatever they want to do cool so this is why we need this now right like this we could ship this code and this would be upgradeable now of course box V2 is not upgradable um but box V one would be upgradeable so why is remix adding all this other stuff what is initializable well let's copy this and let's paste it in and you can also see all this weird initialized stuff what what what is going on with that well let's let's add this in and of course we're going to do a named proxy if you want to write this out yourself feel free uh excuse me we're going to remove this because we did not add the version in here uh initializable so what is this why is open Zeppelin telling me I got do I got to do this initializable thing and it's doing all this weird initialized stuff so let's go into initializable oh and if it doesn't let you do that let's open up our file explorer we'll look for initializable Doo and let's see let's read this so if you want to pause and you want to read this I'm even going to toggle the word wrap if you want to pause and you want to read this feel free to do that but the main thing we know is this piece here since proxy's contracts do not make use of a Constructor it's common to move Constructor logic to an external initializer function might be thinking wait wait wait wait what they don't use a Constructor remember storage is stored in the proxy not the implementation so we have proxy which will direct our calls to the implmentation but it's like borrowing the implementation functions right so all the storage is happening over here if the implementation has a Constructor and it sets number to one right the proxy will have number still set to zero cuz the when you deploy a contract The Constructor gets called from the implementation so proxy contracts or contracts that are meant to be used via proxy don't use the Constructor so what you need to do is then with a proxy you need to First you need to deploy implementation then you need to call some initializer function now the initializer function is going to be essentially your Constructor except for it's going to be called on the proxy so that's kind of the difference that doesn't make sense please ask questions about it because it's really important so Constructors are not used in proxy contracts so what a lot of upgradable contracts do is they first they call this disable initializers function in Constructors like you see here and I'm actually going to copy this paste it into my box V1 like this and then often you'll see this comment I'm going to paste this over here because sometimes different linters will say hey you're using a Constructor in a upgradeable contract you shouldn't do that so we just say hey like let it happen right what this disable initializers function does is it says hey don't let any initialization happen so if we go see this we say require that you're not initializing right you can't call any initializer functions so you could just as easily just just do this right they're kind of the same but this is much more for both right this is making sure hey don't do any initializers Constructor don't do anything so this and this are almost the same but this is more verbose as you know verbose is better but let's say we do want a Constructor what we would do is we' add an initializer so we do something like function initialize public initializer initi initi Aller and of course we'd say our boxy one is initializable public initializer like this and we would add whatever we want to initialize and then what we're going to do is we're going to deploy the contract and then we're going to have the proxy immediately call our initialized function instead of doing this Constructor instead of the implementation having the storage we want the proxy to have the storage typically you'll see initializer functions have two underscores like this so if we want our box V1 to have an owner right we can't set storage we can't do like owner equals message. sender in the Constructor like we normally do with a ownable contract instead we need to put that in the initializer function so what a lot of people will do is they'll add double uncore like ownable uncore in it like let's say we did want this to be upgrade uh ownable and actually let's go ahead and add that right now we're going to add this ownable upgradable I'm going to paste it in remove that ownable from like this comma I know I kind of was quick but I uh I know you all are Advanced enough to kind of know what I just did here I refactored this a little bit so that's a named import remove the version and now we're doing this ownable upgradeable instead of ownable I'll explain what that means in a second oh and this actually goes here a note if you see this linearization of inheritance graph impossible this means that we're trying to inherit stuff in the wrong order so we'll just do this is that the right order no that's still the wrong order that the right order cool that's the right order okay so what you'll see is these upgradeable initializable functions will be prepended with double underscores right and so what this is doing is it sets the owner it's setting the owner to message. sender and if I command click into this or command click into this we look up ownable in it we see it does this ownable and it Unchained all it's doing is calling transfer ownership right that's it this is essentially the same as setting owner equals message. sender right but we're just prepending with the double underscore to say hey this is an initializer function treated as such right it should only be called in this initialized section additionally most of the time you'll see this initializer function which doesn't do anything but it's best practice to have this in here to say hey this is a upps upgradable contract we're going to treat it as such okay so you'll see this in here a lot too but I know I kind of went through this a little bit quickly but let's just do a quick recap of what we learned we can't use Constructors with our proxies a Constructor adds storage to the implementation and if we have a proxy pointing to an implementation the implementation would have the storage of where the owner is and we need the proxy to have the storage of where the owner is so we need to call initialize through the proxy not through the implementation the initializer function is essentially a Constructor for proxies you can almost think of it like that we want to preen them with this double underscore to know that they're initializers and we don't want any initializers to run in the Constructor and we only want them to run once you'll also see this initializer modifier which basically just says hey you can only initialize one time right a contract can only be initialized once otherwise it'll erir great and that's pretty much going to be our box so now we made this ownable so since this is ownable down here in our authorized upgrade we could add an only owner modifier in here so that only the owner could upgrade it if we wanted to but we're not going to add that but I wanted to add this ownable init here just to show you hey like so this is what you do instead of working with Constructors so that's our box V one let's fix our box V 2 so our box V 2 we're going to do pretty much the same thing so we're going to grab all these paste it in here I'm going to toggle the word wrap we're going to make this initializable uh ownable upgradeable and U UPS upgradeable is like this we're going to need to add authorized upgrade which we're going to keep blank but if you want to play with this you can obviously implement this we're going to want to add a Constructor and an initializer so we're going to copy both of these and just paste it right in here a Constructor which disables Constructors and then an initializer which is going to be really what we want and that's pretty much it that's the only changes that we need to make now we can make this even smaller right we could say okay cool we don't care about upgrades we don't care about initializing and we just say goodbye this doesn't need initializer this doesn't need any of that stuff and we could even delete all this if we wanted and now it's just UPS upgradeable right without any initializer and without any Constructors and we could do the same thing with box view one but I just wanted to demo what it look would look like if you did want a Constructor but now that we've done all this work let's actually show you this in action so we're going to deploy box V1 we're going to get an address we're going to use that proxy address to make sure that these functions work we're going to then deploy box V2 we're going to point our proxy to box V2 which will essentially mean we upgraded our contract and it's all going to be from the same address so let's do this we're going to make a little two scripts we're going to make one called deploy box. s.o and a new one called up upgrade box. s.o so we're going to deploy the box and then we're going to upgrade it so let's deploy spdx you know the drill license ragma solidity 0.818 contract deploy box is script import script from forg STD script. Soul we're going to need to imple import box V1 from docbox V1 Soul function run external external returns I'm going to I'm going to return address and you'll see why in a bit returns address address proxy equals deploy box turn proxy and I'm going to create a deploy box function function deploy box so this is a little bit different this will be a public returns address and what we're going to do is say box V1 one box equals new box B1 this is going to be our what our implementation this is going to be our logic right this is where our proxy is going to point to delegate call right to borrow those functions now we're going to need to get a proxy on top of this the proxy that we're going to use is the ERC 1967 proxy and we can learn more about this proxy in the open Zeppelin documentation we can learn more about this uh the EIP for ERC 1976 whatever you want to do but it's going to be this proxy that we're going to use to point to our implementation right to point to our box V1 which has all this upgradeable logic in it so we're going to import that we're going to import ERC 1967 proxy from and this is actually just a regular opens up in contract so we're going to do Forge install open Zeppelin slop Zeppelin contracts this just a regular one contracts oops uh D- no- commit we're going to go to our boundary. toml and this is a remapping comma at open Zeppelin contracts equals lib slopen Zeppelin uh opens up Dash contracts I think that's what it is right lib opens up L contracts and opens up on contracts upgradeable okay opens up on contracts SLC contracts like this and Port this from at open Zeppelin contracts proxy ERC 1967 uh like this this is the proxy type we're using now we're going to say ERC 1967 proxy equals new erc1 1967 proxy and if we command click onto this or control click or just look at this this does have a Constructor we pass in the logic and the data so we basically say hey proxy this address is going to be the implementation the logic that you're going to use and then any data you want to pass to the initializer right if we look at upgrade two and call we call upgrade two and then if there's any initializers call that afterwards right uh we're not going to have any initializer stuff so we're not going to do that but we're just going to say address box because we just deployed this box no data this is where like I said this is where we put the initial address stuff we wanted but then we're just going to say return address proxy so cool and let's just make sure stuff is working Forge build or at least we're going to make sure code is compiling and source file that's not specified required compile version that's cuz we haven't implemented that that's fine cool this looks good and we're going to write some tests to show you this actually working in a little bit but cool so we have a deploy box let's actually write an upgrade box script now and then we'll write a test to show both of them spdx lense identifier MIT pragma solidity 0.88 contract upgrade box is script import script from Forge STD script. Soul script scripts cool function run external returns address oops I'm going to have this external oops I'm going to have this use the most recently deployed box so to do that we're going to actually install Forge install chain Excel or- boundary devops D- no- commit like I said there might be a better devops tool than this you can find the recommended devops tool the GitHub repo associated with this recommended tool is going to be Foundry devops so great so that's what we're going to use I've worked with this one before so we're going to say address most recently deployed equals devops tools. get most recently deployed going me de meant and this is where we're going to get the ERC 1976 proxy let me oops toggle the word rep here move this down on block. chain ID oh let's import that as well import from oh oh and I got to go to the founder. too do a little bit from lib Foundry devops slsrc Dev Ops tools. s looks good get most recently I spelled that wrong get most recent deployment so we're going to get the most recently deployed proxy first and you'll see why in a second and first we're going to actually deploy box V2 so we're going to import box V2 from SRC boox v2. soul oops. soul so we're going to do a little vm. start broadcast did we do that in box deploy box oh we should do that here back in the deploy box we're going to do vm. start broadcast and then a stop broadcast that okay bm. star broadcast in the upgrade box we're going to say box V 2 new box equals new box V2 bm. stop broadcast and then we're going to say address proxy equals upgrade box and I'm modularizing this for our test cases but we're going to say we're going to create a new function called upgrade box we're going to pass in the proxy address right this is the proxy address and then the address of our new box and then we're going to say return proxy so we're going to create this function upgrade box which has our previous proxy and then the address of our new box for us to do so we're going to say function upgrade box address proxy address uh address new box be a public returns address do little vm. start broadcast so okay so we're going to call upgrade box we have the proxy address and we want to call upgrade on this right since this is just an address we can't call upgrade on an address we're going to need to call upgrade on using the ABI of box V1 right so let's import that as well import box V1 from docbox V1 do we're going to say box V1 proxy equals box V1 of the proxy address like this and what we're going to do is now that we've given our proxy address box V1 ABI we can now just call proxy upgrade 2 since box V one is U UPS upgradeable means it has access to this function address new box this we're going to upgrade it and we're just do vm. stop broadcast like this we could also optionally wrap this in box V2 or we could you know do a direct function call whatever we want to do now we'll just return address proxy and that's it right so what is this doing when we actually upgrade well we deploy Box 2 implementation we are calling this upgrade box function and what we're doing is all we're doing is we're saying hey point the proxy to this new place that's it we're saying proxy contract now points to this new address that's it don't believe me all right let's write a test so new file and we're going to write some crappy tests here we're just going to do the whole Suite just to show you the power deploy and upgrade test. T.O you know the drill spdx license identifier MIT contract deploy and upgrade test is test import test from board sd/ test. Soul fragma solidity 0.818 we got to do a whole bunch more Imports we're going to need to import deploy box from do script deoy box. s. so import upgrade box you know this is what we're actually testing from. script upgrade box. s.o reading to import box V1 from yep thank you GitHub co-pilot and box V2 we're probably going to need to import more stuff but it's fine function setup what do we want to set up here well let's get a deploy box public deployer upgrade box public upgrader we'll do an address public owner equals make addr owner and we're going to say deployer equals new deploy box upgrader upgrader equals new upgrade box okay cool and we probably should write a whole bunch of test but for this video I'm just going to write one say box V one public box V one and we'll say box V1 equals deployer do run we're going to have to wrap box V1 like this Co so we have our box V1 it gets deployed our deployer run is a deploy box run Returns the address of the proxy not the address of the Box V1 right Returns the address of the proxy not the Box V1 so we can even call this to make it more clear box V1 public proxy since this is actually a proxy address actually let's do this even better address public proxy and this is why before we were working with addresses because it can be kind of confusing to know what it is the proxy right the the proxy and it right now points to box V1 cool hopefully that's more clear so now we'll do a function test upgrades like this and we'll just test the whole darn system so we have the box we have the proxy address pointing to box V1 now in our upgrade box in our run we went ahead and did all this but for now let's just use this upgrade box functionality because so we can so I can show you a little bit more granularly what's actually happening right so test upgrade let's let's deploy our own box V2 we do it in run we could 100% do it in run but I want to do it myself so I'm going to say box V2 equals box V2 or Box 2 equals new box V2 vm. prank box V2 box two now I'm going to say address proxy equals upgrader do upgrade box proxy which is just an address address of box box too so our upgrade box upgrade box here all it's doing is saying okay cool get the proxy for box V1 and now point it to V2 so we're calling that in our test here and now we could do unit 256 expected value equals two and we could say assert equal oh actually we don't we shouldn't even set this let's not even set this right so this address is going to be the same we're never resetting this address we're being very clear about that boom proxy deployed here boom we're never even we never change the address so it's always going to be this address now we can do though is we can Sayer equal expected value is box V2 on the proxy address. verion if this works this means that on the proxy address which originally pointed to box V1 it's now pointing to box V2 we can also do box V2 proxy dot set value or what do we call it box V2 set number set number number we say like seven or something right and we could say assert equal 7A Bo comma box V2 roxy. getet number like this and we could even add another function test proxy starts as box B1 right public we could say vm. expect revert with calling this function because set number doesn't exist on box V1 so we try calling set number on the proxy it should fail so let's run these one at a time Forge test DM this should indeed revert great and then let's test this and this should indeed upgrade Forge test DM test upgrades oh we failed let's get some granular detail here- VB left is seven right is zero set number get number oops we forgot to actually add set number in here so let's do number equals uncore number whoops now let's run that test and boom it passes we have successfully upgraded our box this is very exciting so let wrap this up I know we went through this really quickly I want you to ask a ton of questions about this process ton of questions about this ask them in the discussion ask them on Twitter ask them to your buddies whatever you want to do we just learned about upgrades like I said I highly recommend you do not default to this and you do not let protocols that have upgradeable smart contracts keep this centralization Vector because it is if you have an upgrade able smart contract that means that a group could change the logic of that code at some point or be coerced to change the logic Etc but this is an incredibly powerful primitive to know about especially delegate call we're almost done push this up to GitHub add this to your portfolio take a break congratulations I'm going to go ahead and deploy this to a test it now just to show you what it will look like on ether scan feel free to just watch sit back relax you've done a ton of amazing work to make my life easier I'm going to borrow a make file and just kind of tweak it let's change let's just delete all this stuff deploy it's going to be deploy box deoy box upgrade P script upgrade box upgrade box make deploy args equal Das Das Network aoia all right so I ran the deploy we deployed two contracts let's grab this one first poia ether scan me show you what this looks like looks like this one didn't quite verify correctly I could go ahead and manually verify it if I wanted but let's look at the second one looks like neither one of these actually verified correctly but that's fine I can go to my broadcast see which one's which we can go to both these runs let's see the first one okay we did create box and so this is going to be the address of box V1 so I copy this paste it in here I can go ahead and verify this manually later but I know that this is my box view one we'll go back to broadcast click this one scroll down uh this one doesn't have a contract name but I know that this one is going to be my proxy address so I go to your browser let's open keep them both up past it in here this one didn't get verified correctly either but that's okay so this one's our box this one's our proxy and this is the one that's more important right this proxy is pointing to this implementation okay now we're going to call our upgrade we just doing make deploy make upgrade like this oh and I needl since I'm using Foundry devops I need ffi equals true remember only do that if you are confident about what you're running and do make upgrade so this actually is a bit of a bug with this script that I just found out I do need to update my run latest to ERC 1967 proxy I either need to upgrade my script to look for null or I need to upgrade Foundry to add this for the proxy name so I'm just going to manually add this in we're going to hit clear we're going to rerun it looks like that is a bit of a bug sorry about that but now that it knows that this is the ERC 1967 proxy we're actually running this script now to upgrade the box and the first thing that we're going to do is we're going to deploy our box V2 which for some reason is actually verifying looks like something was just wrong with the first time I did it but all good if I paste this in we now have a box V2 being created and it looks like it's trying to verify right now oh and it looks like this one actually did verify so if we refresh this one so it looks like our box V2 is here we place this in it looks like this one did actually verify which is great box V2 now if we go back to our proxy we hit refresh we can see we called an upgrade two on this contract now whenever we call functions on this it'll actually point to box V2 right so we can even grab the contract address we'll use a little cast send paste this in here we'll call get number like this or actually excuse me cast call cast call and of course D- RPC URL seoa RPC URL this we can see that it starts off at zero that number starts off as zero then we can call well we can do send instead set number takes a u into 256 we'll set the number to 77 RPC url-- private key private key remember you're going to need to do source. andb to do this we'll send a transaction to actually update update this and we're calling the proxy right we're not calling this box V2 address we're calling it right on the proxy then if I go up up and we do call again we're now going to get 4D for the binary and if we do cast d-2 base paste DEC for decimal we convert this hex to decimal and we see we get 77 back so we have successfully deployed and worked with a proxy this is so awesome take a break we we got two more you're so close you're almost done we got two more scrolling all the way down Foundry governance another quick one and then introduction to security and then I'm going to send you on your way to make the future of Finance the future of smart contracts better place you're so close take a break get ice cream post on Twitter I will see you soon all right hi baby Patrick all right here you go here is your 12w seed phrase now you're going to need that in order to generate your private key which you're going going to use to sign all your transactions uh now just remember if you lose your seed phrase or you lose your private key you won't be able to send any more transactions ever and if you accidentally expose or leak your key or seed phrase whoever gets it will be able to spend all of your money what this is how a lot of people feel when trying to get their friends into crypto they tell them that they have to follow all these very difficult rules and if they break one of those rules they're going to get rug pulled for all their money so the wallet user experience for getting into crypto isn't great private keys can be very difficult to handle anything you want to do costs gas preserving privacy from your wallet can be difficult sending multiple transactions at once rely on you interacting with a middleman smart contract there are a lot of issues with current private key and wallet management and account abstraction is here to try to help aid those account abstraction can be boiled down to one single thing in a traditional transaction you need to use your private key to sign the data to send the transaction with account exraction you can sign the data with anything to reiterate normally we validate transactions by signing them with our private key imagine being able to sign a transaction with your Google account with your GitHub account a transaction can only go through if three of your buddies give you a thumbs up you can only sign a transaction during the day you can't surpass some type of spending limit so one more time just to drill it in historically private key equals wallet with account exraction whatever the hell you want is a wallet and with this whatever the hell you want with this customization this means that we can additionally have other people pay for our transactions right now if you want to do anything on chain anything at all you always need to have at least a tiny bit of gas and sometimes depending on the chain that you're working on getting that tiny bit of gas can be a huge pain in the butt but account abstraction can help solve this so if I really want to give baby Patrick his first wallet uh gooo Gaga I can actually code in some parental controls where he can create all the transactions and then I have to approve them and all of his super likes on skibbidy toilet I will defin be approving so this all sounds fine and dandy but how does it actually work now getting into this is where this gets a bit complicated because there are two places where account abstraction exists as of March 1st 2023 the first official account abstraction smart contract was deployed to the ethereum mainnet called the entrypoint doou and you have to interact with this smart contract in order to do this account abstraction thing and other chains like zync have this natively baked in so let's first learn how this works with ethereum which doesn't have it natively baked in and then we'll look at how it works with sync which has what's called native account abstraction in a traditional ethereum transaction you take your metamask or your rabby or whatever wall you're using you sign a bunch of data you spend some gas and you send this onchain and the ethereum node will be the one that will add this transaction to a block in the blockchain right this is pretty well known whenever your metamask pops up any of these transactions in here are you sending a bunch of data that you signed with your metamask your metamask did the signing send it to an ethereum node and it adds to a block but as we've been saying private private keys are really sucky so how can we have an account without having to deal with private keys well you still kind of do have to deal with a private key and on etherium the first thing you have to do is you have to deploy a smart contract that defines what is the thing that can sign transactions so you have to deploy some type of smart contract first to the blockchain whereas previously only private Keys could sign transactions but you could say all of my friends have to sign the transaction with their private keys or the Friends cast has to you could use something like a Google gole session key to be the one to sign transactions if you can code it you can build it so this smart contract will be your new wallet and you will have a smart contract wallet so now you might be asking okay cool but how do I like send a transaction through my smart contract wallet that is deployed will it like pop up in metamask for me well this is where it gets a little bit more complicated so now just remember traditionally you use your mamass you use your private key to sign some data and then you send it to an ethereum node and now the main difference is you are no longer sending your signed transaction your signed data to an ethereum node you're going to send this someplace else now now with account abstraction you'll sign your data with whatever you use to sign it could be Google could be your friends whatever and you're going to send something what's called a user operation to an ALT mempool so according to ERC 4337 which is the eipc for this you'll actually send this thing called a user operation which has all this addition add transaction information and you're not going to send this to the blockchain you're instead going to send this to something called an ultimate pool and this is still going to be all offchain this Altman pool is basically just any group of nodes that are facilitating these user operations so this is why you actually don't have to spend any gas when you sign and send this transaction because you're actually not sending it to an ethereum node so there is a chance that you're not even going to be making transactions in your metamask when you send to this alt mol for at least on ethereum working with these alt men pools these account abstraction accounts the wallet ux is going to have to become a little bit more clever to deal with this now these alt men pools they are going to be the ones to actually pay some gas because what they're going to do is they're going to take your user operation they're going to validate it themselves they're going to make sure everything looks good and then they are going to be the ones to actually send your sign transaction on chain so it's the alt mempool nodes that are going to be sending the transaction and doing the traditional ethereum transaction so in ethereum account abstraction or ERC 4337 is just a framework that everyone's agreed upon for sending these user operations so these alt mempool nodes are going to be the ones to send this transaction and they're going to send it to this thing called entrypoint doou a group called eth infantism won a grant from the ethereum foundation to be the one to create and deploy this contract it's this team that actually has deployed this entry point v07 on chain to ethereum optimism Arbitron polygon blah blah blah and so it's this address it's this smart contract that handles every single account abstraction user operations sent all of these alt mempo nodes calling this contract call this function called handle Ops where they pass all the data associated with a user operation which includes pointing to your smart contract account that you deployed so these alt men pool nodes are going to deploy your contract for you it's going to always be routed through this entrypoint doou which is going to do something validation and then it's going to be routed to your contract your smart contract account which is where everything will be directed from so when you you know work with an app when you send a transaction to something like a your account will be the message. sender or the from account here and it'll go through all the logic that your account set up so for example if you set it up so that only Google could sign Keys If Google didn't sign the key this whole transaction here sent from the alt men pool nodes would revert and then of course once everything's included your transaction will be added to the blocks blockchain now there's a couple things here there's a couple of things called add-ons one of them is a signature aggregator this is where it Aggregates this is an optional add-on to account abstraction where this entry point will let you define a group of signatures that need to be aggregated this is where you can have like your friends be on your multisig and then there's also this thing called a pay Master which this is where it gets really cool where you can set up your codebase to have somebody else pay for the transactions so the alt mempool nodes of course will pay for the transaction to actually send it but then you can set up a contract called a pay Master which will just have the logic of saying hey so and so is actually going to pay for my transactions here and you defined all of this in your account you set it up as such now you might be thinking okay cool Patrick well I'm always going to do this if the alt mempool nodes are always going to pay for my gas well if you don't have a pay Master the alt mempool nodes will pay for your transaction but they will only pay for the transaction if one of these accounts on chain is going to pay for it so if you don't have a pay Master set set up it'll try to pull funds out of your account and that's how the whole system works here so simple in concept very convoluted in practice here now this process obviously involves a lot of different steps a lot of different moving Parts you have to send to these alt men pool nodes they are going to be the ones to send to the onchain entry point you have to customize your account and blah blah blah do all this stuff some chains have said you know what let's just do this natively ZK sync is one of these chains where they combine this process together let's look at how ZK sync does a count abstraction for ZK sync the process is going to look really similar you still have to deploy a smart contract that has all your rules codified but the main difference is that the alt mempool nodes are also the ZK sync nodes so we actually get to skip this step of having to send our transactions to this alt menol because the ZK sync nodes also work as alt mempool nodes the reason ZK sync can do this is because they have what's called default accounts for every single account every single metamask account every single account in ZK sync is technically a smart contract account that has very specific functions and behaviors that can be validated so anytime you interact with any address it will always assume it's a smart contract because that's just how they work so what I'm showing you here is their default account smart contract anytime when you load up ZK sync into your metamask and your addresses are automatically created they are a automatically connected to these default accounts and this is what the code of those addresses look like I've got a video coming out next where we're actually going to create some account abstraction accounts on both ethereum and ZK sync so you can see exactly what they look like and how they flow and how everything fits together so be sure to watch that as well if you want to learn how to actually code these things and hopefully we can save baby Patrick from having to deal with his private Keys himself thanks for watching and I'll see you next time all right y'all in this video we're going to be actually walking through building some minimal account abstraction accounts now we're actually going to be doing it two different ways we're going to be building one for ethereum and one for zync why because ethereum and zync do it slightly different for ethereum whenever you send a transaction via account abstraction you actually have to send it to this alt mempool for ZK sync there is no alt mempool you just send it via the normal meol you just have to specify your transaction as a type 113 if you want to follow along obviously the code here is going to be at cyphon minimal account abstraction right here you can follow along here and we're going to be creating two smart contracts one is going to be minimal account you can see this account right here very very minimal smart contract it does almost nothing interesting all it really does is it allows for either our private key to pay for the transactions or this smart contract itself to pay for transactions it's incredibly minimal we didn't add any interesting functionality in here but as we go along and build this we'll show where if you wanted to add additional customization for example maybe adding a pay master or a signature aggregator or some type of spending allowance or a Google session key whatever as we build this out it'll become clear where you can expand on this and build them yourself then additionally we also have in z K Sync here we're going to have our own custom ZK sync minimal account as well which is going to be slightly different and in doing this we're actually going to learn a ton about ZK sync as well because because the ZK sync ecosystem is actually very different than the way the ethereum ecosystem works because like I said you actually don't have to send your transactions to an alternate men poool you can just send them directly to the exact same men poool you always do and ZK Sync has it built into the actual layer 2 to handle all these trans actions so if you go to the readme associated with this and we scroll down to example deployments we can see here we have a ZK minimal account on ZK s aoia we have one on arbitrum as well if you want to go check these out you can check them out here but what's cool is we have two transactions here where we have the approve function where the from on ZK sync and this is what's really cool to me where the from is actually going to be this ZK sync minimal contract here now it's not actually verified because the contract verification for some of the parameters that we're going to be using doesn't work quite yet but what makes this so crazy is that you can't have a from be a smart contract in the ethereum ecosystem but in ZK sync you can so for our arbitrum example this is still really cool so the from is going to be one of these bundlers one of these alt mempool people this is going to be similar to what you would do on etherum our from is not going to be our smart contract wallet however we were able to interact with our smart contract wallet as if we were sending the transaction so all this did was submit an approval to the usdc token and during this transaction the message. sender was our smart contract wallet so very cool we're going to be building both of these and this is going to give you the power to create any type of flow that you want for your smart contracts if you want people to send transactions with a special session key that you create great you can create a smart contract that does it with this process if you want to create a super special multisig where you and a bunch of friends and a certain passcode have to be the ones to get together and send a transaction great this is how you're going to learn how to do that and you're going to learn how to do it for both ethereum and ZK sync which is going to be awesome so let's jump into it we are going to start building with ethereum first and then we're going to build with ZK sync so that we can really understand the differences and as we do ZK sync we're going to learn a ton so let's get froggy all right so here we are in our brand new blank vs code where we're going to create some account abstraction wallets you are going to learn a ton in this section and I'm incredibly excited for you to come along with us here this is probably going to be one of the more advanced projects that you make in your Learning Journey but let us begin so we want to just first make sure we are on Foundry so I'm going to do a quick found up make sure we're on the latest version of Foundry here get everything downloaded and then we're going to go ahead and do a little Forge init create our basic project here and great so we have this set up so let's go into our source oh let's actually go into Source script and test command click or control click let's delete all these and we're going to go ahead and create a brand new file actually no screw that we're going to create a new folder called ethereum and then we're going to create a new folder called ZK sync right and right in the read me here let's delete everything say about what are we going to do number one create an AA or account abstraction account on ethereum let's just say a basic a basic one right and then number two create a basic AA on ZK sync deploy and send a user op SL transaction through them so we were going to deploy these send a user operation or transaction through them and really see the whole process end to end note I'm not going to send an AA to ethereum but we will send an AA TX to ZK sync so we're actually just going to send our transaction directly to ethereum because kind of showing the account abstraction I don't think is that interesting but I do think it's interesting on ZK sync but we are going to still send a transaction through our smart contract wallet on ethereum it'll make sense in a minute I promise so let's go ahead let's get started working with ethereum here so in our ethereum folder we're going to create a minimal account. soul and this is where we're going to start you already know the drill we're going to set up a little pragma here MIT 0.8 let's do 24 contract minimal account like this so here's where we are and the first question is okay uh what what the hell do I need to do and this is where we can go over to ERC 4337 and figure out okay what are these smart contracts even supposed to look like right because we know we're supposed to be sending transactions to this alt mempool nodes and they probably need to be formatted a special way and then we need to send it to this entry point smart contract which will then send to our contract so there's probably some very specific functions that need to be called for this process to work correctly so let's figure out what those functions are so that our process can work correctly now if you go through the EIP itself you'll find what is needed for like a user operation and this is the data that needs to go to the alt M Pools you'll also find the entry point definition this is what we need to be worried about because this is when pass to onchain contracts the entry point contract and then to the account and pay Master a packed version of the above structure is used so so when you're sending data to an account abstraction alt mempool this is the data you need to send it but when you're sending data to either this entrypoint contract right because every single one of these user operations flows to this entrypoint contract you need to send all this data and again if we look at the entrypoint contract itself we go to write contract we know that this is where every single user operation is going through it takes Ops which is a tuple and a Ben beneficiary address here so we can even go to ether scan. death. net here just really see what this is so ether scan. death. net is a way to kind of see a smart contract right in the in your browser from ether scan we can look up function handle Ops like this and we can see the handle Ops it takes a packed user operation and a an address payable so so whenever we send our data to these alt mempool nodes we need to send it so that they can send this pack user operation stuff and where are they getting this pack user operation stuff well there's another smart contract called packed user operations. soul and there's this struct so we need to send all the data about our transaction in this packed user operation we need to pick the sender the nuts the initialized code call data all this other stuff and and the signature is really this customization piece where we can kind of Define how we want to Define signatures right because again countra ction you can sign anything with anything if you can code it you can build it so we need to figure out what this contract needs to look like at some point the entrypoint contract is going to call this contract and we need to set this up correctly now right in the EIP they talk about having this account contract interface the core interface required for an account to have is going to be this this function validate user operation where it takes this user operation takes the user operation hash and this missing account funds bit and then returns whether or not the user operation is valid back in this image here whenever these alt mempool nodes call this entry point this entry point is going to call your account and your account is going to say hey uh this transaction is valid or it's not valid if it's not valid it'll revert the alt men pool nodes won't be able to send the transaction and if it is valid then the alt menol nodes will be able to send the transaction for you so we need to make sure our validation is spotless and this is the function that will do it so we could 100% add this in here ourself but what I actually want to do is I want to import from this eth in infantism account abstraction project here I want to import this whole thing as a package that way we can use their interfaces and any other cool stuff that they've built we can use it in our codebase so we're going to go ahead and copy this and I'm going to be using version v07 for our codebase here so if you want to make sure to follow along that's the version that we are going to be using so back in our codebase we're going to do a little Forge install paste that in here and then do a little ATV 0.7.0 D- no- commit and now we're going to go ahead and install all of that as a library in our lib we have that account abstraction Chunk in here and they have an i account so we can actually just import that ourselves so we're going to say import I account they have that account interface as defined by the EIP here so we'll say I account from lib slac account abstraction SLC contracts SL interfaces account. so I already know where it is so so cool and then we'll say contract minimal account is I account uh so that we don't miss any stuff and if we command click or we go to this cont ract here we can see down at the bottom we have this function validate user op which is exactly what the ercp specified and then we have all the information here on what this function actually does if you want to pause and go through this feel free but we're going to explain it as we go along here so so we do know at some point we're going to need to add this so I'm just going to go ahead and pop it in here right now and then just make it like blank here to do this now we're going to need this packed user operation object as well so we're going to have to import that as well so I'm going to say import packed user operation from lib slac account abstraction slash contracts SL interfaces slacked user operation. Soul like this and if we command click on this or control click on this you can see we automatically get this struct pulled in here from this contract Well I this technically isn't even a contract this is just kind of like a floating struct here but in any case we get it into our codebase here and really at the end of the day this is the most important thing that we need to flesh out so let's actually just start with this right because this smart contract is going to be an account and this validate user operation is essentially the validate signature right what the entrypoint contract is going to send to us is this packed user operation this packed user operation is going to have like hey call usdc and set it to approve and here's the signature blah blah blah but also they're going to give us this user op hash or the user operation hash it's going to be the hash of the entire user operation and it can be used as the basis for a signature so in the user operation in this user op in this packed user operation they're going to have the signature and we need to figure out from the signature that they give us and the hash that they give us okay does it actually match and then missing a account funds is going to be missing funds on the accounts deposit in the entry point and this is the minimum amount to transfer to the sender basically to the entry point to be able to make this call so you can kind of think of this as like the fee basically and this is how these these alt mempool nodes are going to get paid after they send these transactions because they don't want to send it for free right so let's go ahead and start actually validating a user operation and let me just dive into this pack user operation for a second so the sender this is where it's going to be you know our minimal account they're going to say hey I want the sender to be our this minimal account this account abstraction account the NS should be like a number only used once you can almost think of it as like the sequence of transactions in the transaction we can ignore this for now this is uh if we set this the account contract will be created by this is like a Constructor the call data and this is where we put like the good stuff if you will this is where we say hey our minimal account should approve should approve usdc for 50 tokens or something should call the approved function or or transfer or like whatever this is like the actual meat of the transaction account gas limits is obviously gas limits pre verification gas this is some more uh gas stuff gas fees more gas these are all to handle the different gas fees basically pay and data so in this image here again so by default your account is going to have to pay the alt me pools for the funds right your smart contract they're need to be funds in here to pay for it however if you've set up a pay Master if you've customized somebody else to pay for your transactions this is the data that needs to be sent as such and obviously the signature and we're going to sign this this whole chunk of data up here and we're going to customize in our smart contract here what is a valid signature so cool hopefully that makes sense let's keep going let's actually start there so the first thing we're really going to care about is we're going to want to validate this signature in here so I'm actually going to create a custom function called _ validate signature and we're going to take this user operation and this user o operation hash so in our packed user operation they have this signature and we need to validate this signature against all of this let's really quickly figure out how we want signature validation to work this is again where your creativity can run free I'm going to be super lame in basic I'm just going to say a signature is valid valid if it's the contract owner that's it so if it's if it's the minimal account owner so that's it so whoever deployed this contract gets to be also gets to be the only one who sends transactions through it so it's a little bit lame because basically we're like all right metamask you need to call this smart contract wallet in order to call anything kind of like just adding an extra step but it'll show you what we intend here so we're going to say import ownable ownable from open Zeppelin and we should probably install some open open Zeppelin then shouldn't we so I'm going to go ahead I'm going to install open Zeppelin I'm going to do Forge install install open Zeppelin slopen Zepp Zeppelin contracts and I'm going to be using at 5.0.2 D- no- commit for this one so if you want to follow along with me also install 52 at oops excuse me it's v502 sorry and it looks like those are in and then I want to update my founder. real quick to do some remappings we're going to say remappings equals at open Zeppelin Zeppelin SLC contracts equals lib slop Zep Lin hyphen contracts like this and now we should be able to get at open open Zeppelin SL contracts slash access slown A.O like this now we can make our minimal account I account and ownable and since we're making this ownable we have to add a Constructor ownable ownable and the initial owner is going to be message. sender like this cool so now now that we have an owner of this smart contract we're going to set this up that whoever is the owner of this contract is going to be the one to validate the transactions and so actually I guess this is kind of cool because you can transfer ownership of this smart contract wallet to different wallets and so I I guess that is actually kind of cool that is a a bit of a novel feature so you can transfer ownership of a wallet without ever having to share your private key you know what actually I take it back that's cool as hell so um let's actually go ahead let's let's create a function called underscore validate signature and we're going to take the user operation and the user operation hash and we're going to use these to actually validate the signature because remember the user operation is going to be basically all the stuff the meat of like hey what's the transaction that we're trying to even send and then the user operation hash is going to be the hash of all this stuff so we want to make sure that this signature that they're sending us is a valid signature for the hash of all this stuff right so this owner this message sender this owner the owner of this contract should be the one to sign all of this populate that here and then we can check via the hash and then via the signature that stuff looks good um you'll understand what I mean in a second so so cool let's create the function so we'll say function unor validate signature and this is going to take the packed user operation I think we can keep it as call data bytes 32 use op hash this be internal internal View and we're going to have this actually return a un 256 validation data and you'll see why we need that in a little bit so this is the function that the entrypoint contract is going to be calling right validate user operation or validate user op and they're going to populate all this stuff here and this user op hash is going to be the EIP 91 version of the signed hash so this is technically in the wrong format and I'm not going to go on kind of a side tangent on what these EIP 191 hashes look like my co-instructor Kira is actually going to go over that a little bit in another video so hopefully by now you actually know what those are but they're going to send us this hash and we actually need to convert this hash back into just like a normal hash and open Zeppelin actually has a tool for us to do that as well so I'm going to import that import message # UTS from at open Zeppelin SL contracts SL utils SL cryptography slash message utils doou and if we look in here comment this out so I can look in here if we look in here there's a function called to e signed message hash and this is actually the function that we're going to be using it's going to return the kak 256 digest of an eap1 191 sign data with version 0 x45 or the personal sign message so uh I know there's a lot there but we need to basically format this hash into the correct format here so that we can do an ecdsa recover which is going to say which is going to give us who actually signed a hash so a little bit B of A pre-processing step if you will so we're going to say uh we're going to get the hash we're going to say bytes 32 eth signed message hash equals message UTS do2 e signed message hash user oph like this and now that we've converted this user operation hash into kind of this correct format now we can do this thing called an ecdsa recover so we're actually going to grab some tools for that as well import ecdsa from atop Zeppelin contracts SL uols SL cryptography SL ecdsa that's so I feel like most of the time in smart contract development we never have to deal with signatures or any of this stuff it's just when we're doing accounts that we do so we're going to be calling this function recover recover and what this does it does try recover does try recover gets the rsmv calls try recover again and we eventually call this pre-compile called EC recover which basically says okay this is some signed data here is the hash here is the signature who actually did the signing here and if it's valid the math will all check out and it will return a correct address otherwise it'll return address zero if it's wrong so now that we have this set up correctly and I know there's a whole bunch of math here don't worry kir is going to come out with a video that's going to be phenomenal if this none of this makes sense to you if you're watching this on YouTube link in the description if you're watching this on cyr updraft you should have just watched that so go back and watch it again if it doesn't make sense quite yet so we have this in the right format now now we're going to actually get the owner so we're going to call EC DSA do recover we're going to say eth sign message hash user op. signature so we're going to say okay with this signature and with this data in this hash who signed it right so we're going to say address signer equals this so ecdsa recover is going to return who actually did this signing and then all we have to do is we can say if signer does not equal the owner oops owner then we're going to return return Sig validation failed failed failed otherwise we're going to return Sig validation success so these this sig validation failed and this sig validation success failed is just one and success is zero but we don't like magic numbers so we're going to set it up like this we could 100% say you know failed in success up at the top but I kind of want to follow the same patterns as the account abstraction Playbook and so what we can actually do is they have these defined in a group of helper contracts so we're actually going to import those so we're going to import Sig validation failed and Sig validation success from lib slac account abstraction SL contracts SLC slh helpers doso like this if we look up this helpers do Soul contract we can see Sig validation failed equals one Sig validation success equals zero so we're just going to follow their standard so if it failed return it failed otherwise return successful here so all we're doing is we're saying given kind of this hash and the signature that they gave us let's verify the signature is the owner of this contract right is the owner because that's the only signature validation here but this is where we would say all right make sure that the Google session key is correct or make sure that seven of your friends are signing this or make sure that this or that or the other thing right so this is where we get to do a lot of that cool stuff there's additionally a signatures aggregator which we're not going to get into but we can do more customization with that so anyways so back in our validate user op we can now say un 256 validation data equals validate signature and if we go back to our I account let's grab this go back to our I account we have this return validation data this is the packed validation data structure basically the first 20 bytes is going to be zero for a valid signature or one to Mark signature failure and that's actually why we're following this process here uh there's also some really cool additional pieces you can have you can have valid until valid after for a Time range uh and you can do some other cool stuff here but for us we we just need to make sure we return the UN 256 validation data and for us our validation data oh we've already got it defined right here for us if it failed it's going to be one so we should fail and if it's going to be zero we pass hooray we're not quite done yet ideally we would also want to validate the nuns so in this packed user operation data there should be a nuns we could keep track of like the nuns in here so we could do like 256 hour NS equals z and we could have some validation on the nuns we could say hey it needs to be sequential 1 2 3 4 5 6 7 8 9 10 you need to do an order you need to do any order it's going to be in a mapping it's going to be this that you could do whatever we wanted here but the actual nuns uniqueness is managed by the entry point itself so we don't really have to do anything ourselves here so I'm just going to comment this out and not do anything but ideally you should do some type of nuns validation and then finally we also have to pay back money to the entry point so this missing account funds bit is basically going to be hey here's how much this transaction is going to cost and here's how much you need to pay back to whoever sent the transaction if you have a pay Master you can add on into this to have the pay Master actually do the payments however we're not going to deal with any of that so we need to have a little pay prund transaction or pray prund function where we actually pay the entrypoint contract the amount it's owed so we'll do a little function pay prund U6 missing account funds we'll have this be internal and we'll say if missing account funds um is greater or I guess not equal to zero or greater than zero then we'll do a classic you know bull success comma equals payable message. sender call Value missing account funds gas is going to be uh type uint 256 Max uh and then no data and then success so we're just going to say hey pay pay back the entry point contract I guess hypothetically we should hardcode this to be the entry point contract but it's the entry point job to verify the payment is good not us so we don't really need to care about this at all so we can even just just do this um but we're probably going to get yelled at by our linters so whatever so we just need to pay back the entry point contract and speaking of which we should really have this validate user op only be callable by the entry point but we'll add that in a second so at a high level though this is really all we need this is kind of all the functionality that we need this is kind of all the functionality that we need to have a valid account abstraction based account now at the moment anybody can validate user operations through this which isn't great uh and anybody can basically pay themselves which isn't great so we probably want to lock this down uh let's uh let's do that shall we but this is already awesome like you you've already essentially created your own minimalist minimalist account for ethereum or any evm chain that doesn't have built in account abstraction great work so let's keep going on this though so we're probably going to want to make sure that this validate user op is only callable by that entry point contract so right in our Constructor we'll do a little address entry point like this we'll create a state variable called called address iore entry point entry point make this address immutable private of course and then we'll just say I entry point equals entry point now I am going to go one step further though I'm going to go ahead and and import the I entry point interface and then that will actually tell us more about how the entry point actually works and it'll allow us to add some nice getter functions to this as well so I'm going to do a little import I entry point so the I entry point interface from lib SL account abstraction slash contracts SL interfaces SL I entry point. soul and if we look in here we can see kind of all the different functions the entrypoint interface the entrypoint contract can work with the biggest one being obviously handle Ops but they've also got some other nice ones like get nutts where I can get the actual NS or increment NS of a smart contract wallet so in any case I'm going to have instead of this being an address I'm going to have this be an i entry point and we're just going to wrap this like this we going to do some little headers Getters like that so that at the bottom I'll add this hand we'll do a little function get entry point uh looks like get up co-pilot got me here and if you don't have that headers tool definitely be sure to check out Transmissions 11 headers tool for making beautiful headers like this every single time so we'll do headers getter like that and uh cool and then we have a little State variable here looking good okay cool now that we have this we should probably create a modifier modifier called require from entry point like this and then we'll do if message. sender does not equal address iore entry point then we should revert with some new custom error I'm going to call it error minimal account not from entry point like this and so we will revert this and boom now that we have this modifier we can make our validate user operation exclusively from the entry point here cool all right great so now are we done with this this is looking really really good here are we done with this not quite we're actually just missing one final thing here so here's what's going to happen so remember this minimal account is going to pretend to be our EA right this is our account abstraction account this contract needs to be able to do stuff right now if we send a transaction we can go ahead and validate this right but again if we look at our if we look at our little image again we need to remember that our account well actually this isn't a great image let me go use the other image our account our account our middle account contract needs to be able to call and interact with all the daps that we're going to be working with here and as of right now this contract can validate user operations but it can't actually send any tractions itself as of right now it's not possible for this contract to actually send a transaction you know like to a for example so we actually need to give it the functionality to do that so the entry point right if we go back to this image the entry point is going to validate a transaction on our account and then it's going to pass the transaction information to our account and then our account will be the message. sender and actually send an interact with the DAP or whatever right so we need to add probably one of the more important functions here a function called execute and we'll add this up here I'm actually going to go ahead and make a couple headers headers internal functions like this going to put this like here headers external functions like that we're going to do oh I put that in the wrong spot whoops so external functions internal functions and then we probably would want to flesh out our npec but I'm not going to not going to do that right now Okay cool so we're going to need to add a new external function called execute and this is going to be the function that whenever we send a user operation to the entry point we're going to say hey you're going to need to call that execute function on our contract to call the DAP so little bit confusing from our end as develop ERS but this will make the lives of the people who are using these account abstraction accounts much much easier so we're going to make this execute function and we probably want to add the things in here that are needed to execute a function right so we're going to need an address Des for the destination a un 256 value if they want to send in eth and then a bytes call data uh function data or fun data or just yeah function data where this is going to be the ABI encoded fun function data right and this will be external and we could have this as exclusively requir from entry point where the only the entry point can call this and that would allow this setup to work great where entry point calls our account and then our account calls adap but this would mean that our metamask has to go through kind of this long account abstraction process every single time and maybe it make sense for them just to call straight from their metamask directly to the account if they want so we're actually going to make an an additional modifier here called modifier require require from entry point or owner where the owner of this minimal account can also call our smart C account or it can be the entry point right so either one we're happy for both ways and the reason we're happy for both ways is because if the owner is calling then that's obviously proof that the correct person is actually calling this however if the entry point is calling this right it's when the entry point the entry point is going to call validate user operation and all the signatures are going to have to be validated here so cool so require from entry point or owner this will be our modifier we'll say if the message. sender does not equal address iore entrypoint and message. sender does not equal owner then we're going to revert minimal Minal account uncore not from entry point or owner like this little underscore here and then we'll create this new error error paste that in here cool and then and then I just kind of want to be a little bit more explicit here so I'm going to do some more headers headers errors cuz I love me a good nice clean code base we'll do headers State variables right and state variables could be storage or not storage we'll do header headers modifiers this post that in there modifier modifier and then headers functions and just paste that here kick it off with the Constructor external functions internal functions Getters okay cool I love me some clean headers the code base is starting to look cleaner cleaner obviously we'd want to add some gats back in here to make this look even cleaner but oh the headers just make it look so nice okay beautiful code is good code friends okay so now we have this execute function and we would definitely want to add some netpc onto this but I'm going to skip it for now um we would definitely want to add some netpc onto this but all we're going to do is just a basic low-level call for this execute function so we're going to in here we're going to say okay A little bull success comma bytes memory result equals des. call Value will be value and then the function data will be here we'll say if not success then we can go ahead and do a little revert here and then we'll do a little revert minimal account just say call failed we'll even pass the result it's part of the failure reason that means way back up here we'll do a little error and we count called failed bytes in here so so we'll actually revert with whatever the return data was here and that's looking pretty good all right and then the last and final thing here we need to do is we need to add a receive function external payable because this contract needs to be able to accept funds in order to pay for transactions right because again we don't have a pay master so whenever we send whenever the alt mempool sends a transaction it's going to pull the funds from here which we pay them in our where is it in the pre pay prund down here so our smart contract needs to be able to accept funds first of all so now people can directly call through this alt men pool to the entry point to our smart contract or they can just call it directly into our account if they're the private key owner of this okay cool and with just this we can actually go ahead and write some scripts to test this deploy this and have this be our minimal account awesome it's incredibly exciting let's keep going so now as many of you know let's go ahead and write some deploy scripts here we'll call deploy minimal. s.o we're probably going to need a a helper config s.o because the oops this should not be a folder delete that folder change it to a new file we're going to need to helper config because the entry point contract is going to be different on different chains so we're going to need to interact with that contract here and then additionally we're going to create a send packed user op. s.o and this is going to kind of be the Pinnacle of what we're looking to do here this send packed user op. s.o so and if everything works here this should also work marvelously yes yes okay cool and it's in US writing this where actually the blunt of our work is going to be because we're going to have to understand how all the signing and the creating of the data works and this is really where the complicated nature of this kind of comes into play so but let's go ahead and let's learn how to deploy this real quick the deploying is pretty easy so we'll do a little pragma here MIT 0.8 I think we're using 24 here and to get this going this is going to be a script so we're going to do import Port script from Forge STDs script. so contract deploy minimal is script like this we have to import our minimal account from SC ethereum SL minimal account that's all oh is that wrong do a little Forge build to make sure everything works and it looks like everything isn't working. toml open Zepp Zeppelin contracts equals lib opens up on contracts slash contracts let's try that okay there we go there some other issues here that's not found import minimal account oops contract minimal account what's it m about D Forge build now okay Min imal account okay cool and those just don't have a compiler version okay great so now that we have those we're going to of course need to make a function run and we're probably going to need to make a function deploy minimal account public that we're going to call in run so for our for our minimal account all we need is an entry point and we should definitely do that in a helper config so let's go to our helper config here let's get this set up little little pragma here MIT 0.824 contract helper config is script like this which means we're going to have to import script from Forge STD script script so like this we're going to create a little error helper config uncore uncore invalid chain ID I should probably just turn this into a package huh this helper config and then you in The Foundry devops tool maybe but we're going to do a little struct Network config this is going to have an address entry point like so then we'll do where are we going to deploy this so we'll say un 256 constant eth sepolia Oria eth sepolia chain ID equals 111 55111 I think EO and then we'll do un 256 constant constant CK sync set polia chain ID equals 300 like so I'm just going to paste this here for now so don't forget it we'll create a little Network config public local network config yeah I should definitely turn this into a package sorry I haven't turned this into a package yet Y and then we'll do a mapping un 256 chain ID to the network config public network configs I'll do a little construct Constructor network configs of eth poia chain ID is going to equal get eth sepolia config and let's go ahead and create that function function get esoa config public pure returns Network fig memory like this and we'll say return Network config entry point it's going to be this address here a lot of boilerplate stuff we get to do and I'm just going to copy paste this for zync get ZK sync p a config for ZK sync since it has native account abstraction we're going to do address zero which again I haven't taught us about that yet so you can kind of just ignore that for now uh but we also want to do function function get or create Anvil eth config public returns Network config memory memory like this we're going to say if local network config entrypoint do not equal address zero then return local network config like this or we'll probably have to come with something a little bit more clever because this is also going to return zero uh otherwise we're going to have to deploy a mock entry point contract and we'll do that a little bit later so so let's just add another function function get config by Chain ID un 256 chain ID public view returns Network config memory if chain uh block or excuse me chain ID or actually excuse me function get config public view returns Network config uh memory get config by chanity block. Chain ID all right un 256 constant local chain ID equals 31337 this if chain ID equals equals this then we're going to go ahead and return get or create like this else return uh else if we're going to do this conditional again if Network config of chain id. entry point does not equal address zero then return like this else revert with this error here and this that means this can't be a public public view just has to be public cool this can't be public view either because we have this okay cool and then we'll deploy mock down here in a little bit but cool so now we can get the config just by calling get config which means back in our oh oh whoops I put this in the wrong one let's put this over in the right one here which means back over here I can import helper config from SRC or script slh helper config dos. soul and our deploy we can say helper config helper config equals new helper config we can say helper config do Network config config equals helper config doget config like this memory now we can just do a minimal vm. start start broadcast vm. stop broadcast like this probably want to set up an account in here but I'm not going to bother we can just say minimal account minimal account equals new minimal account and then I'll do minimal account. transfer ownership ownership to message. Sender so this should pretty much already be the case um but just to make sure our tests are all working correctly I'm just going to do this oh and this is actually going to be fig. entry point in here ta it's a little Forge build make sure everything's working it sure is okay very nice now we're probably going to want to add an account in here as well so I'm actually just going to go back to our helper config up in here create a little address account like this I'm going to create a constant I'm going to say address constant burner wallet cuz if I interact with this I'm definitely going to want to use a burner wallet going to grab my burner wallet address here then in here we're going to do for aoia we'll do account will be the burner wallet or this should really be the your test net wallet but burner wallet works fine too and then we'll do account burner burner wallet like this cool and then in instead of entry point does not equal add Z let's do account because down here we're actually going to use address zero for like real so we'll do instead of entry point we'll do account does not equal add zero and looks much better okay cool now we're going to deploy the mock entry point in a little bit but fig. account but I want to just get this all set up here and I want to get a basic test going okay cool so we now have a deploy script actually oops returns uh helper config memory and Min IM all account like this do return helper config and minimal account oops sorry no just straight up helper config Okay cool so now we can use this in our test we can go over to test create a new folder ethereum and then here minimal account test. t. and let's start building a test for this and this test is actually going to be kind of Bonkers in a good way we're going to do a lot of signing of stuff we're going to do a lot of API encoding of stuff and we're going to be learning a lot during this so buckle in because this is where it gets fun okay MIT 0.8 .24 is that what we're using 0.8.4 yep okay contract Min andal account test is test like this import test from forg sdd test. s all right great function set up you know the drill here you've done this a 100 times we're going to need to import that minimal account from SRC SL ethereum SL minimal account. Soul we're going to need to import deploy minimal is that the name of it deploy minimal deploy minimal from script slash deploy minimal. s.o like this and we're going to do in here deploy minimal deploy minimal equals new deploy minimal deploy minimal dot what do we call it deploy minimal account deploy minimal account and we're going to get the helper config back so we're going to say import helper config from script script slh helper config dos. so like this and we'll say helper config helper config and minimal account minimal account equal s deploy minimal account deploy deploy minimal. deploy minimal account and what's it m about deploy minimal account helper config minimal account oops it's CU I spelled it wrong okay and you know what let's actually make these State variables and let me do a little word rep here config minimal account get rid of this and get rid of this Tada all right we are cooking so now what what do we want to test so we basically want to test that somebody can sign the data go through this alt men pool go through the entry point and then have our contract do something we could have it do really anything but I kind of want to test working with a contract so for us our test is going to be a usdc approval right so the so the message. sender should be our minimal account minimal account and it should approve prove some amount the usdc contract but it should come from come from the entry point because if we work this in such a way that it actually works if it comes to the entry point that means all these alt mol nodes will be able to bundle our transactions they will be the ones to submit it and all this stuff will be py door right so we're going to go ahead and write some tests to kind of simulate bundling these transactions sending this transactions we are going to simulate we are essentially going to simulate being these alt mempool nodes here so so this is going to be really exciting for us to do so let's start writing some tests and we're going to have to update our setup and update a bunch of stuff in here but uh let's keep cracking so let's do a quick little function just to see if our basic functionality works right so this execute function that we created where is it execute the owner should be able to call it and like send a transaction through here no problem so we want to make sure that this this flow works right so before we even get to the account abstraction stuff we just want to make sure that our offchain private key our offchain owner can call the minimal account which can call the usdc directly right because this is kind of going to be the simplest flow and this will give our user our minimal account users kind of the most customization with this minimal account right because they will be able to then directly interact with this contract or send the transactions to the bundlers with the alt men pool stuff so let's just test to see if directly calling this works so we'll do a little function test owner can execute commands be public and minimal accounts up there so let's do a little arrange act assert going on here so for arrange what should we do well we should probably get a mock erc20 right so let's go ahead and get that uh this actually comes directly with Foundry and open Zeppelin so we're going to use the open Zeppelin one so do a little import mock erc20 from atop Zeppelin contracts slash I think it's MOX SL or Mo ERC or what is it erc20 mack. is that what I I just looked up erc20 mock ec20 mock yes contracts mock token contracts mock token there we go and it has mint and burn great open Zeppelin contracts MOX token erc20 mock okay cool and then we'll do a little erc20 mock usdc we'll say USC equals new erc20 mock the erc20 mock takes nothing okay cool so we're going to do a little usdc approval actually we can do a little usdc mint let's do a little uscc mint take it back cuz in this mock we have this mint function let's just test that that's a little bit easier and more fun to test so we can kind of start by assert equal the usdc do balance of address minimal account is going to be zero like that then we can say address destination is going to be the address of usdc right because what are we testing and minimal count we're testing execute so we're going to need destination value function data so destination is going to be our usdc contract value is going to be zero and the function data is going to be the mint function so D is going to be this U 256 value is going to be zero and then we can do bytes memory function data equals this is where we do some wonderful ai. ncode with selector erc20 mock do mint. selector like this and if you're not familiar with how this works definitely be sure to go way way way back to the nft section to learn about this the nft section of cyphon updraft so this is going to get us the function selector of this uh we actually could also just do this actually now that I'm thinking about it but I'm going to do this for verbosity because if this did have parameters we would you know add the parameters in here but any case so now we need to prank the owner of this so we can do a little vm. prank minimal account. owner like this and then we can run minimal account. xute Des value function data and this should have our minimal account mint some erc20 mack to the minimal account right so and let's yeah so let's do assert equal usdc do balance of address minimal account should be how much are we minting here let's go back to that ec20 mock mint oh oh excuse me mint does take an account and amount here so let's actually go back over here let's go up to the top and we'll do U 256 constant amount equal 1 E18 amount so what did we just say it was it was going to be account and amount so we want to do when we encode this we want to do the account so we'll say address minimal account and then the amount like this and now we're actually encoding mint with minimal account and amount so this is actually kind of a more fun test because we're testing a function with parameters so I like that a lot better so USC balance of minimal account should equal this amount that we just added in here and great that's our whole test let's give this a whirl Forge test d-mt paste this in let's add a couple of these let's zoom in a little bit setup failed invalid owner oh oh it's because it's passing in the zero address so when we do our deploy deploy minimal account here this account. config if we go over to the helper config uh we don't have this set up so it's giving the zero address so yeah let's go ahead and and set this up here so let's do return Network config entry point let's just do address zero for now because we're we're going to need to create the mock in a minute but for now let's just do add address zero and then we'll do account um I'm going to cheat a little bit and I'm going to use The Foundry default sender for this so if you look in base. Soul we've mentioned this a few times before the default sender for Foundry is this kind of default color it's this address right here so I'm going to use this here up at the top I'm going to say address constant Foundry default wallet equals that address here and we're going to have the account be The Foundry default wallet like this so could be restricted to view and then we'll deploy mod in a little bit but okay so now we actually have an account here the founder default wallet so now if we rerun this test again this one should actually work now now that we have a a nonzero address sender not from entry point let's go to our minimal account. require from entry point require from entrypoint or owner this is why we write tests my friends so let's run that again and boom okay cool and it's giving us a warning because we we haven't finished this function yet but we have this passing and this is very exciting because now we know for our minimal account abstraction we can at least do this setup right here right cool now we want to move over to make it do this setup and there's going to be a couple of steps that we're going to do to get there all right cool well we should probably do one more we should test that if you're not the owner and you're not the entry point you should not be able to do command so we'll do a little function test non owner cannot execute commands public like this a range will be pretty much the same as what's up here so actually just going to grab all of this yeah I'm just going to grab the whole thing and instead of minimal count out owner we're going to do a little random user address random user equals make a DD R random user like this and then back down here we will do a little vm. prank random user Forge Forge test and we'll have everything compile here and run oh duh it failed successfully but uh I forgot to tell it it's going to fail so we'll do a little vm. expect revert and this will be minl account minim small accountor not from entry point or owner. selector rerun the Forge test and voila okay things are looking good now we get to go into the fun stuff we just tested the execute which is cool we need to test this validate user operation so in order for us to test this we're going to have to create create a packed user operation we're going to have to get the hash of it and we're going to have to figure out how much it costs I think we can skip a lot of that though and we're probably going to have to refactor some of our tests so we can work with keys to actually do some of the signing here and kind of our ultimate goal is going to be function test validation of user Ops Ops like this this will kind of be our final test but before we get that we should probably test a couple of of other things first so in this validate user op the first thing is going to be this packed user operation right which we can get from this contract here and it's going to be this struct and it's going to be this signature so we are actually going to have to write a script here that actually can generate all this code all of this and then actually sign it so we could do this 100% right in our test here however when we send a packed user operation we're going to have to sign it anyways so we might as well just actually create the code in here and then reuse it in in our test because that's going to be much better because then we'll get to test actually our signatures over here test our signature creators inside of our test so before we can even test validation of user Ops we're actually going to have to test creating this packed user op right so we're actually going to have to test creating this packed user operation so we're going to have to make a script that will add all of this stuff in that will sign this and then we need to make sure that this pack user operation is good and that the signature that we used is good as well so and then only then can we actually run this so we have to take a step back and let's start writing this send packed user operation and this is actually what we're going to do to test on an actual test net or an actual main net that's I I tested this on an actual main net because I wanted to see the real experience but you don't have to do that of course so we're actually going to build it here so that we can work with everything make sense okay great let's jump in okay so you know the drill pragma make this MIT 0.824 contract send packed user op is script that means we're going to have to import script from Forge STD script. Soul like this we're going to have a function run public which we're not going to Define yet then we're going to have to have a function called generate user operation like this and this is what we're going to have to build here this get signed or generate signed user operation and this should return that exact thing that we're going to pass to our minimal account here right we're going to have to pass this this packed user operation type so we're going to want to import that so we're going to say import this packed user operation from and this is actually in the lib account abstraction haha SL contract SL interfaces slpa user operation. Soul like this and this is going to return this packed user operation and this is a struct so pack user operation memory like this and here's where we get to use all the fun signature knowledge that we've recently learned to actually generate this signed user operations so first we're going to have to generate the unsigned data and then we're going to have to sign it and return it and return it like this so let's actually focus on this first generate unsigned data and I'm actually going to put this in a separate function so I'm going to have another function here function called underscore generate unsigned user operation like this and and this is just going to take some bytes memory call data we have this be internal pure and it should return also a packed user operation memory except this one is just not going to have the signature right so if we go back to this file this is the packed user operation so our our generate unsigned user operation is just going to populate all these fields basically leave the signature blank and then we'll have this gener signed user operation actually do the signatures so this this will definitely be the easier one so let's even just get started here we'll do a little return packed user operation and we'll just populate the fields as we see fit so the first is going to be a sender and we probably need to pass that in as a parameter as well so we'll do address sender like this sender will be sender we'll do a little nuns this is where we probably want to be clever with our nuns here as well we probably want to parameter tize that too so we'll do nuns or U 256 right it's U 256 yep un 256 NS say nuns is NS init code we probably could modularize this as well but we're going to ignore this right because we're not going to be initializing any contract so we're just going to do a little blank data bit here or do I do hex hex like this yeah okay then the call data is just going to be the call data and the call data of course is going to have you know all of our function data our function data to call all right next is going to be a couple of different gas limits now I'm just going to kind of wing this we don't really need to get this exactly correct because a lot of these are just limits here so just roll with me on these so account gas limits we're going to do we're actually going to make a couple of different variables at the top we're going to do a uint 12 8 verification gas limit this code was inspired by some of the ideology that was used to build some of this account abstraction bits here so this verification gas limit we're just going to say 16,777,216 and just know that this is probably going to be fine if you run into issues with gas you might want to tweak these a little bit but this is what we're going to run with for now U into 128 call gas limit is going to equal this so these are going to actually be the same and then for the account gas limits we're going to do some clever ways to concat uh these two variables together even though they're they're kind of the same thing so byes 32 you 256 verification gas gas limit and if you don't understand exactly how this is working don't worry too much about it uh little left shift 128 gas limit like this so this is really just kind of us combining these two into one bytes 32 if you want to jump into chisel and play with exactly what this will return you are more than welcome to do so but then we're going to do pre verification gas is just going to be this verification gas limit then we're going to do gas fees like this and we're going to have to make some more clever stuff here again this is where we could be clever with how we're doing some of the gas fee stuff but I'm going to say Max party fee per gas is going to be 256 this and for gas fees we're going to do a little concatenation as well byes 32 un 256 Max priority gas fees shifted 128 or Max fee per gas which we're going to have to create that as well I say U 128 Max Fe per gas equals Max prity gas fees yeah like I said if if the gas fees don't quite make sense here don't worry too much about it they're just gas fees and gas limits then what we have we have pay master and data we did not add a pay master so pay master and data we're just going to say hex blank we're going to pass nothing and then for Signature we're also just going to pass some nothing here okay cool the reason I put this in its own function is because this can be kind of here but we have our generate unsigned user operation which just generates essentially just this struct for us so what we can do now is we can say packed user operation unsigned user op equals generate unsigned user uh generate unsigned user operation this will take the bytes call call data or byes memory call data call data uh excuse me this needs to be byes memory call data address sender and we're not going to pass the NS in here because we're actually just going to use a Foundry cheat code to get the NS of the sender so there's a get nuns address account get the nuns of the given account or wallet boom we can just do it like this so we'll do a little un 256 nuns equals vm. getet nuns sender like this and then we'll pass the call data in here the sender in here and then the NS in here as well and this of course needs to be Memory like this okay nice great now we have this unsigned user operation now let's just go ahead and sign it and then return it so okay great so we have this pack user operation we just don't have the signature we just got to assign all this now in order for us to actually sign this we have to get the user operation hash that the entry point contract is looking for so what so we want to actually sign this way the way that the entrypoint contract is expecting now if we go back into our lib account abstraction I'm actually just going to cheat a little bit and look for the entry point. Soul right here in account abstraction there's actually a function in here called get user op hash and this is how our entry point contract is expecting that hash to be created so what we could do is we could 100% copy paste this or we could kind of take this time to actually deploy our mock entrypoint contract and then use this get user op has function to actually get the user op hash so and what's important to know is that the chain ID is going to be part of the user op hash this is actually really important so that we don't have cross chain replay attacks it's also hashed with the actual entry point address there's no issues with using different entry points and we want to use whatever function the entry point contractor we're actually working with is using so back in our helper config we're going to need to add that entrypoint contract address for sapoia well not for ZK sync but at least with our Anvil our local we want to deploy a mock entrypoint contract so that we can actually work with that when working on our local network so let's go ahead let's actually import that entrypoint contract we'll do a little import entry point from lib slac account abstraction SLC contracts where is this contracts coree entrypoint Doo like this and then down in our mock we can actually deploy this I'm also going to grab a little console here console 2 from our script I'll do a little console 2. log deploying mock dot dot dot then we'll do uh entry point entry point entry point equals new entry point like this there's no Constructor or anything and then we can take this entry point address here and boom do address entry point like so and then we're also going to want to do vm. start broadcast of the founder defi wall just in case we're on Anvil and then bm. stop broadcast cast of course like so nice so now that even our local one is going to have this entry point contract here we can use it to call that get user op hash function so we actually not going to sign it quite yet we're actually going to get the user op hash then we're going to sign it and then we're going have to do some clever signature stuff to actually sign it so to get the user op hash we're going to say bytes 32 user oph equals and this is where we're going to have to get past that helper config address so in another parameter here we're going to get that config so helper config dok config to import that as well import or actually we can just do Network config from script slh helper config s.o we don't even need helper config do we can just import that Network config like this and actually if we do this we don't even need the sender because instead of doing the sender we can just say config do account here and we can do that here config do account account like there and then the user op is going to be config dot like this we're going to need to wrap this in an i entry point interface so import inry point and you can see why we installed this as a dependency here import I entry point from lib slac account abstraction SLC contracts SL interfaces SL I entry point. Soul so we can do I entrypoint config entrypoint get user op hash and pass in our unsigned user op right there cool then once we have the hash we can convert this into an eth signed message hash so there's actually a function called two e signed message hash that takes a by 32 and this is going to return the kak 256 digest of an EIP 101 signed data with version o so we're basically just going to add all this EIP 91 stuff to our byes 32 so that it turns into a proper digest for Signature stuff so we'll do a little bytes 32 digest equals this user op. to e signed message hash sign message hash and since we're putting this function onto our bytes 32 we're going to have to import that oh and it looks like we're having an issue we probably are going to have to do the helper config but let's go ahead let's do import message hash utils from atop open Zeppelin contracts SL utils [Music] cryptography Mage utils do so and then we're going to say using message hash utils for bytes 32 and it looks like this is actually causing issues so let's just do helper config do Network config like that okay cool we'll run a a forge build in a minute so okay so now we have the digest this is the correctly form added hash so we're pretty much on the home stretch now all we need to do is sign this digest here so we're going to do a little vm. sign we're going to have to have the private key comma digest here now here's one of the cool things that you can do in Foundry typically this is where you'd have to like do like a vm. EnV uint private key whatever you'd have to stick your private key in here but as you know because you're taking cyh updraft yeah yeah you don't do that because that's a great way to accidentally expose your private key so we're not going to do that here so Foundry is pretty clever where if you have unlocked a key right you know how in s for up we teach you to do you know Forge script-- account instead of-- private Key Well if you have a private key unlocked with an account you can just do config doac account you can basically pass this an address and Foundry will be smart enough to go ah okay so we're using an address here let me check if I have that key unlocked I sure does boom we're going to use that unlocked private key to actually sign this which is outstanding so so we're actually going to sign this and if you watched Kira's video we're going to get that uint 8 V that byes 32r oops byes 32 R where is that byes 32 R and the bytes 32s like this from the signature and then we're finally going to create this signature at the bottom by just combining these values together so we're going to say user signed operation equals excuse me we're going to say user signed operation. signature signature equals ai. ncod packed r s andv and just be sure to note the order this is vrs and this is RSV I must have spent like 3 hours trying to figure out why my signature was wrong and it's because I had the order wrong so note the order here and then we're going to return our signed unsigned user operation actually this is kind of confusing because now that it's signed let's let's just rename this to user op user op user op user op user op okay so we now have a function called generate not generated generate signed user operation it's probably giving me a warning because this should be view let's call A View generate user generate signed user operation we have generate unsigned user operation and we can now use these in our test and we're passing call data and a config so what we're going to do now so we're going to pop back over to our test now that we have a script to actually do this way up at the top we're going to do send user operation send packed user operation send packed user op is going to be a state variable that we use we're going to go ahead and import it send packed user op from script slend packed user op. s.o like this send pack user op send pack user op and then now what we can finally do is we can finally test that this actually works so before we actually test the validation of our user Rob let's just test that we're actually signing stuff correctly right because if we're not assing stuff correctly then our validation isn't going to work correctly either so let's create a little function here function little test function called test recover signed op and this will be a little public view function and this is where we're just going to do an ECR recover on our signed user operation hash and if we're get the correct owner this should work well and I'm going to do a little refresher on all this we're going to kind of summarize what we we learned after we write this test because I know we've gone over a lot of stuff don't worry you're doing phenomenal by getting this far and we're going to go over this again so don't worry too much so test user op test recover signed operation let's do a little arrange act assert here for our arrange we're actually going to cheat a little bit we're going to copy all this because we're going to do the exact same arrange here and oh we also need the function data as well and now we're actually going to combine all of this into the execution call data so when we did the test above here we only need the function data because we were just calling directly this execute right and this execute will call the usdc and pass the you know the function selector and all the data that needs to go to the usdc what we need to do because we're planning on having validate user operation work correctly so we are actually going to have to code our call data that tells the entry point contract to call our cont contract and then have our contract call the usdc so we've encoded this bit here but we also now need to encode first calling the entry point and then calling the minimal account right because I have to move all this over because we're going to send our data to the alt men pool here the alment pool is going to call the entry point we need to tell the entry point to then call our account and then have in that same data that we signed have the minimal account call usdc so hopefully that makes sense here so we have the function data for calling the USC we also need to get the function data to call the execute so we're going to actually wrap this up in call data so we wrapped this up in call data in function data now we need to wrap this up in call data as well so we're going to do bytes memory execute call data and this is the data that's going to be used in order to tell entrypoint to call this function which will call the usdc byes memory execute call data equals ai. encode with with selector minimal account Min minimal account. xute do select door comma destination value and function data so this execute call data is saying hey entrypoint contract where is it entrypoint contract call call our contract and then our contract call usdc right minimal account call this execute function and then inside this execute function call usdc make sense great we have this execute call data we now need to use this call data to pack create our packed operation right so this packed user operation because this is what the alt mempool needs to get so we're going to have our sender nuns blah blah blah all this good stuff here what's cool is now that we have this send packed user operation oh we need to do equals new send packed user operation actually initialize it so now that we have this contract we can just pop this stuff into our sendpack user operation and what are we going to call generate signed user operation with the call data and the config and this is going to return what it's going to return our packed user operation that is nice and signed so we're going to have to actually import that as well so let me copy this do we not import that yet we have not uh we can actually just import it from the sendpack user operation which is kind of cool that we can do that like that but we're going to say packed user operation packed user op equals send packed user op. generate signed user operation execute call data comma and our our helper config I believe what is it what does this take it takes the network config so not the helper config but we're going to do helper config doget config so helper config doget config so our helper config is going to give us the network config we're going to pass that to here and this needs to be Memory like so so oh and and this cannot be view because we're calling this and this could potentially deploy MOX So Okay cool so we have our pack user operation finally it should be signed it should all be peachy hunky dory it should all be good now we can finally do our act here which is going to be where we recover where we take this where is it pack user operation where we take this signature and we'll say hey let's use this public private key cryptography thing and figure out who actually signed this we can always derive the public key that signed this we can't always derive the private key obviously because it's the private key but we need to ask the question hey is the person who signed this the right person so we can go in here and we can do our little ecdsa recover and we're going to have to import that as well from our wonderful friends that opens up one so little import e e c DSA from atop Zeppelin contracts UIL cryptography SL ecdsa do like this and we can finally down in the bottom down in our act here where is it down here we can finally do ecdsa do recover this and if we look in this and we look up that function recover it takes a hash and a signature so this is going to be the user operation hash and this is going to be the signature so if we scroll down we have this whole packed user operation we need to convert this into its hash don't worry our friends at the entry point remember they have this function get user op hash right which calls user op. has blah blah blah and this is a little bit cheeky actually a problem that I ran into for a while when I was first learning this I was like hey is the hash hashing all of this because you can't get the signature of the whole hash if you hash the signature first like what the what the heck how what what is it actually hashing and the entry point is kind of tricky if you scroll up in here there's like a library that they're using user operation lib for packed user operation and if we go to this user operation lib there's a function in here called hash where they have this it has this function called hash where it calls encode and this basically encodes everything except the signature so there's some stuff going on behind the scenes actually to Hash the whole thing a very specific way without using the signature which is why again we always want to make sure we're getting our hashes with the get user operation hash with whatever entry point that we're using right so because the hash isn't because we could 100% just hash this ourselves but maybe we do it slightly differently than the way the entry point does it and we'll lose our minds because we don't hash the right way so actually before we do the ACT we need to get the hash so we'll do bytes 32 user operation hash equals entry point oh we need to get the entry point so we'll do I entry point config dot or do we have the config no we should have gotten the config but hper cig. gig. entry point. getet hash and we'll pass it this packed user op hash here so we'll get the hash and now we can finally pass this in to the recover function although this isn't quite exactly right yet either we also need to convert this to a 2 eth sign message hash there's a lot of getting the format right in here so uh we'll we'll always want to kind of keep that in mind which means if we're doing that we got to scroll back to the top I know a lot of stuff here and we're going to have to say using message hash utils for bytes 32 if you don't do this stuff won't work and you'll be sad so let's get that as well import message utils from atop Zeppelin contracts SL utils cryptography SL ms. so like this and then now down here we convert the user operation hash to the correct format of the hash and then we can pass the signature so we'll say user operation has. signature that we just created from this function here oh my goodness and this is going to give us an address so we'll say address actual signer equals this and we can finally do a little assert equal the actual signer is going to be the owner right because we can only this should only work if the minimal account owner does the signing so we'll do minimal account. owner like this woo I know that was a lot of stuff going on here but let's run this as a test moment of Truth here oh and then I did this wrong contracts there we go so Moment of Truth here oh I entry point oh we got to import the entry point to um is that in send packed user Ops it sure is so we can import it from there actually I entry point so now we can finally do a little test on this scroll back oh just kidding not quite yet I also messed something else up here message hash I should get good at spelling huh that's usually my weakness user operation hash do signature signature oops sorry this is packed user op. signature cool now we can finally run this let's grab this test here clear everything out Forge test d-mt paste dvvv Moment of Truth aha interesting we're getting this error no wallets are available now the reason for this is when you're working with scripting like we are right in our scripts here we have this sendpack user operation and we do this sign here right so Foundry is smart enough to know that okay if you're doing a script right when we do forg script-- account or-- private key if we have that it'll say okay that account is quote unquote unlocked and and anytime you do something with a private key in an unlocked account it'll go through however when we're just running Forge test right like we're doing right here we're not passing in an unlocked account so founder gets to this line and goes uh nothing's unlocked even though even in our helper config we're using the default wallet also we're going to have to refactor this just a little bit because I I messed something in here up but in any case so what we actually have to do is we have to be a little bit clever and use a workaround for this specific line here so we're going to have to do a little bit of a workaround here for this signing to actually work when we're working on a local chain or working with a test versus when we actually go to the Wild and use this on a test net and the beauty of this is this actually inspired me to make this issue on the founder repo as a new feature hey maybe it would be cool to just automatically use an anvil default key so that you don't have to kind of do this work around that we're about to go through right now and this is the beauty of Open Source and maybe by the time you watch this this will be fixed because yeah as I was recording this I was like ah why do I have to do this work around it would be great if founder just had this feature so we made this feature so any any rust devs watching this who want to take this on you'll get a big thumbs up from me if you fix this so and this also just shows the beauty of Open Source and how all the tools were working with here are constantly improving and constantly growing which is why I have to consistently remake all of these videos all right cool so let's refactor this for working with local tests anyways so we're back here we're going to need to refactor this and we're going to need to do a little bit of helper config stuff that we've done before so a lot of the times instead of doing all this stuff here we'll make a code constants chunk of the top I'm not going to do that here but this would be a little bit better if we made like a code constant and we inherited and blah blah but this is just kind of our fun codebase but if you are here at this point in the course you already know how to do all that so we're going to going to go ahead and skip that for now and do kind of the hacky way so in our script here we're going to say if block. chain ID equals equals 31337 we're actually going to do this a little bit differently so we're going to take this vrns we're going to do v r and s like so we're going to initialize them as blank and then we're going to say if block that chity equals 31337 then we're going to do vm. sign and we'll do V comma R Comm s equals vm. sign and instead of config do account we're going to do the UN 256 Anvil default key like this and we can grab this but just running Anvil getting kind of the main key here killing Anvil pasting it right here so this will now be the Anvil default key so if we're on a local chain we're just going to use Anvil here and then we're going to say else we're going to do all this stuff here uh we're going to swap this out with vrns like so so now since we're using the Anvil default key for our local chain development we're going to have to go back into our helper config and actually we need to refactor this anyways and we're going to have to go down to the bottom and update this so that instead of working with The Foundry default wallet we're working with Anvil by default here so up at the top we're actually going to Comet this out and now we're going to say address con instant Anvil default account equals and that's actually where we're going to pull Anvil back up and then grab this account here equals this we're going to grab this Anvil default account and we're going to use the Anvil default account instead of The Foundry default wallet now the other thing that we're going to have to do because I forgot to do this is his local network config equals this and then return the local network config if you didn't do this part this would just always be true and you would just constantly be deploying mock so we don't want to do that so now we're using the Anvil default account Anvil default account so that when we use our user operation we will sign stuff with the Anvil default key and then all of our tests should work so long as we work with the Anvil default account that does mean that back in our deploy minimal though we're going to have to do VM to start broadcast config account and then also transfer ownership to config doac account just to make sure that we're going to transfer right away to the correct person here so so now now that we've done that little bit of a refactor let's rerun our test here what do you know we do indeed pass so this means that we've actually successfully written a codebase that we will sign our user operation methods correctly so we've got this kind of huge script in here well it's actually not that huge which will generate a signed user operation and it's slightly different for working with local chains but we're working with a real test net it's going to use this and it'll work perfectly trust me I'm going to do it in a little bit don't worry and we're actually correctly signing these user operations very nice so now we want to get to the most important test and then actually we're going to do one more test as well test validation of user Ops so this is where we're going to do what well we're first going to sign our user Ops then then we're going to call validate user Ops with our signed user Ops and then three we're going to assert the turn return is correct all right so let's do it and then we're going to actually do one more so then we're going to do a final function test entry point can execute commands and that's going to be our final test here and the reason of course we want to test this is because again once again who is actually sending these user operations well it's going to be these alt mempo nodes who are going to submit the transaction to the entry point so we need to make sure that those are working correctly here so let's do this test validation of user Ops here and luckily we can actually reuse a lot of the code that we've used up here and by a lot of the code I literally mean like all of this so we can kind of save our some time by copy pasting that user operation hash then we're going to get into the actual act here so we're going to do exactly what we did before but instead of just testing that we can recover correctly we're just going to test that validate user op actually returns correctly so we'll do a little vm. prank the address of the entry point I guess we're going to have to do this I probably should have just initialized this at the beginning huh well I don't need this address either hper config getet config.py we're going to be the entry point cuz in our minimal account right validate user validate user op can only be called by the entry point here so we're going to call we're going to be the entry point we're going to say un 256 validation data equals and remember we are kind of just having some real minimalist validation data but technically you can add a ton of stuff into your validation data so we're going to say un 256 validation data equals minimum small account. validate user op user op we're going to need to give it the user operation hash and then we're also going to need to give it this missing account funds now for this we can kind of just pick some random big number because again this is just going to be sending the money to the entry point and for just the validation it doesn't really matter for the actual call it'll matter but for just validation we can do whatever so I'm just going to pick kind of a random number here we going to do U into 256 missing account funds we're going to say 1 E18 that's probably plenty that's probably actually way too much but again random number so we're going to get this validation data oh user packed user op excuse me and now technically we should parse this validation data because our function here is actually pretty simple it's just kind of returning what it's returning zero or one right or what is this yeah one or zero but Tech technically this validate user op if we go to the I account. Soul the return validation data is actually like has a ton of data packed into it so we probably should go ahead and parse the validation data but since our codebase is pretty simple and we just know it's returning a one or a zero we can assume it as such right a one is going to be failed a zero is going to be a success and we are assuming that this is actually indeed a success so what is it zero is a succcess so we're going to say okay assert validation data equals equals z or excuse me assert equals validation data and zero and now we can test this as well test d-mt paste that in and that passes as well okay awesome so we've tested we're doing all of our crazy signature stuff correctly we've tested that our minimal account validation is working correctly now let's just finally test what we really care about which is going to be be that the entry points can actually execute commands based off of our kind of crazy nonsense right so let's do this last one and then I'll show you exactly what this looks like end to end on a real actual Network and then once we do all this stuff here we can move over to ZK sync and we'll show you how to do this whole process on ZK sync which from a devops perspective is actually a lot simpler because they have native account abstraction very exciting stuff and the reason so particularly excited about you learning account abstraction is because a lot of people still aren't really using this to its fullest there is so many cool things people can build with this so so you are unlocking a crazy skill just by learning this so anyways let's do test entry point can actually execute these commands here so let's scroll on up and you already know we're probably going to want to do all of this stuff again right so I'm going to actually once again copy paste we're getting the destination the value creating the function data the ex ution call data creating the packed user operation and then getting the user operation hash we're getting all that good stuff here and that's what makes writing this test actually so much easier because we've already done most of it but what we do need to do is we actually need to fund our account right because we don't have kind of this optional pay Master thing so when these alt mempool nodes go to submit this transaction they originally pay for it and they're going to be like hey uh we need to be reimbursed for this we're pulling it from you so you better have the money so we're going to go ahead and just do a little vm. Deal address minimal account like this and we'll just deal 1 E18 I know this is kind of a magic number and not best practice but you know you get the picture then we'll do a little act here we'll do a vm. prank and here's what's cool is we can actually be a random user now so we're going to prove that a random user basically any alt mle node can submit this to the entry point and as long as we sign it you know we're doing it with our metamask not with Google here as long as we sign it anybody can send our transaction which is kind of wild so vm. prank and all they're going to do is on this entrypoint contract is call this function handle Ops that's it which we're going to pass our Ops our our pack user operations which is just going to be a single user operation and then the beneficiary who is the person to actually get the fees which we're going to give to random user right because they're the one actually executing this transaction so we're going to give them the fees for actually doing this thank you random user for sending our transaction here so all we have to do is do helper config dog config entry point yeah I should have saved this earlier but you know I entry point helper config dog config entrypoint dot handle Ops and all we have to do is pass in the array of this packed user Ops so let's actually also do a little packed user operation array memory Ops equals new pack user operation array of size one here and then we'll say Ops of zero equals packed user Ops like this so handle user Ops we'll pass in this Ops array we'll give random user random user is it random user random user oh I didn't capitalize you okay well we'll give random user the fees for this and then we can just do an assert finally packed user operationa user there we go and then we can do an assert and we're going to do the exact same assert that we did when just our EA was the one to call this so we're going to do this assert right here because we're doing this mint assert here so let's scroll on down we'll do assert boom random oh and then we make this payable as well so it doesn't error on us user operation hash oh we don't even need the user operation hash because that's inside of our handle user Ops and let's go ahead and let's test this Forge test d-mt paste it in- vvv zoom in just a little bit and it failed whoops so since you're at this point in the course you now are a little bit better at debugging you're a little bit better at understand what's going on stuff like this is pretty much going to Define your life debugging stuff and figuring out where to solve it so we're going to do a little bit of a debugging exercise we're going to solve this we're going to fix this and then we're going to move forward in life and this is going to be a great time for you to pause the video and try to see if you can debug this yourself of course if you got the same issue hopefully you did because you've been following along because guess what this is coding coding is a lot of the time it's going to be fig fig out why you got certain errors right and it's going to be going through all the debugging skills we've been learning talking to chat gbt maybe Googling it maybe even going on YouTube for the error so pause the video go ahead try to debug this yourself and we'll come back in a minute for something like this chat gbt will definitely not be very helpful so let's go ahead and jump into some debugging practice so Foundry has some really nice tools where we can actually do Forge test-- debug and it will drop us into kind of this really lowlevel debugger here where it has all the op codes and everything that's going on here so one of the tricks that I like to do is hit shift G and this will bring you right to the end of where it actually reverted and in kind of the the bottom here we can see the line and the code of Sol where this actually had an issue right so we're looking kind of right here now what we can do is we can start walking backwards to see okay what was the line in this handle ops command that actually failed because the output we got from Foundry before wasn't really super helpful so I'm going to start pressing the K keyword if you look at the bottom there's kind of this JK previous next op code this is op code by op code we haven't gone over op codes yet we go over that in the assembly course you can go ahead and check that out later if you want but we just go ahead and start hitting J which will walk us back through kind of the code base at some points Foundry will get a little bit confused it won't exactly be sure what line we're pointing to but we'll keep going back and eventually we'll land here so it's saying try I account sender. validate user op and this is the line that is having issues huh but we we tested validate user op validate user op is working great I account account sender so this sender should be what this sender should be the minimal account okay well let's okay let's quit this by pressing Q let's go back and let's see okay get signed user operation okay generate user blah blah blah let's go see what this is doing uh sender is going to be sender okay who are we assigning to Sender config do account oh we're setting the wrong account ah now we could 100% confirm this too by actually going to the entrypoint Doo finding this line here right and I've kind of already cheated I've got these added right here and doing a little like console.log making sure these are the correct senders the correct addresses Etc so this would be another way to do this of course you would have to do kind of a clever import so if you want you can go ahead do like a clever import here in your ENT in your mock entry point here and import console to print them out print out those values Etc so but in any case yes this is wrong this should be the minimal account so we're going to need to do a little bit of a refactor here so call data config yeah okay so we're actually going to need to have the address minimal account passed in here as well and it's this minimal account instead of the config do account that we're going to have to work with so same thing with the nuns we're going to have to use minimal account here and since we're updating this any place that use this is also going to have to get updated so this is all going to be fine but all of our tests are going to be kind of messed up so in here we're going to have to do a little comma address minimal account and I'm just going to copy this whole bit right here so great that looks good now we're going to have to do a comma here address minimal account okay that looks good now we're going to comma here okay that looks good now any place else I don't know let's do a little Forge build see if stuff's actually working it sure is okay and now let's rerun the test and let's see if that actually works now H aa25 invalid account nuns and if you want to go ahead and debug this one feel free or I can just tell you but I highly recommend you pause the video and you go ahead and try to figure this out yourself but basically our vm. getet nuns this returns essentially the wrong nuns the entry point also has a get nuns function but we want to do get nuns minus one let's run this now for the final time and we will find finally see that that everything passes successfully fantastic job getting this far so I know we just went over a lot so let's do a quick summary on all the amazing things we just learned and the power that you just unlocked for yourself so we created a minimal account which takes advantage of ethereum's account abstraction or really any evm compatible chain that supports this account abstraction allows us to Define anything can validate a transaction not just a private key maybe our friends want to validate it maybe our Google session key wants to validate a transaction whatever you want all we have to do is code a smart contract that says here is what can sign my transactions once we deploy this when we actually want to send an account transaction transaction we first sign the data and we send it to a group of alt mempool nodes these nodes are going to be the ones to combine everything into a single user operation they're going to combine everything into a user operation and call the handle Ops function on an entrypoint contract this contract will then do a lot of validation and if it looks good it will call your account and your account will call the DAP it's working with Etc this is really fantastic because you can sign and send transactions where you don't pay any gas if you have set up a pay Master where somebody else is going to pay for the gas you can code any type of validation into your account you can say my Google session Keys is going to be the one to sign my transactions my friends are going to be the ones that sign transactions I'm going to add a spending limit I'm going to give my children an allowance on their account abstraction transaction I'm going to give them a wallet that they can use for now but I'm going to put parental controls on it where I have to approve all their transactions you can code literally any rules that you want into your account we built a minimal account that uses this account abstraction the main function that we needed to get correctly was validate user operation instead of sending a regular transaction object to the blockchain those alt mempool nodes will send a user operation to the entrypoint Dos contract which will call your contract and call the custom logic that you built for your validate user operation if the transaction is valid and your and the signatures associated with the transaction are valid it will then execute the transaction and do whatever you want here we did some very basic signature validation and we even wrote a quite badass script to generate signed user operation data generate unsigned user operation data and then actually send the handle Ops transaction directly to the blockchain so at this point you have learned what I want you do to learn for ethereum account abstraction this is a great time if you like to go ahead take a break go to the gym get some ice cream get some coffee whatever you want to do but we're not done with a abstraction we have understood this wonderful process on ethereum however as we've kind of seen it's quite convoluted so we are now going to learn a can abstraction on ZK sync which has this built in the only difference is you need to send a type 113 transaction and that's it because they have what's called a combined mempool they have the alt mempool and the normal menol are both just the mol which is really cool so game plan moving forward we're going to done we've done this we're just going to deploy a user op onto arbitrum and then we're going to do the whole thing again for ZK sync like I've been saying now's a great time to get take a break go to the gym get some ice cream get some coffee and we'll see you soon but let's do it so before we actually go to ZK sync let's go ahead let's actually send this let's actually run this for arbitrum and if you go on the GitHub repo associated with this course you can go ahead and actually see kind of the make commands that we're going to run I'm just going to go ahead and do it right here because it's not super important that you actually run the scripts but it is cool just to see kind of it all happen so so to for us to deploy our codebase we're going to do a little Forge script script SL deploy minimal. s. so-- RPC URL we're going to be using an arbitrum RPC URL I've already sourced mymv and I already have this in here like I said I'm just kind of quickly speeding you through this just so that you would see what this would look like we're going to do D- account is going to be my small money AKA my burner account this is a burner account that I deploy stuff with since arbitrum is a real main net there will be real funds here so you always want to use a burner account to deploy stuff just in case you mess something up so we're going to use a burner account or my small monies account and then we're going to do D- broadcast D- verifi verifi like this and after this has been deployed and I've actually already sent it just a tiny tiny tiny little bit of eth as well after this has been deployed we can kind of scroll down in here we can see this is the minimal account that I deployed I made it I added some gats back and stuff it's a little bit different than exactly what we coded together here but here is the code code base and now what we're going to finally do is we're going to send that user operation and actually we do need to update our script we actually do need to update this script because I forgot to add the Run stuff in here so let's let's add the Run stuff in here real quick so we're going to say helper config helper config equals new helper config address this is where I probably would want to do like helper config doget config do usdc but I'm actually just going to grab the arbitrum arbitrum main net endpoint arbitrum mainnet usdc address so grab this we go to arbitrum scan paste this in boom native us to see token deployed by Circle to arbitrum Okay cool so that's going to be our destination U into 256 value is going to be zero here let's do bytes memory function data equals let's just call the approv keyword so we'll do ai. encode with selector we'll say ic20 let's import this from atop Zeppelin contracts token slc20 ic20 do so Soul like here approve. select door and we'll approve and I'm going to pick myself this is just another one of my wallets that we're going to go ahead and improve here and then we'll choose an amount we'll do 1 E18 yes this isn't the best code because I'm just kind of showing it for this video if you want to go check out the nicer code be sure to check out the GTO repo then we're going to do the bytes memory execute execute call data equals ai. n code with selector this is nearly exactly as what we did in the test minimal account dox execute. selector dest value function data like this we need to import minimal account import minimal account from SRC ethereum minimal account. Soul like this then we're going to say packed uh user operation memory user op equals uncore get excuse me not equals generate signed user operation we're going to have the execute call data what else we're going to need the config so helper config doget config like this and then the address of our minimal account which I'm just going to kind of hard code for now boom execute call data like that then we're going to say packed user operation array memory Ops equals new packed user operation array one exactly like what we did in the test Ops of zero equals user op and then finally vm. start broadcast I entry point do we have this in here yeah we should do I entry point of helper. getet config entrypoint broadcast oops do handle Ops Ops and then and this can be this can be anybody that we want I'm just going to do config account here config dog config so I'm going to go ahead and and kind of speed through this actual deployment process here what I'm going to need to do in here is I'm going to need to go ahead and add arbitrum an arbitrum config once I add an arbitrum config I'm going to need to make sure all my wallets and stuff are set up correctly uh I'm going to kind of speed through doing that do that behind the scenes so all right let's go ahead and then of course this needs to be payable and then a little vm. stop broadcast as well okay so let's go ahead let's run this as well so we're going to do Forge script send packed user op. s. so- RPC URL arbitrum RPC URL D- account it's going to be small money D- br br- vvv now I've actually already run these commands and I've already deployed this minimal account much earlier and I don't feel like spending more actual gas one of the things that's kind of rough about testing a account abstraction is there's not really a testet way to test these so I had to ship it onto a real mainnet which is why I did an arbitrum here so but like I said did this a while ago and here's the output so this code base is working wonderfully and now you know how to do this we can see we have an internal transaction in here um so we have an internal transaction in here where if we look at kind of the logs in here we can see we called handle Ops we had an ops. sender we had the call data in here we had all everything we talked about and we had the a beneficiary and what this ended up doing was we go to the logs here we scroll down in the logs here the usdc token gave approval gave this much approval to this address and we have success sucessfully made an account abstraction user operation call let's go so you could 100% take your newfound power here and go build some amazingly cool things for the ethereum ecosystem where you're where there's a lot of smart contracts where there's a lot of layer tws that don't have account abstraction built in natively and you'll have to do kind of all this funky programming or you can follow along with me and we can learn how to do this on ZK sync so if you didn't take that break be sure to take that break go to the gym get ice cream get coffee get whatever and then come back cuz we're going to do this all over again but on ZK sync with Native account abstraction so take a break and I'll see you soon all right so let's start jumping into working with ZK sync for account abstraction now like we were saying ZK Sync has what's called native account abstraction we don't have to do this weird middle step of sending to this alt manool we just send to the normal ZK sync mempool there's also no entrypoint doou everything just goes directly to your contract right so we get the much simpler setup that kind of looks like this where you send your transaction to the men poool and you don't even have to spend gas this is why when we actually did send that transaction send deploy that smart contract in remix with ZK we actually had transaction type 113 we were actually just signing a transaction we didn't actually spend any gas ourselves we sent this data to a zync era node and it deployed our contract and then actually did end up charging us afterwards to spend gas because somebody needed to spend gas but we but this is why we hit sign instead of send transactions so we signed all of this data which they then sent and since ZK Sync has native account abstraction built in it was was able to automatically charge our wallet and all this happens kind of automatically and don't worry this is my test n account I'm not this rich now to get working with account abstraction on zync we're going to install this package called Foundry era contracts this is a mirror of a lot of the system contracts in the ZK sync system we're going to learn about this thing called system contracts that ZK Sync has which enables a lot of these really cool automaic things happening in the background for the duration of this curriculum anytime you see like era contracts or matter Labs era contracts we're going to work with this cyphon Foundry era contracts instead I've made a lot of tweaks to the codebase so that's easier to work with and easier to use so this is what we're going to be working with at some point I'll put like a little disclaimer at the top here that says hey instead of this now go use you know whatever The Zing team comes up with but for now this is what we're going to be working with so I want you to go ahead to get started and we're going to ahead and we're going to go and install this and you know let's get let's close all these up let's pull up our terminal do Forge install paste it in and for this video we're going to use 0.0.3 so we're going to say at 0.0.3 D- no- commit of course all right great now that we have this installed we can actually open up our Command pallet and look for I account account. but instead of in the account abstraction folder we're going to look for it in The Foundry era contracts folder so if you can't find it like that you can just open up your lib Foundry era contracts SRC system contracts contracts interface I account. so and I would like you to also open up this default account. Soul which at the moment is completely commented out although depending on when you watch this it might not be commented out so the reason I'm showing you these is because something really interesting that ZK sync does on ethereum there are two kinds of wallets you have kind of your classic traditional externally owned accounts this is going to be your mamass this is going to be your rabby Etc and then you have your smart contract wallets these are going to be your multi- your account abstraction accounts which we just created and these are basically the two different kinds of wallets now this causes a lot of issues though whenever you're coding transactions sometimes you have to know if it's a smart contract wallet or not some people have code where they say hey you know what dealing with smart contract wallet is too complicated and and some of them will even have checks saying if you're a smart contract wallet deny the transaction revert the transaction and there's a lot of reasons for this but it definitely makes dealing with wallets dealing with addresses really difficult so what ZK sync did was it said okay you know what all eoas are smart contract wallets so externally owned accounts and smart contract wallets are basically exactly the same and we are going to treat them as such and this default account contract which again I've got everything commented out you can uncomment it to kind of see what this looks like every single account every single smart contract account is set up as a default account so if we go to our metamask here and we take our wallet address and we go to the zync era sepolia Explorer or main net Explorer doesn't really matter we paste that in here it doesn't look like it's a contract right it looks like it's a normal wallet address there's no contract tab here Patrick what are you talking about well the zync Explorer is smart enough to know ah okay the code for this is a default account so we're going to show it as if it's not a smart contract wallet so we're going to show it as if it's a normal externally owned account and not a smart contract wallet however they are all smart contract wallets which I actually think is really cool because in this sense you know that every single address you interact with is going to be a contract and is going to have code and to me that actually makes stuff a lot lot easier now every single wallet including your EAS follows this interface follows this interface here which I think is really cool they have a validate transaction execute transaction execute transaction from outside pay for transaction and prepare for pay master and this looks really similar to what we saw on ethereum for our ethereum account abstraction but again because ZK Sync has account abstraction built in every single wallet has this account abstraction type functions that we can interact with and this is one of the things that makes zking so powerful is that it has this account abstraction built directly into the chain because of this it makes doing all this setup much easier right we don't have to deploy that entry point contract we don't have to send our user operations to an alternative mol and it cuts out the middleman here so every single account every single address will have these functions to some extent okay so knowing this we can now take this knowledge and actually apply it to what we're going to do here so we're going to create a oh I've already created the zkn folder we're going to create a new file called ZK minimal account. soul and we're going to get cracking and this is going to be our minimal ZK sync account abstraction account so we know we need this I account thing right we know this is the most important interface we need our contract to have these functions in order for us to use this account abstra action thing so let's go ahead let's import this and start from there so I'm going to do import I account lib Foundry era contracts SRC system contracts SL contracts SL interfaces account. soul and do a little toggle word wrap here so cool and now we're going to do contract ZK minimal account is I account like this oh and then of course let's do wow pragma can't believe I forgot that in the beginning MIT 0.824 boom okay now it's saying hey it should be marked as abstract let's just grab these functions in here boom we're going to copy paste them in here we're going to get rid of these comments here but you should add comments going to add these little semicolon bits here or these little curly brackets and one of the things we're going to need is this transaction call data transaction we go back into the I account it's pulling from this memory transaction helper. Soul so let's actually import that as well so we're going to do import transaction from and I'll explain what that means in a minute lib Foundry era contracts slsrc system contracts uh SL contract contracts slash contracts SL libraries slash memory transaction helper. Soul so now we have this transaction thing we have these functions let's keep going so probably the first thing that we're going to need to do here is understand okay what are these functions like what what are they actually doing and we can probably tell based off of their names but let's get a better understanding by going through the interface itself so the first one is going to be validate transaction and if we go to the minimal account. Soul this is going to be analogous this is going to be very similar to validate user op so in ethereum they're called user operations but since account abstraction is built directly into ZK sync ZK sync just says validate the transaction because it doesn't care if you send a an account abstraction transaction or a regular transaction considers all of them transactions so this validate transaction is going to be the zync equivalent of this validate user operation on ethereum they're user operations on zync they are just transactions and what's kind of cool here is there's this transaction struct transaction call data transaction I know that's a little bit confusing here and we're actually going to change these to memory though memory memory memory memory to make our coding a little bit easier because we don't really want to have to do a lot of like memory to call data conversions here but ZK Sync has this transaction object and I have created this memory transaction helper. soul that you guys can check out the reason I created this was to again make a lot of the development here a little bit easier some of the conversions between call data and memory kind of break a lot of things so I just said screw it for this tutorial we're just going to work with memory we're not going to deal with any of that conversion stuff and make your lives miserable but in this memory transaction helper there's this struct transaction so this is the structure used to represent a transaction in ZK sync and what's cool here let me zoom out just a little bit I know it's this kind of massive struct but what's cool here is every single transaction anytime you send a transaction on ZK sync it's this struct that's used to represent it and so if we kind of go through this we see first we see transaction type so Kira went through this a little bit on the different transaction types type one type two type three and the account transaction types of 113 AKA o x71 we have a classic from a classic to a gas limit more gas stuff more gas stuff more gas stuff a pay Master now this is going to be the exact same as a pay master in the ethereum world they're built natively into ZK sync you have a nuns you have value there's some reserved keywords for maybe in the future yeah for for this in the future we might want to add some new fields to the truck so just some Reserve stuff obviously the data signatures and and then this Factory depths which we will get to in a little bit these are actually really important pay Master input and then Reserve Dynamic again this is just kind of like a reserved extra space in the struct here every single transaction can be fit into this struct here essentially so when we and ZK sync send an account abstraction transaction all it's going to do is say Okay transaction type is going to be 113 from is going to be you know r ZK minimal account uh two is going to be blah blah blah Etc we could also send kind of a normal transaction type two and the account could be from whomever right so anytime we send a transaction in ZK sync it can be every single transaction is at some point put into a struct transaction into this struct here so when we do validate transaction we send a transaction hash suggested signed hash and then the actual transaction itself and when we call validate transaction one of the parameters is going to be the transaction struct which we will populate of course now what are these two the transaction hash and the suggested sign hash well let's go back to our I account here so the suggested sign hash is going to be the hash of the transaction so the TX hash is the hash of the transaction to be used in the Explorer and the suggested signed hash is going to be the hash of the transaction is signed by the EAS we are going to ignore these right now we're not going to use them this is something that something called the boot loader is going to work with which again we'll talk about in a little bit but for now we're going to pretend these don't exist and we're only going to focus on this transaction now what this returns is going to be the magic value that should equal the signature of this function if the user agrees to proceed with the transaction so it's a bytes for magic but you can kind of think of this as again like a true false because here if we want to have this return true all we would do is say like return I account account. validate transaction trans selector boom if we want this to return what essentially is true this is all we would return and just like in minimal account how this returned this validation data which has like a zero and a one and some other stuff this is kind of the equivalent of that where you just return the function selector and that's the equivalent of saying the transaction is valid so we're going to delete that for now though because we're going to actually learn how to validate this pretty soon so we're going to validate the transaction we're only going to focus on this transaction thing we're going to ignore these for now because we have to learn something in a little bit to understand these next we have execute Transaction what do you think this one can do well let's go back to the minimal account in our minimal account we have this execute function and we put this modifier on it require from entry point or owner or either the owner of this contract could call this execute or the entry point which was that account abstraction contract this execute transaction is the exact same if we want to directly call this function with an owner without going through the account abstraction proxy that is ZK sync we would just we would just directly call this execute transaction function and again this takes a transaction hash and a suggested sign hash which again we're going to ignore for now but it's given this transaction object so we're going to keep ignoring these for now transaction memory transaction boom this is to execute any transaction next we have execute transaction from outside let's go into to I account take a look at this one so this one doesn't have any comments here however what this one is is this is going to be the function that gets called for somebody else to execute a transaction so this is basically where if you sign ATX send the signed TX to your friend they can send it they can send it by calling this function so basically you create a transaction you sign a transaction you send it to your friend and then they call it with this function so execute transaction and execute transaction from outside essentially do the same thing is basically just going to be a hire admin calling this versus execute transaction from outside is going to be basically anyone being able to call this you can kind of think of this as the function that the entry point contract would have called in the ethereum world and when we create this function we're going to have to validate the transaction and then execute it pay for transaction this is similar in our minimal account to pay prund which was an internal function here in order to do account abstraction somebody needs to pay for the transaction so this is where you encode who is going to be paying for the transactions it could be your account it could be somebody else and then prepay for pay Master this is the function that gets called before you actually pay the pay Master if you have a pay master and again a pay Master is somebody who is going to be paying for the transaction so so this is essentially what we want to do so anytime somebody sends an account abst raction transaction here's basically going to be the process there's essentially two phases there's the validation phase and then there's the execution phase so the first thing that happens is the user is going to send their transaction to the ZK Sync API client I have here sort of a light node but you can basically just think of this as sending it to ethereum right so you send to the zync node then the ZK sync node checks to see if the nuns is unique by querying the nuns holder system contract huh wait what by querying the nuns holder system contract what is that and this is one of the biggest differences between ethereum and ZK sync ZK Sync has a large collection of these things called system contracts they're smart contracts deployed on ZK sync by default that do a whole bunch of very interesting things let me show you a very specific example this is address 006 so it's all zeros and then 806 and this is what's known as the contract deployer system contract on ZK sync if you scroll down you look at the contract tab you'll see a whole bunch of constants and you'll see this contract deployer Doo this is a contract that ZK Sync has on it by default so just by running a ZK sync node you automatically get this contract deployer smart contract and this contract governs actually deploying smart contracts yes I know crazy so on ethereum to deploy a smart cont contract all you have to do is send an ethereum transaction containing the compiled code of the smart contract without specifying any recipient doing that the ethereum nodes go ah there's no two here they're probably trying to create a smart contract I'm going to take their code and deliver it as such on ZK sync that's not how you do it you actually call a function on here create create two create two account create account you call one of these functions and it's these functions that will actually create a smart contract so ZK Sync has a lot of these system contracts at very specific addresses that govern a lot of the functionality that goes on in zync the contract deployer being one of the most important ones this is also why when trying to deploy a smart contract to ZK sync we can have a hard time so Forge create with Foundry does this ethereum addition right it sends an ethereum transaction containing in compil code smart contract without specifying a recipient this is why we have to do Forge create-- ZK sync D- Legacy because Foundry ZK sync sees this leg C sees this and goes ah okay they're probably meaning to call this create function on the contract deployer system contract so this is why actually a lot of these different commands don't quite work for ZK sync as of today with Foundry because of these system contracts now these system contracts actually make it a lot easier to interact with ZK sync because if you want to just do anything you just send a transaction and you say hey I want to create account and you call a create function and arguably that's actually much simpler but it's one of the biggest differences between ZK sync and ethereum is going to be these system contracts in the zc casing documentation there's a ton of information on the different types of system contracts what they do and then how to interact with them as well so in any case put this a little bit earlier so this is going to be the life cycle of a type 113 AKA a0x 71 transaction so this is the life cycle exclusively for an account abstraction transaction okay so phase one in the validation the zisc API checks to see the nuns is unique by quering the nuns holder system contract so another one of these system contracts is this thing called The Nuns holder what this contract has is it has a ton of mappings where it has the nuns of every single smart contract on ZK sync yes so you can look up the nuns of every single smart contract on ZK sync by querying this nuns holder contract so this nuns holder smart contract has a mapping of every single account every single account address and the nuns that they currently are working with the second step in a zync account abstraction transaction is going to be checking the nuns holder system contract making sure that it's good then the ZK sync node is going to call validate transaction which must update the nuts so in our ZK minimal transaction whenever we send an account abstraction transaction this validate transaction function is going to be called and if this bytes magic returns a a valid magic value then these ZK sync nodes will go cool this transaction looks good but if not it will say uh-uh no good here so then a question should probably come up okay so we're calling this Val transaction thing but it must update the nuts so then this is actually not going to be a view function this is going to be like a legit transaction so the question is so who is the message. sender when this is called so so are you telling me Patrick that anyone can call validate transaction and then just update the nuns that sounds insane well that would be insane which is why we don't want to allow that so Patrick you're saying we must update the nuns so who's the message. sender when is called well whenever you send a type 113 transaction the message. sender the message. sender is always going to be this thing called the bootloader system contract now the bootloader system contract you can kind of think as like the super admin system contract of all these system contracts so whenever you send this type 1113 transaction it will be rerouted to this bootloader system contract this is how zync has account abstraction built in it has this bootloader system contract you can kind of think of this as the entry point smart contract on ethereum mainnet so for everything that happens in here the message. sender is always going to be the bootloader system contract make sense Okay cool so Sy API client aka the zky node will call this validate transaction which is going to update the nuns and we're cool with that because it's going to be the bootloader system contract that actually is doing that call so we're probably going to to want to restrict the functionality of validate transaction here so that only the bootloader contract can call this once because we don't want anyone updating our nuns willy-nilly next the ZK Sync API client aka the ZK sync node will check that the nuns is actually updated so if this doesn't update the nuns whole transaction will revert then it will call pay for transaction prepare for pay master and validate and pay for pay Master transaction so basically it will call and do all the functionality for paying pay for this transaction before actually sending the transaction to see if there's enough money to be to pay for it and once this is called it will verify that the bootloader gets paid so there needs to be a there needs to be a balance inside of the bootloader kind of similar to what we did with minimal account how we sent the well we have message. sender here but this is the entry point how we sent the entry point funds kind of same thing with ZK sync we just have to send the bootloader funds and then if it passes all of this the validation phase is done and then we move on to the actual execution phase of the transaction so in the actual execution phase this ZK Sync API client will pass the validated transaction to the main node sequencer so everything in validation kind of happens in this like we said this light node so you can kind of think of the ZK sync system is having a whole bunch of light nodes or API client nodes and then the main node the main sequencer node so the main node and sequencer as of today are both the same but maybe in the future they get split up Kira does a great job talking about why centralized sequencers are bad and and as of today ZK sync is working on decentralizing the sequencer so that there's not just one but as of today there's just one the reason that they kind of have this split up into two is it would be very bad if the main node was stuck validating transactions all day so they have this kind of client API this light ZK sync node do all the validation once the ZK sync light nodes validate that the transactions are good only then do they pass it over to this main node so we don't get a denial of service attack if you're unfamiliar with that don't worry about it then the main node will finally call this execute transaction function so very similar to how the minimal account we have execute where we have require from entry point or owner we're going to do the exact same thing in here this execute transaction we're going to say require from bootloader and then finally if a pay master was used the post transaction is called so if there's any type of post transaction we're not going to be worrying about that but that would that then be called so that is the whole process of running a type 113 account abstraction transaction on ZK sync this is going to be the whole process and we're going to see that flow go through here now you might be asking hey Patrick what about execute transaction from outside well we're going to set this up so that anybody can actually call This And they just still have to run through the same transaction validation as everybody else does so this is where the bootloader calls it this is where anybody can call it you'll see what I mean when we build it out but this is the flow that we're looking to do we're going to work with these system contracts we're going to do a lot all right so even though we've barely even coded anything we've really just kind of been talking we've already gone through a lot so I want to take a quick breather a quick refresher on kind of all the things we just learned because I just threw a lot at you and it's okay if it doesn't quite make sense the first time here right so follow along with me code along with me here and I promise you it'll make sense be sure to use the GitHub discussions be sure to ask questions in the community because this is a crazy unlock this is a crazy PowerUp that not a lot of people are taking advantage of so let's do a quick recap of all the things we're doing here so an account abstraction transaction is called a type 1113 transaction and unlike ethereum where you actually have to send your transaction to an ALT group of nodes which will then send it to an ethereum node on ZK sync all you have to do is say hey this is an account abstraction transaction and you can send it directly to the normal ZK sync nodes when you do that a ZK sync system contract called the bootloader is going to take ownership of that transaction in ZK sync ZK Sync has a group of what's called systems contracts these are special contracts in the zyn ecosystem with very unique privileges locations and update mechanisms one of the simplest ones is going to be the nuns holder smart contract which is literally a smart contract that has a mapping of all the nses of every single account every single address in the blockchain when we send an account transaction transaction a whole bunch of validation happens where the ZK sync node will call validate transaction to increment the nuns if the transaction is valid it will then pass it to the ZK sync sequencer to finish executing the transaction we can additionally sign a transaction and let people call execute transaction from outside where where the bootloader isn't the message. sender where whoever sends the transaction is message. sender but we want to make sure they run through the same validation as the bootloader would run through and of course if we call execute transaction from outside whoever is calling this is going to have to pay for the gas whereas when we do the execute transaction and validate transaction the pay Master will pay for the gas so cool so I know that's a lot but stick with me we're going to build this it's going to be quite cool and I am going to challenge you after this to build your own own codified rules for account transactions some really easy ones could be like a spending threshold and some more difficult and more interesting ones could be like all right you're going to sign a transaction with your GitHub keys with your GitHub session keys if you do that that would be very cool all right well let's get cracking building our codebase here and I want to just already clean this up with some headers external function grab that paste it here external external external and then we'll also do internal functions like this boom because we're going to have some internal functions because we're going to reuse some code across some of these so the first one that we're going to have to work with and probably the most important one it's going to be this validate transaction right so we must increase the nuns for this at notice and we must validate the transaction oh and actually before we keep going we should do a Foundry up ZK sync make sure we're working on zky Sync here do a forge build- ZK sync and we might have to wait a little bit for this and great after a little bit of waiting we actually get an output here now there's going to be a lot of warnings in here because a lot of the cheat codes we use in Foundry give basically warnings for ZK sync because again ZK sync and ethereum are slightly different they don't use the same evm they don't use the same op codes so we're going to get all these warnings but as long as none of these are warnings with our actual code base that we're going to deploy these are pretty safe to ignore and it looks like that is the case so cool and we'll periodically be compiling as normal just to make sure stuff works so we're going to do this validate transaction and this must increase the nuns it must validate the transaction we're once again going to do check the owner sign the transaction and we'll go into this transaction object again so we're going to have this be real similar to what we did with the ethereum minimal account where it's just the owner there's a single owner there's no cool rules here if you want to go do cool rules later on you absolutely can we should also it doesn't say that we have to do this but since we're not going to be adding a pay Master right we're not going to be doing kind of any of these clever cool payment stuff we will also check we'll also check to see if we have enough money in this wallet to pay for the transaction and that's pretty much it so let's go ahead and jump into here so the first thing we're going to want to do is we're going to want to increment the nuns so every single one of these wallets every single one of these accounts comes with a nuns and it's this nuns holder system contract that keeps track of the nses and it's also what we'll have to use to increase the nuns so you can see there's increase min nuns in here set value under nuns there are all of these different methods in here here to actually increase the nuns and and work with nses for us to actually increase the nuns we have to do what's called a systems contracts call so calling these systems contracts isn't quite as straightforward as just okay drop in the address and call it now making sure we call a system contract actually requires a couple of special things we need to do on the nuns holder we're going to need to call this function here increment Min nuns if equals so basically we're going to pass it the EXP expected nuns of our account which will start off as zero and if it is zero it'll go ahead and just add one right so we have this raw nuns' address as key old raw NS plus one so we're just going to increment the nuns by one here so we need to call nuns holder and then increment the nuns of our ZK minimal account to do this we actually have to in our Foundry dotl we have to add a flag underneath remappings we have to add this is system equals true so and this is a going to be a little bit confusing and if it doesn't make sense the first or second time this is going to be one of those times where I just say hey don't worry too much about it so I asked this question on stack exchange ethereum and luckily the ZK sync team actually responded and I asked for some clarifications but essentially what happens whenever you pass the is system flag to the contract it will inline replace all simulations with their is system call counterpart so calling system contracts in ZK sync is actually very difficult so what the compiler will do what the ZK sync compiler will do is if you have this is system equals true it'll say okay well anytime I see a very specific call where the data is X Y and Z I'm going to convert that into a system contract call these are called ZK sync simulations so if is system is true very specific calls are going to turn into a system contract call once it's compiled right so if we look in the ZK out from our little compilation here we can even go into where is it ZK minimal all the way to the bottom ZK minimal count the Jason this bu code here this if you're familiar with evm by code is not not ethereum buy code at all this is ZK sync byy code which is completely different than ethereum byy code but making a system contract call can be quite complicated so basically system is true says anytime you see this specific data inside of a call turn into a system contract call so and here's a good example for example if there's a simulation like so call address 25 with data 7 string hello secret thing if this is a simulation or basically a a key phrase or a key word or a key call that's equal to the system contract. update nuns holder one if is system is false is passed to the compiler the codebase will just stay as this right it'll do this weird call to random nowhere bill but if his system is true it'll automatically transform this into system contract. update nuns holder so whenever we compile a smart contract like this we need to have is system be true or false and if it's true anytime it sees one of these very specific calls it'll transform it into a system contract call you can almost think of these as like kind of very specific keywords very specific variables that ZK sync searches for whenever it compiles to swap out for a system contract call so we want to do this system contract call so we're going to use some tooling to do this system contract call and make it very obvious to us that it's a system contract call and very obvious to the compiler that's a system contract call so we're going to use this Library called the system contract caller to do this so I'm going to go ahead and import this system contracts caller from libf foundary era contracts slsrc system contracts SL contracts I probably should have put a remapping in for this huh um slash libraries slash system contracts caller. Soul like this now this library has a lot of stuff in it it's got a lot of different addresses but the main thing that we're going to be using it for is the system call with propagated revert and it's this function that's going to help us make these system calls make these simulations without us having to really kind of know exactly what's going on here so we want to call the system contract all of this is if this systems contract stuff like doesn't really make too much sense to you for now like I said don't worry too much about it just kind of blindly follow along and just know that this is what we have to do to update the nuts and there's going to be a couple of times when we call one of these systems contracts and just in order to call the systems contracts you need to set this is system to true just know this is how we call the system contracts we need to update the NS so we need to use this system contracts caller dot system call system call with propagated revert this is going to help us do that system call and in here we need to pass a gas limit to value and data so gas limit for here we're just going to do a uent 32 whatever gas is left we're just going to pass all the gas that is associated with the transaction two is going to be the nuns holder system contract contract so we're going to need to get that nuns holder system contract we can get this from a constants doou file in The Foundry error contracts so all of the constants are in here this is setup for ethereum this is setup for ZK sync mainnet technically if you look in the true zync codebase these system contracts addresses can actually change but we've hardcoded it for now if in the future these addresses change I'll go ahead I'll update the addresses I'll update the dependencies just go ahead and check the minimal account abstractions just go into this make file and just use the same versions that I'm using in here so that you always know you're using the correct versions but in here there's a nuns holder nuns holder system contract with an address over here it's based off of an offset so we're just going to use the address of this nuns holder system contract so we're going to need to import that as well import the nuns holder system contract from lib slf foundary era contracts SL uh SRC SL system contracts SL contracts SL libraries SL SL constant. Soul like this and so we're going to call the address of this nuns holder system contract and what's kind of cool is if you're in this constant. soul you can see the nuns holder is at the system contracts offset plus 0x3 so we can look at the systems contract offset is this if we take this address and we go to ZK sync era Explorer it's basically saying okay at 0x 8003 this should be the nuns holder so hold on let's just do a little popup open chisel we'll do address my Addie equals this or address like this we look up my ADD boom it's the address we get pop this into the Explorer we can go and see that this is indeed the nuns holder system contract so that's actually pretty cool and yep same thing it has all the same functions both the same read and write functions for working with Nunes which is very cool so we're going to send the gas the nuns holder system contract it's going to be the two we're not going to send any value and then we're going to do ABI do encode call so encode call is kind of a nice newer way to do encoding it's kind of similar to encode with signature but we're going to call that increment Min nuns if equals so I'm actually going to to actually work with that I'm going to import I nuns holder from libf foundary era contracts slsrc system contracts SLC contracts SL interfaces SL I nuns holder. Soul like this we're going to say ABI dood call I nuns holder do increment minant if equals comma transaction. nuns or excuse me undor transaction. nuns so this transaction object as we've seen and has a nuns value that needs to be sent so we're going to say increment the nuns whatever nuns that was given to us we're going to take that nuns and add one and this is all we need to do I know it sounds like there was a ton we needed to do but this is really all we need to do to increment the nuns it's just this one systems contracts call to increment the nuns and then we're good to go this also has some return data we're going to ignore the return data though now I know there was a lot here so I'll do a quick recap again because these are this is pretty complicated stuff so this is what's known as a system call simulation zync sees this and it goes oh okay that's kind of a weird call I'm not going to let you call the systems contract unless you have is system is true in here then I'm going to transform this into a systems contracts call the nuns holder system contract controls all the nses it has a function called increment Min nuns if equals and that's how we can increment the nuns of our ZK minimal account so we've incremented the the nuts next what we need to do okay we're going to need to check for fee to pay we're going to need to check the signature of course which were signature Wizards at this point and then return the magic number so each transaction is going to require a certain amount to pay to be paid right same as ethereum so we have to calculate how much this transaction is actually going to cost we don't have to do the math for that there's actually a tool that zync has built that will allow us to get that ourselves so it's called the transaction Helper but we're going to use this thing called the memory transaction helper that I made to make it easier to do pretty much everything that we're going to be doing so so we're going to import this and actually it's in the same place that the transaction object is in so we're just going to import it from that memory transaction helper. soul and in this there's a total there's a function total and in this there's this function called total required balance which basically takes this transaction and figures out how much is required to actually send the transaction so what we're going to do to check the fee to pay is we're just going to do a u 256 total required balance equals transaction. total required balance and oops excuse meore transaction. total required balance and we're going to need to use this Library so using memory transaction helper for transaction like this so we're going to get this total required balance and then if this total required balance is greater than address this. balance we're going to revert and of course we're going to use a custom revert so error ZK minimal count not enough balance this and we'll revert with not enough balance great so that's it check into fee to pay does this contract have enough balance again this is where we could add some pay Master stuff we could say hey uh so and so somebody else has signed up to do the payment and here's all the logic to do all the payment stuff but we're not going to be adding any of that customization we're just going to have the money in the ZK account minimal pay for the transaction so this is how we're going to check that and then finally the important stuff we're going to check the signature in a very similar way to how we did it with ethereum so first we're going to get a byes 32 transaction hash is going to be equal to theore transaction. or excuse me encode hash so this memory transaction helper has another function called ncode here where it does some very clever encoding so one of the most important things is it needs to know what type of transaction is it is it a legacy trans transaction type which is again type what type zero is it a EAP 712 transaction type AKA a account abstraction transaction type akaa type 1113 yes these are all the same thing okay that needs to be encoded a little bit differently is it a 115 AKA a type 2 transaction is it a 2930 AKA a type one yes there's so many different transaction types there's also blob transaction which which is a type three but it's not supported at zync at the moment anyways so each one of these transactions has a different function that actually governs how they are encoded so this memory transaction helper already helps encode it for us boom we have this encode hash EAP 712 transaction we already kind of learned about encoding and stuff right now so we're not going to go deep into it we're just going to trust that it works we're going to say transaction hash is transaction. encod this trans action object like exactly like the user operation has a signature and this is what we need to validate on it so we're going to get that signature we're going to saycore transaction. signature and we're going to need to combine this with the txh and we're going to have to figure out how do we actually validate this well exactly the same as with the minimal account we're going to have to take this transaction hash and convert it to an eth signed message hash and what what have we been doing while we've been using open zeppin so we're going to do a little import here message # utils from at open Zeppelin SL contracts SL utils SL cryptography SL ms. Soul like this opens up on Capital H there so that it actually works now that we have this we can scroll back down and we can do this once again message m.2 e sign let me zoom in signed message hash of the TX TX hash so we're going to convert this hash to the correct format here we'll say bytes 32 converted hash equals this and then we're going to do the classic recover so we'll say address serer equals ecdsa recover and this we're going to have to import that as well let me scroll back up do a little import ecdsa from atop Zeppelin contracts SL utils cryptography ecdsa Doo so we're getting the ecdsa now we'll call ecdsa recover and this will be the converted hash and the underscore transaction. signature like this we'll get the signer now that we have the signer we can check we can do a little bull is valid signer equals and all we got to do is check to see signer equals equals owner which we actually don't have an owner function yet we should definitely add this so let's import ownable as well import ownable from at open Zeppelin SLC contracts SL access slown and we'll make our ZK account minimal is I account is I account and is ownable which means we need to add a Constructor so we'll add a Constructor ownable message. sender Tada brilliant okay so it's a valid signer if the signer equals the owner and if it is a valid signer then we're going to say this magic then we're going to say this magic is the account validation success magic this is kind of the equivalent of saying true and we can import this as well in this from the same place that I account is in account validation success magic so if it's true do that else we can just say magic equals bytes four of zero and then just and then finally just return magic so this is our validate transaction function yay so now like I said we are completely ignoring these so I'm even going to comment them out like this since the boot loader is technically going to be the one that calls this and we'll add some access controls like that in the future zync allows you to do some really crazy customizations with your transaction hashes so you can have some literally like vanity transaction hashes which is pretty cool and you can like save some gas if you have some pre-processing steps with the suggested signed hash and you can do some other really creative stuff with these two variables our code base is going to be super simple super minimal so all we care about is the transaction and we're going to completely ignore these make sense so here's what we do with this validate transaction first off we must increase the nuns boom we make systems contract call to the nuns holder system contract and we increase the nuns that's one of the other things that's so cool about CK Sync here is we have power over our nuns we can control our nuns in our smart contracts very cool stuff then we check if we have enough money in our smart contract to pay and there is a nice little function that comes with our transactions called total required balance that we can use to make sure we have enough money and then we do the classic signature checking first we encode our transaction struct exactly the same as we did with ethereum we use a little helper function called encod hash to actually encode it then we convert it to an eth signed message because we got to have things in the right format then we run the ecdsa recover to get who signed this hash then we check to make sure the signer is the owner of this contract and if it is we say hooray we did it and if not we return bytes four of zero which is basically the equivalent of say saying false so this is how the ZK sync system is going to validate that a transaction sent via account abstraction is valid now the only additional piece we need to add to this is we need to make sure only the bootloader can call this right because we don't want anybody just updating the system contract we only want the account abstraction system to be able to call this validate transaction and increase the nuns so we're going to have to create a modifier here very similar to the old entry point modifier where we're going to do a little first off I want to do a headers modifiers like here do a little modifier zoom in a little bit modifier Quire from boot loader and we're going to have we're going to say if message. sender does not equal the boot loader formal address and we're going to import this in a second then we're going to revert with ZK min minimal account uncore not from boot loader like this we're going to have another error zync not from bootloader and then we need to import the bootloader formal address and guess what we can get this from the same place as the nuns system holder contract this is in the constants do solve we look for this boom address payable constant bootloader formal address so this is where we get the bootloader formal address from okay okay nice so we have require from bootloader let's make sure we actually add it here require from bootloader only the bootloader can update our transaction hashes only the bootloader can now update our Nunes and we have a way to validate our account abstraction transactions are valid I always feel like I'm speaking poetry when I say account abstraction transaction all right so check we've done some validation cool after we get all the validation done the ZK sync node that got the transaction is going to send it from itself to the main node the main sequencer and that's going to call execute transaction so let's now focus on execute transaction and make sure we get this one right don't worry the rest of this will come together and it will make sense but we're going to call execute transaction because this is where we do the thing so same thing we're going to ignore these first two these are for some cool advanced stuff that we quite frankly don't care about and may never care about to be honest so we're just going to comment these out and we're only going to care about this transaction object and this is going to be the exact same transaction object that was recently called through the validate transaction function so execute transaction here we're going to do something very similar to what we did in the minimal account on ethereum so first thing we're going to take this transaction C object and we're going to get the two from it so address two and again we can go into the struct we can see okay what this has transaction type from to Gess gas gas pay Master NS value Reserve data signature blah blah blah all this stuff we're going to get the two we're going to say 2 equals address 160 transaction. two right and we have to do this because two is a u into 256 so we need to convert it from a u 256 to an address next we're going to need to get the value which if we look in here value is a uent 256 we're actually going to need to Safe cast it to a uent 128 the reason that we have to do that is we might have to use value as a system contracts call and it takes a u 128 so U into 128 value equals uh and we're going to use some utils here that we haven't imported yet I don't think we've imported these yet have we we haven't imported these yet but we will utils safe cast to u32 or excuse me to u 2 U 128 excuse me this is transaction. valal like this and we have to import this utils so The Foundry era code base has a utils and let's actually Oz Imports and these will be era Imports era standing for like ZK sync ZK sync era Imports so we're going to import this utils library from libf foundary era contracts SL SRC system contracts SLC contracts SL libraries SL utils do s like this and now that we have this utils bin here we can now call this safe cast to you in 1228 so we're going to get the value and then we're just going to get the data so we're going to say bytes bytes data equals transaction. data and we're going to be making uh bytes memory excuse me bytes memory data and we're going to be doing something real similar to what we did in our minimal account right remember in our minimal account we just did a call and then if there wasn't a success we reverted we are are essentially going to do that but we're going to tweak it a little bit so for our minimal account we did it like this for here we're actually going to do it a little bit differently we're going to use assembly so if we go to the zkc docs call static call and delegate call actually work slightly differently so ideally we're just going to follow the ZK sync way and do these calls in an assembly block if you're not too familiar with assembly I know we haven't really gone over it yet we have an assembly in form of verification course that you can definitely check out for now just kind of blindly follow along with me here we're going to have this assembly section we're going to say success dot or colon equals call we'll say gas to Value add data ox20 comma M load data and then zero and zero and we'll say before this we'll do Bo success like this and this is how we're going to make calls so this is essentially the same as doing this just in a little bit lower level language don't worry too much about it if it doesn't make sense and then of course if this fails we'll say if not success then we're going to revert ZK minimal accountor execution failed failed like that go back over to the top error execution failed like this cool now this is what we would normally do so this looks pretty good however I hate to say this we do have to tweak this however if two was to A System's contract for example if execute transaction here was deploying a contract the two would be to the deployer system contract and if that's the case we actually have to call the system contracts caller in the same way we did it with the nuts holder up here so we actually have to tweak this just a bit so we're going to say if 2 equals equals address of the deployer deployer system contract contract contract and we can actually get this from the same place we get the bootloader from that constants folder so we'll just import that as well so if two is going to be that deployer system contract we want to do something different so we could do like if 2 equals any of the system contracts and write some custom code for any of the system contracts but deploying a contract is a pretty common thing so we at least want to be able to handle that if it's to a deployer system contracts we're going to do U into 32 gas gas equals U tills do safe cast 2 u32 gas left like this we're going to do that system contracts caller again. system call with propagated revert gas to Value data else we're going to do kind of this normal call here so we could put a lot of conditionals for a lot of the different system contracts for us we're only caring about deploying if you want to deploy from this Minal account this is kind of how you would do it and since we learned about system contracts a little bit already you can if you want to customize this to do even more crazy things with the system contracts you are more than welcome to do so but with that being said we now have the execute transaction function just about done we do want to add a modifier here because right now anybody can call this so we're going to scroll up we're going to add another modifier and we're going to give this kind of the the same Powers as our minimal account we'll say require from bootloader or owner like this and we'll do if message. sender does not equal bootloader address and message. sender does not equal owner then we're going to revert not from bootloader or owner like this and we'll create a new error right here like so and then require from bootloader owner We'll add add this to the actual execute so that only the bootloader or the owner contract can do this and this is really almost exactly the same as this require from entry point or owner in our minimal account on ethereum nice now with this we pretty much have our ZK sync native account abstraction codebase done which I know is crazy however I said nearly because it's not quite done we still need paying for the transaction in ethereum happened in this validate user operation for here the validate user operation we just check to see if we can pay so the actual payment happens down in these transactions here so let's actually figure out how to do this payment here so we're not using a pay master so we're actually going to make this do nothing TAA this one's done hooray so prepare for pay Master we can keep blank however we do want to actually pay for transactions here otherwise our transactions will fail and it's still in that validation phase actually before gets the execution that the pay for transaction is called so this actually happens before that execute that we just wrote happens so same thing though we can ignore the transaction hash we're going to ignore the suggested signed hash we're just going to focus on the transaction itself and luckily once again in our little memory transaction helper there's a helper function in here called pay to the bootloader which will get the bootloader address figure out how much we need to pay and then actually pay it so all we have to do is do underscore transaction. pay to the bootloader like this and we'll just say bull success equals pay to the bootloader if not success then revert revert ZK minimal accountor failed to pay and then we'll add this new error back at the top error right here and that's it so now we can pay for the transaction we can execute the transaction we can validate the transaction we are pretty much done the only final thing that we want to be able to do is call execute transaction from outside so right now if we sign a transaction we can send it to the ZK sync node as an account abstraction transaction however we could also send it as a normal transaction with everything signed and have somebody else just pay the gas fees to send it and that's what this execute transaction from outside is no bootloader stuff no account abstraction stuff this is like hey you can send my transaction and you will pay the gas right no account abstraction stuff just hey send this and and we can set this up so that it goes through pretty much the same process as the execute transaction bit here all we'd have to do is first validate this transaction kind of the same way we did up here and then execute the transaction so what we're going to do is we're going to take all of this here and stick it in its own function so we're going to do a little return uncore validate transaction action _ transaction at the bottom we're going to create a function undor validate transaction it's going to take a transaction memory underscore actually I hate the underscore transaction this will be internal and I'm going to paste all that code in here and I guess I'll use the underscore because we're using the underscore in here and so this is going to do exactly what we did before call the nuns contract check to make sure we have enough balance get the magic and then I guess I'll just say return return bytes for magic right here and then boom we return magic at the bottom so for validate transaction in our validate transaction function now all we're doing is returning this internal function validate transaction and we can take this same logic bring it into execute transaction from outside where we first validate the transaction and then guess what next we execute the transaction with underscore transaction like this so let's create another function where we did the exact same thing do a little function execute transaction transaction memory transaction although I hate that style guide internal like this and we're going to take all of this stuff in the execute transaction copy it paste it in our function down here that looks pretty good to me we're not returning anything and so now we're going to delete what's inside of execute transaction where did that go oh I already did okay nice and we're just going to call execute transaction uncore transaction like this and in our execute transaction from outside we're just going to call execute transaction so we could 100% say hey you're not allowed to do this but why not it's going to go through the exact same flow and if somebody else wants to pay for the gas to send a transaction great good for us we're still checking the signatures work we're still executing the same way it's still going to come from our account if somebody else wants to pay for it phenomenal and then the last thing we need to do is of course this needs to be able to receive funds so we'll add a receive function external payable so that payable this can actually receive funds like that all right cool and this my friends is our ZK sync minimal account abstraction contract let's give this a compile and make sure this works Forge build-- ZK sync and it does now sometimes with Foundry ZK sync I find it has a little bit of a hard time sometimes so sometimes I will click ZK out out and cache and delete everything in here and recompile and this will take a long time to recompile however I've still found it can be very helpful just in case you tweaked something that was potentially off and it looks like it has compiled successfully so I know there's a lot here and I know we've gone over a lot and I know we're learning a lot and I know we're learning at kind of a breathtaking speed here but this is incredibly powerful work that you're doing you're enabling yourself to have skills that very few people in the industry have right now and you should be very proud of yourself so what we're going to do for the rest of this is we are going to write some tests of course the test setup is actually going to look really similar to what we've already done there's very little we have to actually learn we just have to write the tests however we're not going to write a script to actually do this like what we did with the send packed user Ops and it's because Foundry scripting doesn't work great on ZK sync at the moment so to actually run this and actually work with this I actually wrote a lot of JavaScript scripts to actually get this to go because the JavaScript scripts was work very well with ZK sync at the moment so I'm just going to walk you through my scripts once we get to there and I will actually send a true account abstraction transaction on the ZK sync test sapoia I highly recommend that you don't do this unless you really really want to see because again you're kind of clogging up the test Nets and you have to get the test net zik sync aoia which can be really hard to get your hands on if you want to try this on a local network I highly recommend you give that a try and because my scripts here are written in hard hat I didn't go as hard as I normally do making the code look very good those are our next steps we're going to write some tests then I'm going to show you my hard hat scripts for actually deploying this then I'm going to deploy this and I will show you exactly what this process looks like when you get a successful transaction to run if you're a little mentally exhausted now was a great time to take a break I know I'm throwing a lot at you right now so it is okay and maybe if anything in here doesn't make sense to you it's not clear it's like what is he talking about pay Master this system contract that it's a great time to ask questions and one of the things I actually really like about the ZK sync Discord if you scroll to the bottom of their docs they have a little Discord icon they actually have an AI that has read all of their documentation that you that does a pretty good job of answering questions related specifically to ZK sync docs it's in the Discord it's a great tool definitely be sure to use that as well so take that mental break and I'll see you in a minute all right so now that we have our ZK minimal account let's go ahead new folder ZK sync create a new file ZK minimal test. t. soul in here and we will go ahead and start testing this so you already know the drill we're going to pop open this pragma we'll do MIT 0.824 contract ZK minimal account test is test like so we'll import test from forg STD test. so we will add a little function set up Public public in here and we will get Kraken so if you're following along with the GitHub repo associated with this lesson in the tests that I wrote I actually went ahead and I did this kind of setup here where we see where we we have if it's not the zync chain we're going to deploy with the deployer but if it is the zync chain we're going to go ahead and deploy with new ZK minimal account so we're going to skip this for those of you watching this in cphon updraft we showed you this is ZK sync chain using The Foundry devops tool for those of you who are watching this on YouTube you can just kind of ignore this because we're not going to be working with this anyways at least I don't think but the reason that we have that is because the zc casing chain like we've been saying some of the cheat codes and the scripting don't quite work the same way they do on other evm chains so we're going to skip that the deployment process if you want to have a productionize deployment process for ZK sync you'd have to write some bash scripts which you can do get really creative with your Forge create get up copilot and chat jbt are actually phenomenal at writing bash scripts they're actually much better at writing bash scripts than they are at solidity so you can use that to help you out so but in any case we're going to import that ZK minimal account from SRC /zk sync did I do a capital S no I didn't I did lowercase CK sync you know and let's keep that let's keep this lowercase down here too just so that it's all symmetric across the board ZK sync ZK minimal account. Soul like this and then in our setup we're going to have ZK minimal account I'm just going to call it minimal account like this we'll just do minimal account equals new new ZK minimal account cool now we're going to have a whole bunch more setup stuff here but let's just go ahead and kind of try to mimic what we did with the minimal account tests do basically the exact same thing here right because this ZK minimal account is literally the exact same thing as the one on ethereum except it has native account abstraction built in so what was the first test we did for the minimal account okay well we test the owner can execute commands right and this is where the metamask directly calls the wallet and it executes to do this with our ethereum account abstraction account we use the execute command and we sent the destination value and function data for our ZK sync minimal account if we scroll down what's the function that we have in here we have execute transaction which is required from bootloader or owner and we're going to pass it a transaction object that we're going to go ahead and we're going to build inside of our test here so let's do a little something similar here function test Z K owner can execute commands public like this one we'll do a little arrange act assert because I love to write that so for arrange we're actually going to do a very similar setup to what we did with our ethereum account so we are still going to need an address destination and that's going to be some mock ec20 so let's go ahead and actually import that as well we can pop back open our minimal account Min Min minimal account test. T.O we can grab this mock copy that line paste it in here and I'm I'm just like clicking the line and hitting command C I think it's control C for Linux and windows and if you just put your Cruiser on the line and hit command C or copy and then command V or control V that'll copy the whole line and then paste the whole line so we'll do that down here uh we'll do we'll actually create a new usdc token so we'll say usdc equals new erc20 mock like this a lot of the setup is actually going to look really familiar to what's in here so our destination is going to be that address of the usdc we're going to do a unit 256 value equals 0o and we're still going to do a bytes memory memory function data exactly the same as what we did in our test over here let me scroll back down exactly what we did over here this is going to be ai. encode with selector erc20 mack. mint. selector and then what do we do over here we give it the address minimal account and then some amount so let me copy this amount line as well we'll have an amount at the top and then we'll pass the address of our ZK and let me do a little toggle word wrap ZK or sorry Minal account and then comma amount like this now what did we do next in our ethereum account abstraction well all we did was call execute with destination value and function data however for the ZK sync minimal account we actually have to create this transaction object which is kind of similar to the user operation so we created these user operations in the minimal account using some scripting we don't have a script for this so we are going to have to create some helper functions in our tests so I'm going to do little headers helpers like this we are going to have to make a function which creates that unsigned transaction so I'm going to create a little internal function down here function create unsigned unsigned transaction and this will take an address from a ENT 8 transaction type and address to un 256 value and then a bytes memory data this will be internal View and this is going to return a transaction trans transaction memory like this so we don't have this transaction we're going to go have to go ahead and import this transaction struct import transaction from and this is from that memory transaction helper thing that we have so it's going to be lib slf foundary era contracts slash SRC SL system contracts contracts SL contracts SL Library SL memory transaction helper. soul s cool and if we go back in here it's this transaction struct right so we have to populate this in the same way we had to populate that user packed operation or that user operation right so let's go ahead we'll populate this struct so we can send a transaction to ZK sync again this is one of these cool things about ZK sync is all transactions are these transaction structs so let's go ahead and scroll down create unsigned transaction let's do a let's go ahead and we'll just do return return transaction and let's open it up and let's just kind of go through this and get it done okay first transaction type transaction type is going to be whatever we pass in for transaction type remember for us we're going to be doing a type 113 which is AKA 0 x71 transaction but you could 100% have this be you know a type two a type zero a type one or even a type three which is a blob transaction we have a little video on that as well but we're going to be doing type 113 for account abstraction transaction I think I love saying that um what's next we're going to need a from to gas limit so we'll say from is going to be whoever we pass in two is going to be two now about the two though in these transaction type from and to are actually both uent 256s so so we actually have to convert these from addresses to U 256 so to do that we'll do a ENT 160 first and then a ENT 256 so this is typically how you convert from an address to U 256 you first convert it to a uent 160 and then you do it to un 256 the reason for this is because addresses are actually smaller and they don't really fill up the full 32 bytes whereas the unit 56 fills up the full 32 bytes that's a much longer com that could be a longer conversation if you're interested be sure to check out the assembly and formal verification course in cyphon updraft then we're going to do a little gas limit we're going to cheat we're going to copy a little bit of what we did in our send packed user op because we did a lot of this stuff down here we're just going to use this giant number boom gas per Pub data byte limit we're going to do the same thing and this is the maximum amount of gas the user is willing toay pay for a bite of Pub data Pub data is published data to the L1 we don't have to worry too much about this one so we can kind of just pick any value there we need Max fee per gas we're just going to use this again we're just basically going to say yeah let it all go through we don't really care we need Max priority fee per gas we're going the same thing don't really care pay Master none we're not using a pay master nuns is going to be the nuns that we get so we're going to do a little un 256 nuns equals vm. getet nuns address minimal account and this is kind of a cheaty line that doesn't work super well for zync because again zync has a nuns holder smart contract that needs to be queried and this cheat code I'm not sure at the moment is supported but hopefully in the future this automatically gets rerouted to just asking the nuns holder smart contract for the nuns so for nuns we're going to say nuns value we're going to say whatever value is passed value which will be zero reserved is just going to be this blank array so this is kind of just reserved for different slots in the future so for us we're just going to say un 2560 we do that four times that data is going to be the data that was passed in signature for now we're just going to leave as blank because this is just getting the unsigned transaction here and we'll sign this in a little bit Factory depths this is something that we're going to learn about in a bit it is actually pretty important for now we're going to leave this as blank so at the top we do bytes 32 array memory Factory depth equals new bytes 32 array of size zero we're going to leave this as blank it's not important for most of what we're going to be working with and then pay Master input is going to be blank because we're not using the pay master and then finally reserved Dynamic that's also going to be blank because we're not using the reserved Dynamic either T and this is how we're going to get our unsigned transaction here so we can now take this go back up here and we don't need the signature right take this come back up here and we can say transaction transaction memory transaction equals create unsigned transaction from is going to be the minimal account owner so we're going to say address minimal account. owner oh actually we don't even need the address bit so from is going to be owner transaction type is going to be 0 x71 or 113 two is going to be the destination value is going to be value and then of course our function data so really similar to what we did on ethereum except for we're working with this transaction object now since we are calling execute transaction we actually don't care about the signature because we have this require here require from bootloader or owner so as long as it's the owner of this contract that's the message. sender this will work fine so then all we have to do is do vm. prank minimal minimal account. owner and then minimal account xute transaction and we're going to have to put some empty bytes 32s in here I'm actually going to create a static at the top I'm going say bytes 32 constant or a constant empty bytes 32 equal bytes 32 of0 and since we're not using the TX hash or the suggested hash we're just going to do empty byes 32 empty bytes32 then our actual transaction boom and what are we calling here we're calling mint so then our final bit here we can just do assert equal usdc balance of address minim account should now be the amount all right let's give this a wh so we'll pull up our terminal Forge test d-mt paste that in --zk sync and we'll have to wait a little bit for this to compile and actually go through and you will run into this so as of today doing a lot of what we're doing such as kind of making this giant struct down here working with this transaction memory Helper and everything requires d-va R so this stands for intermediate representation and it's a flag you can add to the solidity compiler to basically have it compile to this middle language called Ule or assembly and then to the evm or arvm don't worry too much about that now again we go over this in the assembly informal verification course but for now just in your Foundry dotl just sit via IR equals true and at the moment this will make your compiles and your tests run a little bit slower so just keep that in mind that it will take a little bit longer but it will allow us to test our code much more effectively here so we're going to have V on true here it'll take a little bit longer don't worry about it that's normal but let's go ahead and let's see if our first test works correctly and after a brief delay we see our test has passed okay excellent so our first initial test for our ZK owner commands is successful perfect let's keep going so then I would probably test that a non-owner can't execute commands if you want to go ahead and practice writing that function you're more than free to do so but let's actually move on to this more interesting stuff because yeah it's like okay cool that's not really a account abstraction though Patrick um I would like to see some account abstraction please so let's do our validate transaction so we'll test validate transaction and we'll assert we're getting this magic value right so we have this validate transaction here and this magic should return this account validation success magic we should make sure that we are getting this as a valid signer right so if the signer is the owner we're going to say it's a valid signer otherwise we're going to get this empty bytes for so let's do a new function test ZK validate transaction make this public scroll down a little bit might get a copilot is already trying to figure it out for me arrange act assert like this so we're going to copy a lot of what we've already did same as kind of what we were doing before we're going to get the destination the value the function data we're going to be calling mint to the minimal account with this amount we're going to be doing the same thing we're going to generate the unsigned transaction here and now we actually need to sign this transaction right we didn't need to sign it up here because our validation for execute transaction was just hey is it the owner or is the bootloader in either case go for it but now we need to call validate transaction right because now we're going to be simulating a true account abstraction transaction scroll back up what's the process look like well the first thing it does is it checks the nuns holder then it will call validate transaction so anytime on ZK sync you send an account abstraction transaction I don't know if I love it or I hate saying it it's going to call validate transaction first so so we need to sign this transaction so we're going to have to create a new helper function called sign transaction so let's do that function sign transaction and this is going to take a transaction m Mor transaction and then also so this is going to be the unlocked account doing the transaction now with doing this we're going to actually run into the same issue that we had with send packed user op right so when we signed the transaction with sendpack to Dr if we had an unlocked account we could use config do account no problem but when running locally we had to use a default Anvil key because why well when you run your tests Foundry doesn't assume that you have anything so we're going to have to do a similar setup here and since we are also just using tests here what we can do additionally is kind of cheat a little bit more so I'm I'm going to leave this as a count however we're going to kind of super cheat here and you'll see what I mean in a minute so what we want to do in here is first we're going to want to encode this transaction and to do that remember we have that memory transaction helper. encode hash transaction code hash trans action and we should import this if we haven't already boom and it's this function again that helps actually encode these right we can go back to this we can see that depending on the different transaction types it encodes them all like a little bit differently so we want to encode it correctly so this will give us the bytes 32 unsigned transaction unsigned transaction hash like this then we can get the by 32 digest we now have to convert this into an eth signed message so we will say unsigned transaction has. toe signed message hash like this and since we're doing to e signed message hash we're going to have to scroll up to the top here and we're going to have to do a little using message # utils for bytes 32 and we're going to have to import that import message # utils from at open open Zeppelin contracts utils cryptography ms. s.o and using M message hash with a capital H here cool that looks good and we can scroll back down cool then we get the digest at the bottom here now we can do that actual signing kind of the same same thing that we did in the send packed user Ops and I'm actually going to even copy this a little bit I'm going to copy the vm. sign Anvil key digest I'm also going to copy the Anvil key and the vrns Anvil key and the vrns here so we could 100% again do like if you know block. chain ID equals 31337 or equals equals 31337 and then use config do account yada y all that stuff but since we're never actually going to run this test on an actual Network because again scripting doesn't work with ZK sync we can kind of safely assume that this is always going to be just running locally so we can actually even just dump this account here and we will say for this codebase we should have our minimal account owned by the Anvil default key the Anvil default user so in sendpack user opt we call with the Anvil default key and back in in our minimal account test we scroll up to the top excuse me if we go to our helper config helper config we're going to use this Anvil default account we could import it from our helper config but again this is our test we know it's going to be a little bit different so I'm just going to kind of copy paste it here and what we're going to do oops sorry this is the wrong sorry the wrong make sure on the right test H so I'm I'm just going to kind of cheat paste this at the top and what we're going to do is when we deploy our minimal account here we're going to do minimal account. transfer ownership to the Anvil default account that way since we're the minimal account is owned by the Anvil default account we can actually sign the transaction with the Anvil default key so a little bit of a workaround here like I said I have an issue in Foundry hopefully somebody takes it on and actually makes this Improvement here if you're watching like I said this is a great great opportunity for you to contribute to Foundry but okay so we're getting our vrns here that's looking very good then we can do transaction memory signed transaction equals so we're just going to set up signed transaction to kind of make it look different and we're going to say signed transaction. signature equals ABI do and code packed remember this is RSV remember we get vrf s but then we have to go RSV to actually do the signature here remember the order is important and then return assigned transaction like this so this needs to returns transaction transaction memory like this cool sign transaction like so what's it matter about it can be restricted to view yeah okay we'll make this View and now that we have this sign transaction we can scroll back up we can do transaction equals underscore sign transaction transaction like this and so now just with that we have a signed transaction struct and if you want you can even do like a little like console to.log of the transaction. signature. data transaction type whatever you want so you can see kind of this transaction struct populated but now finally we can do the act so we have this sign transaction and remember the process for doing account abstraction on ZK sync is first the bootloader or the ZK sync light client or the ZK snc API client is going to call this validate transaction function so we need to simulate being that ZK sync node and the way we do that is we prank the bootloader formal address remember that is another system contract anytime you have a ZK sync node interacting with system contracts the caller is going to be the message. sender is going going to be this bootloader system contract right cuz it's this super special admin smart contract so we're going to do vm. prank boot loader formal address like this and so we need to get the bootloader formal address so we're going to import that from that constants area so I'm going to do import bootloader formal address from libf foundary era contracts slsrc system contracts SLC contracts constants do so like this and so now that we have the bootloader formal address here we can finally say Okay bytes 4 magic equals minimal account Val date transaction transaction empty bytes 32 empty bytes 32 and transaction cuz again for a validate transaction we're ignoring the TX hash we're ignoring the suggested signed hash again us are some fancy smancy things that we do not care about uh we're just focused on the transaction itself and then we can finally do assert equal magic should equal this where is it it should be this account validation success magic and so we can actually grab this from our I account. Soul so we're going to go ahead we're going to import that in our test back at the top we'll do a little actually o Imports here's your 20 Mark era Imports like this well import import import account validation success Magic from lib slf foundary era contracts slsrc SL system contracts SLC contracts SL interfaces account doso Tada now if we scroll down we can do assert equals magic account validation success magic beautiful if this test passes it means we are doing something very cool and it means we are creating an account abstraction transaction and we are able to sign it correctly and allow the ZK sync nodes to say yes this is a valid account abstraction transaction and you can go ahead and push it through so let's run this test we do Forge test d-mt paste this in- ZK sync remember running this with our Foundry DOL having the Via IR is true if you do not have that in the founder. you can also do D- via viir like this but we have it in the founder. toml now as of recording originally we could just do is system equals true in the founder. toml as of recording the latest update of Foundry ZK sync this is no longer the case we now have to pass it directly into the command line I'm sure that at some point this will change and we can add this back into the founder. Tomo but for now we actually have to do Forge test-- Mt paste the name of the test-- ZK sync and then we ALS have to do-- system system mode equals true like this so This D- system mode is the thing that's going to allow us to call system contract and if we don't pass the system mode if our system mode contracts aren't working then we're going to get some weird evm revert errors so if you run into weird evm revert errors definitely be sure to make issues on that Foundry ZK sync project because it's an alpha and the feedback will be very helpful and it will enable you to deploy ZK sync Smart contracts even easier in the future or you can go ahead and try to contribute to Foundry zync that is a great place to start your rust Development Career and again this will take a little bit of time oh and then actually this makes a lot of sense we're getting the not enough balance era here this is an era that we can definitely understand we have to do a vm. deal that minimal account some amount some amount we'll do U into 256 constant amount equals 1 E18 that should be more than plenty address minimal account clear and rerun and it has passed here okay incredibly incredibly exciting so we've tested our validate transaction actually works and we've tested our execute command also works which means if we go back to the ZK minimal account if you scroll back up to the top here it looks like we've actually gone through our whole process ZK API calls validate client which must update the nuns checks the nuns has been updated they call pay for transaction which I guess technically we actually did not test this however for this demo I'm going to say we can go ahead and skip that obviously if this was a real codebase you were working on you would 100% want to test that then API client verifies buot loer gets paid the API client passes the validated transaction to the main node and the main node calls execute transaction which we've already tested works correctly now we could then go ahead and test execute transaction from aside but I'm going to go ahead and skip this for now and just say guess what huge congratulations you've just written the tests and built a ZK sync minimal account abstraction account this is incredibly exciting now a couple of points on running the whole test Suite here if I just run Forge test at the moment what do you think is going to happen without the- SDK sync without the-- system mode equals true we of course we get some reverts right test validate test ZK validate transaction of course fails because we didn't run with the dash SDK sync flag we didn't run with the system mode turned on so it of course fails I have gone ahead and in the actual GitHub repo associated with this course I've added some of these checks in here like if not ZK sync chain if it's not ZK sync Foundry to make it a little bit easier but I don't think it's super important for your learning experience to go through adding all these conditionals in here so if you want to update your code base to reflect what I have feel free to just come into the minimal account abstraction codebase and copy paste the the changes directly from the script so and when you're using this repo as well just also be sure to whenever you run commands be sure to use the commands that I've added in the make files I've set it up so that a lot of the scripts that you're going to need to do are already in here and you can just run like make deploy or make ZK build or whatever that needs to be done here so cool now the final piece that I want to show you all is actually this is actually deploying and sending an account abstraction transaction now like I said as of today Foundry scripting on ZK sync leaves something to be desired so the best way to really do deployments is using hard hat so we don't cover hard hat and Cypher updraft so I'm not going to walk you through actually deploying to ZK sync with hard hat I'm not going to walk you through actually setting this up and deploying this and running with this but I am going to show deploying the account abstraction contract to ZK sync and then send sending an account abstraction transaction to ZK sync as well which is really cool and if you are familiar with JavaScript and hardhead and nodejs and typescript and stuff and you want to run these as well feel free to do so but I'm actually going to skip I'm actually going to jump cut over to me copy pasting all these scripts into my local file here so that we can actually deploy this all right and actually before we actually send this out I do need to make two little tweaks that make the JavaScript a little bit easier I was we were erroneously doing this message u.2 e signed message because I didn't realize that because I didn't realize that in this encode hash function that we're doing here down here it's already putting it into the correct format like so we actually don't need to do this this bit right here where we do message has. eth signed message so my mistake in our test as well message hash we don't have to do this step this is already a digest right here I didn't realize that this in code hash actually already returned that so sorry about that you can comment or delete those those lines and one more tweak as well when we call validate transaction in execute transaction from outside we definitely should check the magic that is returned here right now we're just kind of saying hey uh looks good to me is actually a pretty common security issue for Signature stuff so we would do like bytes for Magic equals this and then we would say if the magic does not equal that account validation success magic then we would go ahead and revert uh with pretty much whatever we wanted here like error ZK minimal count invalid signature like this revert invalid signature boom because we want to make sure that magic value that is returned is actually correct okay now that we have now that we've done the final tweaks here let's go ahead let's deploy this and let's do this so first we're going to run this yarn deploy command to actually deploy that ZK minimal smart contract and we've done it like so so we're going to grab this we'll go over to the zk6 apoia we'll paste this in and we'll see we do indeed see a contract here and this is our ZK minimal account now we can't actually verify this contract as of recording because as of recording any smart contract that interacts with system contracts can't be verified so this is just it is what it is but then what we're going to do we're actually going to send this some funds so I'm going to paste this in here I'm going to send it 0.001 that should be more than plenty we'll confirm I wish I had this much money in my wallet that would be great this is one of my burner accounts ZK sync was kind enough to send me a bunch of testet ZK sync so I could make this video for you all great so now that we have this we're going to take this ZK minimal address and we're going to open up the send a ax right here and we're going to paste this right at the top this ZK minimal address and if this goes through successfully we will see a transaction on here that is from this wallet address believe it or not even though this is a smart contract wallet which is crazy cool so let's go ahead and do little yarn send TX and hopefully this goes through successfully and we will have done it and it's looking pretty good transactions sent from minimal account with hash this hash right here let's go ahead we do a little Refresh on our smart contract now we now see we have indeed a transaction right here it's probably going to be the same one that we just created yep it is and it sure is we can see the from is this wallet here and this is the smart smart contract wallet that we just deployed that's crazy so on ZK sync you can literally have the smart contract Wallet be the from which is not possible on a lot of these other chains really really cool and we've done a very simple approval on the fake mock usdc contract that we actually deployed wow this was a lot but hopefully you can see how powerful this is ZK sync you can have a smart contract wallet that also acts like an externally owned account with account abstraction buil in so we have learned a ton because not only do we learn how to do this on ZK sync we also learned how to do this on ethereum so we learned how to do account abstraction on a chain that doesn't have native account abstraction but has account abstraction via an entry point smart contract and an ALT mol and then we also learned how to do account abstraction on a chain that has a account abstraction built in this is wild and this is incredibly powerful so before you jump off let's do a quick rundown of all the crazy things that we just learned because we've just learned some really really powerful stuff so first off we learned what account abstraction even was we learned that essentially account abstraction is saying okay instead of a private key signing everything you can have whatever ever you want sign anything it could be a Google session key it could be a group of friends it could be the weather account abstraction is the concept of anything being able to validate your transactions as long as you code that anything into a smart contract traditionally only private keys can sign transactions but with the power of code we can have anything sign a transaction on ethereum the way that you have to do this is you first have to deploy a smart contract with that anything codified somehow once you deploy that smart contract you can send an account abstraction transaction by signing the data offchain sending it to an ALT mempool of nodes who they will then submit it to the blockchain to an entrypoint doso via a function called handle Ops the entrypoint will work with some extensions like a pay Master a signature aggregator and then it'll send the transaction through your account where you will interact with a blockchain etc we built a very minimalist version of this in our minimal account. soulle the only function that these smart contracts must have is validate user operation where they take a packed user operation struct which has all the stuff that's needed for a transaction to happen we added a couple of really important pieces we added a function to execute so our smart contract could actually do stuff we of course have validate user op where we used validate signature down here where it was very easy DSA recover just to check if the person who signed the packed user operations is the owner of this contract we of course added a function to pay the the bootloader to pay that entrypoint contract because you need to pay somebody because you need to repay those alt menol nodes who sent the transaction and that was it and we built some really robust tests for this h ethereum and then we also built some really cool and robust scripting for this that was how it worked for ethereum for ZK sync it works a little bit differently because ZK Sync has account abstraction natively built in for ZK sync you don't have to send to an ALT mempool all you have to do is codify your rules your signing rules and then send your transactions as a type 113 and ZK sync will handle everything automatically behind the scenes so in order for us to make a ZK sync minimalist smart contract there are a few other pieces we needed to add so we need instead of validate user Ops we have validate transaction because on ZK sync all transactions are of this struct transaction type so ZK sync will always pass your transaction to this validate transaction function we also added an execute transaction and execute transaction from outside these are the functions that will enable our smart contract to actually do stuff we added a pay for transaction and prepare for pay Master as well to interact and deal with the pay master in our ZK minimal account we had our validate transaction which was a really basic function down here we increased the nuns by interacting with a system contract which was something that we hadn't learned about before on ZK sync there are a lot of admin smart contracts called system smart contracts where they have admin level power they have power over the global of the chain and can do really cool stuff we made sure we had enough money and then we also did a very basic ecdsa recover on the signature and returned the magic as such we then had a very basic execute transaction function which just had a little bit of a conditional for if you wanted to interact with a deployer system contract for this we also wrote some really cool test and we had to make sure that we used Forge D- Forge build - cync D- system mode equals true and depending on when you watch this this key might be a little bit different we might actually be able to have this in the founder. all but as of today that's how we had to do it we wrote some very basic tests for this as well and we didn't write any solidity scripts because solidity scripts don't work great with ZK sync at the moment so what we instead did we kind of cheated a little bit we we watched me actually deploy this contract with some JavaScript stuff that I wrote previously and then also send the account abstraction transaction myself if you're following along with the GitHub repo associated with this course if you scroll down into here you can actually go and see the examples where are they examples you can see the example deployments and the example transactions that we ran if you want to take a look at some of the coolness some of the big differences between having native account abstraction and normal and entry point based account abstraction is that entrypoint based account abstraction the from is going to be whatever node or user actually created the transaction whereas on zync with Native account abstraction the from is actually going to be the smart contract wallet itself which is really cool so I know there was a ton of code but you learned an absolute ton and a lot of people do not have this power unlock for their smart contract development journey I highly recommend you take a minute or several minutes actually you take a break you go get a coffee you go to the gym and maybe you try to build an even cooler account abstraction codebase account abstraction is a great way for web 3 to scale adoption because we can actually code smart contracts that are more userfriendly have easier logins have easier validation and just have a lot more flexibility and granularity with how transactions are signed and interacted with to me there is A1 billion company in this account abstraction idea some somewhere and it's up to you to go out and figure out how to build it and figure out how to scale it so with that being said take a break go to the gym go get some coffee go get some ice cream you have done phenomenal getting this far all right welcome back we're almost there everybody let's scroll on down to lesson 14 we are now on Foundry Dow SLG governance and of course all the code that we're going to be working with is in this GitHub repo so if you want to follow along feel free to go here now there's a ton of conceptual stuff to go over before we get into this but basically we're going to learn everything about what a DA is what they're for and how to use them and as we're going along and as we're learning about Dows I want you to take some time to read these two articles they're both from vitalic and they address a lot of the main concerns with Dows one of them are that Dows are not corporations where decentralization in autonomous organization matters and this article came out in response to a lot of people having really hard coordinating doubts because since they're decentralized autonomous organizations and it can be difficult sometimes to coordinate with so many people and so many heads so this article is really interesting where Dows work really well and sometimes where they don't and this one is one of my favorite articles about plutocracy plutocracy is government by the wealthy this is something that obviously sounds bad and something we want to avoid in this new system that we're creating if we default to typical erc20 based governance we're going to run into a lot of issues outlined in this post if that doesn't make sense to you right now don't worry it will and we'll come back to this in a little bit but first let's learn about Dows what Dows look like and how they actually work especially as developers so I made some videos about this in the past let's go ahead and watch those and we'll come back now before we learn how to code a dow we should learn what a dow is and again I've already made a video that I put a lot of work into so we're going to watch what a dow is from a high level first then we're going to learn how to code a da now Dows or decentralized autonomous organizations is a bit of an overload of term but it typically describes any group that is governed by a transparent set of rules found on a blockchain or smart contract and I say overloaded because some people say Bitcoin is Dow because the miners could choose whether or not to upgrade their software other people think that Dows must use transparent smart contracts which have the rules ingrained right into them and then other people think Dow is just a buzzword so they just slap the name really onto any organization so that they can get some clout and this makes we sad Patrick and this is enough to be confused with the Dow which was an implementation of AD Dow back in 2016 which set the record for the largest hack at that time so there's a lot of different ways to think about it and the Dow term is used in a lot of different ways but in essence imagine if all the users of Google were given voting power into what Google should do next and the rules of the voting was mutable transparent and decentralized this solves an age-old problem of trust centrality and transparency and giving the power to the users of different protocols and applications instead of everything happening behind closed doors and this voting piece is a Cornerstone of how these operate this decentralized governance if you will and it can be summarized by company or organization operated exclusively through code and to really understand all this we're going to look under the hood of the protocol that's setting the precedent for all other Dows in compound then once we look at compound we'll understand what goes into building one of these and all the trade-offs all the different architectural choices mean for your group and then in my next video I'm going to have a full codal along tutorial for developers looking to build one of these themselves but be absolutely sure to watch the rest of this video because it's going to give you all the architectural fundamentals so you can make Intelligent Decisions when you get to that section and be sure that you and your Dow friends smash the like And subscribe button so we can keep giving you the best engineer first content on the planet when it comes to Smart contracts let's get into it so so here we have the compound protocol it's a borrowing and lending application that allows users to borrow and lend their assets and everything about this application is built in smart contracts now often times they're going to want to do a lot of new things maybe they want to add a new token to allow borrowing and lending maybe they're going to want to change some of the apy parameters maybe they're going to want to block certain coins there's a lot of different things that they might want to do so that's where we're going to go ahead to governance this is where you can find a user interface for a list of all the proposals and all the different ballots that came to be so here's a list of some of the governance proposals that this protocol has actually been making to improve and let's look at one of these proposals that's currently actually in process so if we click on the proposal we can actually see everything about this proposal who voted for who voted against and the proposal history here now the first thing to one of these proposals is somebody has to actually create the proposal in a proposed transaction and we can actually see that proposed transaction right here if if we click on this and we scroll down we can actually see the exact parameters they used to make this proposal let's go ahead and decode the input data and we can see this is exactly what this proposal looks like the way that they're typically divided is they have a list of addresses and a list of functions to call on those addresses and then obviously the parameters to pass those addresses so this proposal is saying hey I would like to call support Market on this address set Reserve Factor on this address here are the parameters we're going to pass they're obviously encoded with bytes and then here's the description string of what this is doing and why we're actually doing this the reason we have to do this proposal governance process is that these contracts likely have access controls where only the owner of these contracts can actually call these two functions and the owner of these two contracts is likely going to be this governance sty and values to zero just means that we're not going to send any eth along with these transactions once a proposal has been created after a short delay it becomes active and this is when people can actually start voting on them this delay between a proposal and an active vote can be changed or modified depending on your doubt then people have some time to start voting on them and if it passes which this one overwhelmingly did it reaches succeeded if we click on this transaction again and we go to the compound governance contract and we scroll down to contract right as proxy we can actually see the exact function that the people called to vote namely cast by vote cast vote by signature and cast vote with reason we'll talk a little bit about the exact differences between these in our next video but these are the functions that they're actually calling and if you go to the compound app and we go over to vote this is a user interface you can actually vote through to make it easier if you're not as techsavvy so you can vote right through this app. compound. Finance or you can just send the transaction yourself once all those votes happen it reaches this cued stage now what does cued mean well before a proposal actually becomes active there's a minimum delay between a proposal passing and a proposal being executed so somebody has to call this cued function and it only can be called if a vote passes and it says okay that proposal ID has been queed and we're going to execute it soon now if we go to a different proposal like this one for example we can see it has been executed we can see somebody called this executed function and they executed proposal 82 so this is going to be a full example of the life cycle of a proposal going through this process now there are a couple that even failed whole punch of people voted against this and if you scroll down you can see it was created it was active and the majority of people voted against so that's where it stops now often times just putting one of these proposals through isn't enough to really Garner some votes for it you generally want a forum or some type of discussion place to talk about these proposals and why you like them or don't like them often times a discourse is one of the main places that people are going to argue for why something is good or why something is bad so people can vote on these changes and again snapshot might be one of these tools that you use to figure out if your community even wants something before it even goes to vote you could join one of these and with your tokens actually vote on things without them being executed just to get the sentiment or like I said before you could build your protocol in a way that snap snapshot actually helps you with the voting process all right now you've seen the protocol that has been influencing all the other Dows on how to vote now you know now that we know what a dow looks like let's talk about the architecture and tools that go into building one of these and additionally the trade-offs that they have and the first thing to talk about here is going to be the voting mechanism now voting in decentralized governance is critical to these Dows because sometimes they do need to update and change to keep with the times not all protocols need to have a dow but those that do need to have a doubt need a way for participants to engage this is one of the most important questions to ask and to tell your communities how do I participate how do I engage in this doubt how do I help make decisions and you'll find this is a bit of a tricky problem to solve now an easy approach to this problem is going to be using an erc20 or an nft token as voting power similar to what we saw with compound use the comp token to vote for different proposals seems simple enough right boom problem solved hooray now this actually might be the right approach for certain doubts but it also runs the risk of actually being less Fair because when you tokenize the voting power you're essentially auctioning off this voting power to whoever's got the deepest Pockets Whoever has the most money gets to pick the changes so if it's only the rich people who get to vote then it's highly likely that all the changes in the protocol are going to benefit the rich which doesn't really seem like that great of an improvement over our current world nfts are interesting because they have this non-fungible component but yet even they still run into this issue additionally if you buy a whole bunch of votes you make a bad decision and then sell all your votes you as an individual don't really get punished you just punish the group as a whole but you being malicious you can get away with pretty scot-free now again this voting mechanism is going to be correct for some groups but for other groups maybe no it really just depends on what your Dow and Community setup is going to look like now the next one we're going to talk about is skin in the game now metallic has actually written a lot about this and I highly recommend you read his article Link in the description to see that the skin in the game method means that whenever you make a decision your vote is recorded and if that decision leads to a bad outcome your tokens are asked you get punished for making evil or bad decisions for your da and your protocol I like this mentality because even if you buy a ton of tokens and decide to be evil with it you can be held accountable for your bad decisions now the hardest part about this though is going to be how do we decide as a community what is a bad outcome how do we actually punish these people and that's easy because the answer is I'm not sure now the third method of this voting mechanism is probably one of the most interesting ones but also the hardest ones to implement and this is proof of personhood or participation imagine that all users of the compound protocol were given a single vote simply because they used the protocol and even if they had a thousand wallets that Ed the protocol one human being means one vote this would be amazing and a far more fair implementation where votes couldn't actually just be bought the issue however comes in something known as civil resistance how can we be sure that it's one vote equals one participant and not one participant pretending to be thousands of different people so they get more votes this method hasn't really been solved yet but I'm willing to bet some very clever engineer will do some amazing chain link integration because proof of personhood is basically just offchain data that can be delivered on chain and that's exactly where chain link shines now as you can see all these methods and even more that you probably think of aren't that far-fetched and we actually see these exact same methods happening in the real world proof of personhood or proof of participation might just be the exact same as kind of the regular government voting that we see every day in the United States at least one person gets to vote for one president you can't go around making a whole bunch of fake people and voting for president but in companies the erc20 voting standard kind of applies the more shares of a company you have maybe the more voting power you have in that company so we can draw parallels between the real world and how voting in governance is going to work in our smart contracts and in fact you should draw parallels and look for inspiration from the web TW space now when it comes to implementation of the voting I put them into two categories onchain voting and offchain voting onchain voting is exactly what we saw with compound there's a smart contract onchain you're a voter you call some function called vote with your metamask your Ledger or whatever send a transaction and boom you voted congrats you can wear you're a little thicker now you call that function and you send a transaction you send a transaction H what do transactions use that are kind of annoying and kind of costly uh oh that's right gas imagine you have 10,000 people in your community and it costs $100 to vote per person you're are now costing your community $1 million anytime you want to change anything this is obviously insane and not very sustainable for your community Pro here is that the architecture is really easy everything's going to be transparent everything's going to be on chain and and that's really good but yes the con is that you're going to break the bank account for a lot of people potentially now there are a lot of variations of this to help solve some of these problems especially the gas problem one of the ones that I'm incredibly excited for is this one called Governor C where they use some random sampling to do some quadratic voting to help reduce cost while increasing civil resistance you want to learn more about that one too be sure to read about it in the description so onchain voting is the simplest one here but let's talk about offchain voting how could you possibly vote offchain in decentralized context relax relax you can vote offchain and still have it be 100% decentralized you can actually sign a transaction and sign a vote without actually sending to a blockchain and therefore without actually spending any gas instead what you can do is send that sign transaction to a decentralized database like ipfs count up all the votes in ipfs and then when time comes deliver the result of that data through something like an oracle like chain link to the blockchain all in a single transaction Al alternatively what you could do is you could replay all these signed transactions in a single transaction to save gas this can reduce the voting cost by up to 99% right now this is an implementation and one of the most popular ways to do this is through snapshot and I'm just dying for someone to make a chain link integration because it's going to be so much safer more secure and better and blah blah blah dying for it this is your call to action go build this thing this offchain voting mechanism obviously saves a ton of gas to the community and can be a more efficient way to store these transactions anyways however it needs to be implemented very carefully if you run your entire Dow through a centralized Oracle you are essentially reintroducing a centralized intermediary and ruining the decentral of your application so don't do that and if you made it to this point in the video give yourself a little path in the back you're doing fantastic learning is fantastic like I said I have a video coming out after this one that's going to show you end to end how to build one of these from scratch let's learn about some of the tools that you can use help get you up to speed quicker now there are a number of no code solutions that can go into building one of these dows Dow stack Aragon just kidding this is Aragon colony and DOW house are all Alternatives that can actually help you with the Ops side of running a dowo and building a dow however if you want more granular control and you don't want to have to pay any of the fees associated with these protocols you might want to do it from scratch now let's talk about some of the more Cody solutions that you can use Snapshot is one of the most popular tools out there for both getting the sentiment of a dow and actually performing that execution users can vote through this protocol with their actual tokens those transaction gets stored in ipfs but none of it actually gets executed unless the Dow chooses to so this can be a great way to get the feel for what your Dow wants to do and optionally you can send the transactions and execute the votes as well I highly recommend checking out zodiac which is a suite of Dow based tools for you to implement into your Dows as well tally is another one of these uis that allow people to see and actually vote and interact with these smart contracts through a user interface for those of you who don't know about nosis safe you absolutely should nosis safe is a multisig wallet and the reason that I put this on the list even though it's adds kind of this centrality component is that most Dows in the beginning are probably going to start with some type of centrality it's much easier to be fast when you don't have thousands of people to wait for a vote and in the beginning any protocol is going to be centralized to some degree anyways using a multisig where voting happens through only a few key members can be good in the beginning for your DS and often emergencies as well but just keep in mind when you add one of these you are adding this level of centrality and then of course open Zepp and contracts we love open Zepp and contracts these are the contracts that we're going to be basing our Dow code Along on all right so that's all the tools that's the architecture one more thing before I let you go legality the future of dows is interesting for all these reasons we just talked about but especially on a legal front does it make sense for a DA to live by the same regulation as another company how could you even force a DA to do something you'd have to force them to all vote a certain way if the government tells you to it's it's a little gray it's hard to nail down who do you even keep accountable for these Dows in the United States at least you can actually form your own Dow and have it legally recognized in the state of Wyoming this is something I want to do so we'll just have to see what happens there w at this point you have been injected with all the Dow knowledge you need to succeed and Thrive with this new amazing technology and these new amazing Concepts and it's time to build baby now we are still going to build a dow from scratch but we do have our special guest Juliet from the Aragon team to go over a no code solution that you can use as an alternative hello everyone uh my name is Julia I'm the developer advocate for Aragon and today we'll be building a DI without using a single line of code let's go so to do that I'll be using Aragon as my Dow framework and to give you a bit of a better overview as to how Aragon architecture is set up um Dows are essentially composed of a smart contract which is the one that contains all of the assets that the organization manages um so it access a treasury and then all of the other functionality for Dows is really enabled through plugins and we'll see how this uh how this is represented itself throughout the process that we'll build so we go into ABS ar.org we go into creating a dow um first we'll see the process uh that we'll be taking in order to do that and then we can get right into it so firstly we need to choose the blockchain which our Dow will be deployed in um I'll choose Gorly for the sake of Simplicity and playing with testnet um then we get to describe our Dow so we can have a developer Dow um which can be something like this we can set up our ens we can set up our logo a description a dial for developers um and we can add in additional oh we can add in additional links um as well that represent the organization then we'll go into defining the membership this is the what will Define who is able to participate in the governance of these assets um and currently our app supports two different types of uh membership definitions and governance mechanisms one of them is toen holders which enables holders of specific tokens to vote in the organization and then we have multi-c members which establishes a specific Quorum that needs to be met in order for a proposal to go through now to give you some context both of these on the back are plugins um which essentially extend the functionality of what Dows can do through enable them this specific uh decisionmaking process in order to manage the assets of the organization however keep in mind this can be anything and plugins can also work to move uh funds they can be treasury management mechanisms they can be different typ of coordination Styles um and so really the possibilities are endless when we speak about uh customizing these types of onchain organizations then we're going to create a token Um this can be something like developer token we can call it something like DVP um I can set up say a th000 tokens for myself or an add any other address that I want to transfer uh some funds to um then I establish what is the minimum amount of tokens that someone needs in order to create a proposal I'll say 10 I could also just say like allow anyone out there to vote um and create proposals at which point uh there is a risk of proposal spam so keeping that in mind I'll just say that we need um say 10 tokens in order to create a proposal then we'll go through our governance settings so what is the minimum support threshold needed the minimum participation needed for a proposal to be valid how much times the minimum duration they uh proposal needs to be out there in order for it to uh be counting the votes and then we can say that we don't want early execution which means that we wait for the entire time of the duration of The Proposal as well as uh not enable people to change their vote after they've voted I can also bot yes to that and then the last step is simply revising um those parameters that have set so out of everything that we've defined only the blockchain selection is the one thing that we cannot change later on since that's the blockchain through which we're deploying our Dow but really everything else um we can change it lat later on with a proposal vote um and so the idea here is to really enable these types of immutable organizations to mutate and evolve with time um so I'll sign in my proposal I go back into my deployment um and so at this stage what's happening on the back is that Aragon is deploying this Dow construct instance with uh the specific plugins defined in installed as we determin throughing through the Dow creation process so once that's done we'll can come into the dashboard of our Dow we'll be able to see who is a member of our organization how many tokens are hold I can create proposals I can make deposits um and so this is where we'll be managing the organization um keep in mind that this is a a pretty um default template that Aragon has set up as our initial drafts we have a lot of iterations coming in terms of the type of plugins you'll be able to use the different types of uh decision-making strategies you'll be able to implement and so the customizability really is endless thank you very much all right welcome back you now know a ton about Dows and how they work and we are going to go over one of these plutocracy Dows right one of these erc20 based stles and how to build one yourself from scratch however I want to challenge you to not default to this a lot of protocols default to okay I'm just going to launch a governance token we're going to be good to go and then a couple years down the line they realize that that was a horrible decision and they have a hard time scaling their model they run into issues where they can't separate speculation on the token from the utility of the token and there's a ton of issues with that model so anybody who's watching this if I catch you launching a DA in the future and you do not have a foolproof white paper as to why you need a governance token I will be very disappointed in you I know that doesn't really matter to you but I will be very disappointed in you and you will make me sad so please don't make me sad but we are going to learn this methodology and how to do it so let's jump in because guess what we only have two lessons left and then you're ready to go on your way all right you know where to begin mkdir boundary Dow f23 code boundary Dow f23 or file open let's pull up our vs code at this time you should be pros of this part Forge in it I don't want these three files boom boom boom goodbye boom so let's do a little read me and let's talk about what we're going to do so one we are going to have we're going to have a contract controlled by a dow 100% controlled by a dow every transaction that the Dow wants to send has to be voted on and we will use erc20 tokens for voting which like I said this is kind of the default model that the industry is currently using but I'm telling you it's not a great model please research better ones and make web 3 better but all right and this is the model used by pretty much every Dow at the moment compound Unis swap a etc so I'm showing you the most popular model but yes I'm telling you please don't default to this please don't always use this but let's start with this first one we're going to have a contract controlled by the Dow so let's create a minimal contract that we can vote on stuff for and we're going to do something pretty similar to what we've already done we're going to do SRC new file we're going to make a box. soul real similar to what we did before right spdx license identifier MIT pragma solidity 0.818 little carrot contract box let's close this like this like we said we're going to make this ownable it's going to be controlled by the Dow so we're going to do a little open Zeppelin work Forge install open Zeppelin slash open Zeppelin contracts D- no- commit and since we're doing this we're going to need to open up our founder. paste this in here uh I copied this from a previous project opens up/ contracts lib opens up and blah blah blah now since we have that we can do import ownable from atop Zeppelin SLC contracts accessable Doo and our box is going to be ownable and the Dow is going to own it tracks all right cool going to be real minimal contract un 256 private number this obviously should be like sore number right uh event number changed looks like that function store un 256 new value or new number public this will be our only owner function which this store function will be only ownable will be only callable by our Dow we'll say number equals new number we'll even emit number changed with the new number this is sore number and then we'll do a function read number or get number get number number public or external view returns un 256 return s number and that's it that's the whole contract boom that's it this kind of looks like box kind of looks like symbol storage it's kind of an amalgamation of both but this is it cool we'll make sure it actually compiles with Forge build make sure it compiles looks like it's compiling okay cool awesome so we have our box what's next well every trans action that the Dow wants to send has to be voted on we will use erc20 tokens for voting so let's create our our voting token here new file gov token. soul and this is going to be our voting token now we could implement this from scratch but again what we can do for this is actually just come to the contracts wizard of open Zeppelin go to erc20 and select votes and literally just copy this clipboard and paste it in or copy this ourselves and paste it in here this is going to be our voting token that's it so let me talk to you about what we just copy pasted and we're going to update this to be named Imports because named Imports are awesome this draft erc20 permit we're just going to import this erc20 permit then earc 20 votes so I'm just going to talk you through what this is actually doing so it's it's a regular erc20 token exactly as we've seen but has these two kind of extensions let me toggle the word RP and we have the opens up and contracts installed Okay cool so I'm going to control command click into them again you can open up the file viewer and you know type the actual name of the contract if you want erc20 permit what does this actually do this allows approvals to be made via signatures basically you can sign a transaction with without sending it and let somebody else send the transaction that's it it's based off of this EIP we don't really need to understand this too much but if you're interested I would definitely recommend looking into it the more important one is this erc20 votes contract and like I said it's based off of this compound voting and delegating it does a lot of important things here number one it keeps a history of each account's voting power keeps snapshots of them now this is important because when you start a vote you want to use a historical snapshot you don't want to use the current balance of everyone's tokens at the moment somebody could do something called a flash loan which is something we didn't talk about but they basically can use this defi thing to get a ton of tokens for a very very short period of time and crash the vote so we use a historical value and the way to get that historical value is to keep check points of people's values we can also use a delegate function on our tokens some sometimes we trust a person more than we trust our understanding of a topic so we can actually hold on to our token still that tokens are still ours but we can delegate the voting rights of our token to somebody else these are some of the two main features that this token has if we scroll down we can see we have this checkpoints function which gets checkpoints and there's this checkpoints mapping address to checkpoint we can see the checkpoint object says from block and then votes and if we scroll down there's this afon token transfer function which anytime you transfer a token this gets called it ends up calling this move voting power which does a whole bunch of stuff in here but the main things are it calls this right checkpoint function so anytime you move tokens by delegating tokens or transferring tokens you write a new checkpoint right so you say hey at this block this was people's voting power and you don't do it for every single block right you don't calculate someone's checkpoint in every single block you only calculate the updates in the checkpoints so if we scroll to the top for example says from block this would be like you know let's say you minted let's say you bought a token at block five and then you sold it at block 25 this would just have two checkpoints block five and block 25 that's it it adds some gas for every single transfer you make but it allows us to do these sophisticated voting methodologies so and that's really it other than that it's a basic erc20 token just has these checkpoints has these additional delegate functions as well and that's really it and cool like that's it our governance token is done that's all you need to do what else well guess what the open Zeppelin wizard can help us with even more because what do we need next well we need a doubt right we need a system we need a contract to actually manage these votes right and guess what the wizard has one called Governor we can go through this this and update settings so we can update the name if we want I'm going to leave it as my Governor a voting delay which is anytime somebody proposes something it says okay we're going to wait at least one block for the voting to start maybe you do something like 100 blocks you know it depends on your chain the voting period for how long the voting will actually last a proposal threshold where the minimum number of votes an account must have to create a proposal most of the time this is kept zero a quum percentage percentage of tokens that need to vote in order for something to pass if there's 100 tokens in circulation at least four tokens need to vote for it to pass make these settings updatable or not this is this is to make the contracts fully compatible with Bravo which is the compound implementation the type of votes you can have erc20 votes you can have erc721 votes which is an nft or comple a time lock controller anytime a vote passes give users some amount of time to leave the Dow before it's implemented and then upgradeability we probably want to avoid this as much as we can because like I said before security and with that I'm just going to leave all the settings to be default we can literally copy this into our contract and not really have to do anything so new file my myor soul B this in and let's talk about what is going on in this contract what are these different functions so first off off let's update this to named Imports and we also need to import I votes this is going to come from Governor votes we're going to need to import this time lock controller which is going to come from this Governor time lock and then we're going have to import I Governor which is going to come from governor and that's it so just update these to named Imports and we're good to go so let's walk through what this is doing so my Governor is governor governor settings Governor County blah blah blah all this stuff I'm going to give you the high level overview of what all of these does this Governor contract if we command click into it or control click into it is the core of the governance system this Governor contract we control click into it it brings us to Governor votes but let's go to the governor contract this is kind of the main contract here and how it works is it keeps this mapping basically of proposals right each one of these proposals have a vote St a vote ended and then an executed or canceled and that's really it every single time somebody submits a proposal this mapping gets updated and if we scroll down we have this state function this is the function that tells us if a proposal has passed based off of this mapping of proposals if it's executed if it's cancelled what's the deadline has a quum been reached Etc this is what most us user interfaces are going to read to see if a vote has passed or not keep scrolling down we can see a proposal snapshot which is basically getting the deadline when the proposal is due we can see some stuff like a proposal threshold and then a whole bunch of unimplemented functions like Quorum reached vote success get votes Etc and this is because this Governor function is this abstract contract meant to be extended on and implement it with Governor votes is one of these extensions where it says okay erc20 token voting that's the way we're going to do votes and this has a function like get votes which reads the token voting weight from the tokens built and snapshot mechanism to get how often somebody can vote uh and that type of thing now in our governor one of the main functions that we has is going to be propose and these are going to be the variables it takes in targets is just going to be like a list of different contracts to make a transaction to values is going to be a list of values to send with each Target call data now that we know all about call data is going to be the byes data that we're going to send with each transaction and then just a description right so for example this might be like 0x0 blah blah blah some address here and if it's just one it would just be like you know one address here it's two you know it might be like this Etc values might be like you know something like zero meaning the transaction we send to this address we're just just going to pass zero value you know if there's two transactions with two addresses like 0x blah blah blah something or other you know we could have two values right call datas are going to be the call data for sending to Here and Now that we know about function selectors function signatures and Etc we know that with this this call data section allows us to make allows us to call any function and really send any data to this target that we want so it makes it completely modular and then some description right and this is really just for the internal state of the governor you know it might be something like proposal to send money to Dawn right and so if this was like one two three this is DA's address cool we've just made a proposal to send money to Dawn right if this was you know like like the link token contract for example we could have this be zero we could find the function selector for transfer we could be like transfer function selector and encode you know and then encode all the data for the for transferring some link we could then say proposal to send link to Chris or whatever we wanted to do here right so this is how we can propose any transaction for our Dow to do and send proposals so really really important function here and if we go through it we can see it hashes the proposal it does a whole bunch of checks in here it adds our proposals to that proposals mapping it gets a deadline picks a snapshot for votes and everything emits a log and importantly it returns a proposal ID The Proposal ID is a hash of all the inputs so that this proposal ID will be unique then we have an uh another important function called execute and all of the inputs you can see are the same as the inputs up here right the only difference is it's saying a byes 32 description hash this is just going to be the encrypted description from up here and it's this function that gets called o excuse me and it's this function this ex Cube function that gets called once a proposal has passed to actually send that proposal right so here it first reverse engineers and gets the proposal ID from all those inputs which should be the same as what was proposed and then says okay let's get the status of that proposal State based off of how the votes go and if it's good to go then go ahead and execute it right so we do some execute stuff here the execute internal function actually sends it with some familiar stuff here right we're doing targets. call values call datas Etc this is this lowlevel functionality here it's got some before execute stuff some after Execute stuff we don't really need to worry too much about that we can vote to cancel transactions we can get votes and then finally another incredibly important function is going to be cast vote and there's some derivatives of this like cast vote with reason cast vote with reason and pams cast vote by Sig whole bunch of different ways to cast vote but the main thing this cast vote thing does is it calls this internal cast vote function which calls this internal cast vote function and this is the actual function it calls so it gets the proposal based off the proposal ID it gets the weight of your vote based off of the snapshot of the tokens that you hold calls this internal account vote function which which basically just updates some internal State variables to add your votes to them and then admits an event that's it right and it updates your vote based off of whatever your weight is which in the system that we're using the more tokens you have the more you your vote counts and those are the main functions here so hopefully that made sense I know I kind of went through that a little bit quicker but that's kind of the basics of the governor now Governor is the main contract Governor settings is just an extension to add stuff like voting delay voting period voting threshold Etc Governor counting simple is also an extension uh which is just an extension for a very simple counting mechanism this extension allows our votes to be against for and abstain and so we have this proposal vote for each proposal they get this struck and this is where those votes get counted we have against votes for votes abstain votes and then a mapping of who has actually voted Governor votes just implements this get votes contract and Governor votes Quorum fraction this is just an extension or token weight extraction and then we have this important time lock controller function every single Dow should 100% always have this Governor time lock control using this model means the proposal will be operated by the time lock controller and not the governor thus the assets and permissions must be attached to the time lock controller so we're actually going to deploy a contract called time lock that's going to own the governor anytime our governor contract votes on something and says okay this vote has passed Le executed the time lock controller will say okay cool but you have to wait X days or something you can't execute without some delay and it's really important to have this because if a dow votes on something that a lot of people in the Dow hate it gives them time to get out of the Dow before they get steamrolled if you will so really important to have this and that's pretty much it so we have some uh voting delay voting period Quorum State propose we have all these uh which are just calling super right that's pretty much it and that's all we really need for our governor contract right we have this Constructor which takes the token that we vote on as an input parameter and the time lock controller that's going to block us from block us from executing proposals right away the time lock controller contract is going to own our governor controller contract and that's actually the last contract we need to create a Time lock. Soul so this is the only one we have to build ourselves but we actually barely have to build it ourselves SPX license identifier pragma solidity 0 point 8.18 carot contract time lock and we we barely have to implement this because open Zeppelin already has one of these so we just say our time lock is time lock controller and then we can just import it import atop Zeppelin SLC contracts SLG governance time lock controller. let's import it like this from I spell that right time lock controller okay that's more right governance governance contracts contracts open Zeppelin open Zeppelin time lock controller time lock controller okay cool that looks good now we'll just do a Constructor and we'll pass some parameters in here we'll say U into 256 M delay which we'll put a little comma here this is going to be the Min delay is how long you have to wait before executing we're going to have to pass and we can find all of these in the Constructor of this m delay proposers executors and admin right this is the Constructor of the time lock controller so we're going to need to have this be the Constructor of hours as well M delay we're going to need proposers is the list of addresses that can propose so we need an initial list of proposers we're going to update this so that it can be anybody and then executors is the list of addresses that can execute execute we're going to update this as well so that anytime a vote passes anybody can execute it so M delay address array memory proposers address array memory executors boom and since this time lock controller parent class has a Constructor I'm going talk the word wrap we going to put those in here and it's just exactly the Constructor parameters we created M delay proposers xors cuter and then we also have to give it an admin which we're just going to say is message. sender for now and we need to give it an admin at first so that we can eventually move the time lock controller's admin so that only the Dow can do anything with the time lock controller and you'll see us do that in a minute but those are all the contracts that we need that's it we've written the contracts we're done like I said I'm going to do this kind of quickly I do recommend that after this you go back and you really try to understand what's going on here because I I know I'm kind of doing this quickly but now we're going to write a test to show it actually work and that's it I'm not going to write a deploy script here uh if you want to go back and you want to write a deploy script that's great but I'm just going to write a test to show you basically endtoend exactly the process that happens in one of these Dows so let's go ahead let's write the test my Governor test. T.O and the other reason that I'm going a little bit quicker here is because at this point you understand a lot of this right and you know and should know how to go back and flesh this repo out right with scripts with tests unit tests fuzz tests Etc and you know how to make this project badass and I'm just I just want to give you the new stuff right teach you the new stuff for here teach you about the Dow stuff so let's write some tests just we can really see this process work end to end and we're just going to have one giant test just to show the whole process so you know the drill pragma solidity here contract my Governor test is test you already know we're going to import test from forg STD test. soul and we're going to need a function function set up it's going to be Public public of course and we're going to need a whole bunch of stuff in here setup oops what are we going to need well we're probably going to need at least these four contracts so let's go ahead and import them import magga nor from asrc magor doou import box from Sr cbox doso import time lock from here hit a co-pilot taking over a little bit import go token okay it failed it almost took over here from srcg token. Soul oh is that not what it's called ah sorry let's change this name to gov token like this it's good okay so now let's actually deploy some of these so our gov token say actually let's create each one of these my Governor govern or box box time lock time lock give token go token cool first thing that we're going to need is our gov token equals new gov token and I know this doesn't take any input parameters but we should give our gov token we should actually mint some of these this gov token doesn't have a mint function so I'm just going to create a mint function but in your system maybe you just have the Constructor mint to the message. sender I'm just going to go ahead and add this function mint address 2 you 256 amount we make this public um this probably isn't what you want your token to have you probably don't want anyone to be able to Mint any tokens but this is what I'm going to do mint to amount that's it there's an internal function called mint that we're going to call so I'm just going to say I'm going to Mint to some user I'm going to say address uh public user equals make address it's going to be our user here do this capitals user like this say gov token. mint user and we'll do un 256 public constant uh yeah initial Supply equals 100 ether we're going to Mint ourselves 100 ether boom all right cool now something that you'll often forget is that just because you minted tokens doesn't mean you've have any voting power so we want to run gov token. delegate that delegate function and we're just going to delegate to ourselves so we're saying hey we now have 100 tokens we're going to delegate those 100 tokens voting power to ourselves you could delegate it to somebody else if you want to but for our test we're going to do it for us and we need to actually do vm. start prank user because only the user can delegate tokens to themselves and we might as well stay as the user for these next ones just that we can start off as owners of the contracts we're about to do so now that we have our governance token next what we want to deploy is our time lock because in order to deploy our governor we're going to need both the gov token and the time lock so we have the gov token let's actually create the time lock now so we're going to say time lock equals new time lock and what does this take M delay posers executors so let's create those scroll up we're going to make un 256 public constant Min delay delay equals 360 0 which is going to be 1 hour this is the delay after a vote passes right so this is the time locks M delay nobody can actually execute a past proposal proposal until an hour goes by boom we'll do M delay what else do we need we need the proposers for stuff and we'll just make this at the top address array proposers address array executors and we'll just leave it blank because we don't care proposers executors and this is actually how with the time lock controller you say anyone can propose and anybody can execute you just leave these arrays blank cool looks good good okay now that we have that we finally can deploy our governor contract cuz we have these two so we'll say my or what do we call it do we just call it Governor yep Governor equals new my governor of token time lock like that now we have to Grant some roles so the time lock actually starts with some default roles and we need to Grant the governor a whole bunch of roles and then we need to remove ourselves as the admin of the time lock right we don't want single centralized entity to have power over it so first we got to get some of the roles so we're going to say bytes 32 proposer roll and the way that the time lock has roles is that it hashes the names of stuff so we'll say proposer roll equals time lock proposer Ro there's this function on the time lock called proposer role uh and we're we're going to allow this proposal role to be just the governor so only the governor can propose stuff to the time lock say bytes 32 xq TQ rooll is going to be time lock. executor rooll we're going to give this to anybody by saying it to the zero address and then bytes 32 admin roll right now that's us time lock dot nope it's going to be time lock admin roll and so like I said these are just kind of the um these are hashes in the time lock and we just need to update these we're going to say time lock or time lock dot it has a grant rooll function we're going to Grant this proposal Ro to the governor so only the governor can actually propose stuff to the time lock say time lock. Grant roll xq to rooll to address zero which means anybody can execute a past proposal and then time lock. revoke roll revoke the admin Ro from user so the user will no longer be the admin and then we'll say bm. stop prank this then we just need a new box box equals new box and now we're going to transfer ownership of the box to the time lock and the time lock is owned by the Dow so we're going to say box. transfer ownership to address lock so transfer ownership a common misconception here is oh shouldn't we transfer to the Dow no we should transfer to the time lock so the time lock owns the Dow so the time lock owns the Dow and the Dow owns the time lock it's kind of this weird two-way relationship but it's the time lock that gets the ultimate say on where stuff goes so we transfer it to the Dow and so we can even do a quick test function test can't update box with governance public oops public we'll say vm. expect revert box. store one like this since our box has a store function that's only owner the owner is now the time lock SL the Dow oops if I try to run this test right Forge test- M paste this in this should pass because you can't update the Box unless it's through governance and this will also be our sanity check to make sure our uh all of our code is compiling which it is okay great let's keep going so now let's make a giant function function test governance updates box public and this will show you the exact process from a code standpoint of how one of these dows actually work so first let's get started un 256 value to store is going to be 888 boom so we're going to update our box right this box here we're going to update this new number to 888 okay let's come up with a proposal right remember if we show up my Governor we click into governor in uh and we click into Governor function propose right here first thing we need need to do to kick off anything is propose something hey we are going to propose that box updates the stored value to 888 so we're going to need to have all this stuff in here targets values call datas descriptions so let's start with description because that's simplest right string memory description equals store one in box that's it that's our description pretty easy right what else do we need okay we're going to need some call datas oh well we know what call datas are that's that function selector and all that other stuff that we learned in that nft one right so we can say bytes memory so if you go back to The Foundry nft f23 we go to SRC subl lesson we can remember oh wait we can we can call anything that we want right and all we got to do is encode stuff right like ai. encode with signature or encode with s ctor or whatever we want to do here so we can actually say oh okay so this allows us to make any function call that we want so we'll encode it by saying encoded function call equals we want to well what do we want to call well we want to call this store function ah so we know the function signature of store is going to be store unit 256 so we can say ab. encode with signature we're going to call the store function like this and then what else do we need well we need the value like this and that's it cool let me toggle the word rep here cool so we have the encoded function call so we have the call data that we need to call in okay great what do we need next know we're going kind of in this reverse order values uh well we don't really care to send any value right so let's even just go to the top here we'll make a un 256 array values it'll start off as blank we'll just say values. push zero cool we'll just have it be empty we're not going to send any eth and then the final thing we need is targets so we want to call this on the box contract right oh and actually call Dat is is also an array so we're going to do a couple things we're going to do values all datas and targets targets right so the call datas is a un 256 no call datas is a bytes array targets is an address array so we're going to say values. push zero call datas do push that encoded function call that we just made and then targets. push the address of the box right so now we have all that now we can finally call our proposed function and what does this proposed function return returns this un 256 proposal ID and we need that to keep going so first thing we're going to do is propose to the Dow propose to the Dow so say un 256 proposal ID equals governor. propose the targets values call datas and description boom and we got our proposal ID just like that now we can even view the state of this proposal now right because we can call that state function so we can do even like a little console.log proposal State uh we can call a state function like this actually get a copilot has this right except for we want to turn this into the U 256 version so we'll say un 256 governor. State proposal ID like this and if we look up function state we'll find this there's like a million of these in our governor. soul it returns this proposal state which if we control or command click on that we can see all the different states it can have pending active canceled defeated succeeded cued expired executed so pending obviously is going to be zero active is obviously going to be one canceled is going to be two Etc right and of course we're going to need to import console from test Okay cool so this should return what should return pending it should return a zero and it hasn't started yet it's not active because there's a delay right so we want to actually update our fake blockchain to move past that so we'll just do vm. warp we'll use these cheat codes remember lock. timestamp plus and then we'll just do voting delay you went six public constant voting delay equals one this is how many blocks till a vote is active right and from our wizard we just left this as one oh if we go back to Governor we just left our voting delay is one so this voting delay is one so uh plus voting delay and then actually we'll do voting delay plus one and then we'll also do roll to increase the time as well bm. War excuse me to increase the number block. number plus voting delay plus one now if you view the state it should be active so now it'll be active cool two after a proposal starts because we've proposed enough time has passed we now can actually start voting on something so I'm going to do this cast vote function but I'm going to do cast vote with reason because I like cast voting with a reason so we're going to do Str string memory reason equals cuz blue frog is cool that's going to be my reason that's why I'm going to vote for something because blue frog is cool in order to vote we're going to need to call this cast vote function and if we go to Governor we look for the function Vote or excuse me cast if we go on our search bar we can look for function cast vote there's a whole bunch of cast votes we can see in here we need to pass a proposal ID and support how do we know support works well let's look at this c v internal function this c vot internal function down here support count vote we got to look at this count vote function so let's look for function count vote okay this is the abstract implementation let's we don't want Governor compatibility Bravo we want Governor counting simple cuz that's what we're using Okay support how to support work aha okay so there's this vote type struct that it's checking for let's go to the vote type okay against for abstain so against is going to be zero four is going to be one and abstain is going to be two so what do I want to do I want to write vote four so we're going to do one so we're going to say we have our reason you went 8 vote way equals 1 which means I'm voting for voting yes if you will and now let's do our vm. prank our user or our voter and we'll do governor. cast vote with reason proposal ID vote way and reason reason all right cool now that we voted let's speed up this voting period because everyone voted because we're the only voter let's speed up this voting period and we set the voting period automatically if we go back to our my Governor right voting period was set to one week in here this number represents one week so we're going to speed up this voting period I'm going to copy this number scroll up to the top we'll do U 256 public constant uh excuse me voting period equals this oh and this should have a semicolon voting period we're going to speed through the voting period I'm going to just copy these change this to voting period voting period now now that we' voted and the voting period is done what do we do well we actually need to cue the TX before we can actually for execute so we have to queue it first so there's a queuing process so on our my Governor there's a function function q and a whole bunch of them have this let me open this up function Q on this Governor time lock controller there's this queuing bit because a cue means it's passed but we have to wait to cue it up we just pass the same bits that we originally did for propose so we're going to go back here we'll say the only difference is we need to Hash the description first so we'll say bytes 32 D description hash equals check 256 api. encode PCT description now we can call governor. Q proposal ID uh excuse me this is not right c.q um targets we're going to pass the same values that we propos with so that we guarantee it's the same proposal so targets values function uh call datas and description hash we don't need that zero we're going to queue it and then we're going to finally wait this m delay which we said hey after a vote passes we need to wait this m delay before we can execute so I'm going to copy this again paste it here instead of voting period this going to be M delay M delay and then finally we can execute so we'll do governor. xeq it's going to be the same as what we did to queue it up I even just copy this whole thing paste it here targets values call Dat is description hash X let me spell this right and now finally we can do assert box dot get number equals the value that we stored boom we can do like a console. log box value box. number okay copy this open our terminal clear Forge test DM paste dvv so we can see the console that logs pull it up is this what we've been waiting for no we ran into an issue we see these two logs proposal state is zero we're getting vote currently not active so let's add a couple more these so we can see where it failed it looks like it got to the cast vote with reason and it failed so let's go to our test so it looks like it proposed okay it looks like this failed so it says it's currently not active so did we mess up our voting delay ah it's cuz I did warp for both this should be vm. roll let's see do we do oh we messed that up for all of them let's fix this roll roll roll okay cool let's clear let's run it again hold this up oh my goodness it passed and we can see in the logs proposal state was Zero we waited and then it became IM active and then finally after we got through all the different states we finally were able to update the box I know we kind of sped through this section but like I said at this point you're becoming a pretty sophisticated smart contract engineer and I really wanted to show you the process of voting of a typical from today and for you to see it from the coding side as well now if you want to go further with this I highly recommend you look into some of the different methodologies and some of the newer methodologies that researchers are coming out with for people to actually do votes because like I said plutocracy is not the best so if you want to go farther try experimenting with other ways to build Dows maybe flesh out your own Dow maybe deploy a dow do whatever you want to do here but in any case you should be incredibly proud of yourself because you got through the hardest lesson of this whole course already which was the stablecoin one and then you just learned this incredibly powerful Advanced course in how Dows actually work students we're almost at our end there is one more lesson for us to do and it's our smart smart contract and security auditing for developers do not leave this course without watching this I want you to have at least the fundamental knowledge of where you should look for security help what you should have in mind for security especially now that you have the ability to go out and deploy some amazing contracts I'm not going to teach you how to audit step by step here right but I am going to teach you here's what you should be looking for in an auditor here's how you can begin to start thinking about security and I am working on some security and auditing education material as well to make those of you who do want to go down that path successful so give yourself a pat on the back do a little dance do a little celebration get some ice cream and I'll see you in the next one and then I will I will release you to the world so pause the video and I'll see you soon and as a special piece of bonus content we have Harrison here to give us some tips on gas optimizations so enjoy hey guys I'm Harrison leio and I'm the CTO and co-founder of pop punk LLC where we're building Gaslight GG uh Gaslight GG is a audit firm but we focus specifically on gas optimization for protocols to ensure that your gas costs are as low as possible uh in addition we're happy to announce that we're now building building uh hyper optimized public goods tools for evm developers to make sure that everyone has access to just the best and the cheapest contracts so Patrick invited me on here to show an example of some common ways that you might be using too much gas in your smart contracts Without Really noticing so I have a quick example here we're going to look at an airdrop contract this is a super basic airdrop contract which I'm calling airdrop bad or bad airdrop uh very simple we have a token we're using a counter to iterate um and count the number of transfers uh so as you see in the Constructor we set the token here uh and then we have our airdrop function so we have two parameters um for this function the first one is a memory um array of addresses which is the recipients and then we have a memory array of un 256s for the amounts the first thing we're doing is we're checking to make sure that the amounts match otherwise we're going to revert the next thing here which is really common um is making sure that you're batching your your actions so if we see in this case we have to Traverse through the entire uh put argument array a fulltime just so we can transfer the number of tokens from the message. sender to the contract so let's say there's 50 amounts we'd have to do 50 separate transfer from it's definitely not ideal uh and then lastly here we have a super basic Loop where we're just iterating through the array um and we are transferring the tokens from the contract to the user with the respected amounts here uh lastly we can see that we're iterating this counter every single time in the array or every time in the loop yet yeah so keep that in mind so now if we look at a more ideal example of this the first thing that you're going to notice is we're using a mutable for the token a mutable is good if you're obviously never going to change something because we set this value in the Constructor and it'll be included in the contract deployed by code which is cheaper to read from every time if we look now here we've changed our arguments for our function to call data and we've added a new one called total amount this is done so we don't have to do two Loops through the array we can do one so if you see here the first thing that we're doing is we're transferring this total amount from the message. sender to this contract so that's going to cut a large amount of gas because we're only going to wind up looping one time so if we see here we we've changed the way that we're going through the loop technically we don't have to Cache this array length because we're using call data but if you do see here it's the same thing we're transferring tokens from this contract to the recipient uh we're also using unchecked for our Loop iterator because it's not going to overflow cuz the odds of someone doing an airdrop to more than the max un 256 of addresses is kind of crazy um and the final thing to look at here we're using an unchecked block again but rather than updating this state value of transfers every single time and paying that base G gas cost each time we can just update this amount at the end with the bulk length so these are small things that you can think about when you're writing your smart contract to ensure that you're saving as much gas as possible if we look at the results of this the airdrop bad costs uh 1,9 9 4,690 gas and the airdrop good cost 44,8 42 gas so we've essentially saved 600,000 gas just by doing simple things you know it doesn't make the code unreadable um and you're just making sure that you know the end users of this will not have to spend a crazy amount of money so I want to thank Patrick for having me on here uh you can find me on Twitter atop Punk on chain um or the business account is at pop punk LLC if you're a small protocol or a large protocol feel free to reach out for gas Audits and uh pretty soon in the near future you'll be able to go to gasl light.gg and you'll be able to deploy super cheap super gas optimized smart contracts you know through no code and just pressing one button thank you all right welcome back to our last lesson of the course I hope you're excited because I sure am in this last lesson we're going to give you just a teasing of smart contract security and auditing this is especially for developers we're not going to go over everything security however in here I'm going to leave a ton of places where you can learn and grow and absolutely be sure to sign up for web3 education. deev because we're going to put a whole lot more security information in here as well but we are going to give you the foundational information that you need to even begin to start thinking about where to go and how to work with security in the space we have this repo Denver security to talk a little bit more about security and how it works but I want to give you all a couple of stats before we even jump into security to impress upon you why this is so important this is probably the stat that's the most jarring to me according to chain analysis as of last year 2022 about 3.8 billion dollar was stolen in crypto hacks and about 3.1 billion of that 3.8 billion was specifically Defi and if we go to defi llama last year defi had a total value locked of around 50 billion so if we do the math there 3.1 / 50 we're talking around 6% of all defi was hacked last year that's like walking up to a bank and saying hey can I put my money in you and the bank going yeah sure just ah heads up there's a 6% chance all your money will be gone next year that is an insanely horrible statistic and it's why we need to put so much more focus and so much more emphasis on on security there's a popular website called w. newws that has a leaderboard that if you go to you can see a lot of the top biggest hacks hugest hacks that ever existed went off of code that was unaudited unreviewed by Security Professionals unaudited un audited unaudited uh Na Na un audited unaudited unaudited unaudited out of scope United out of scope and it is not acceptable some of these hacks were absolutely massive losing over half a billion dollars so if you're a protocol or if you developers go on to build protocols here is what you want to think about you can maybe spend $2 million of your budget on security or get hacked for $200 million the spending money on security is a 99% reduction in cost so if you approach security from a business perspective it absolutely 100% makees sense for you to spend resources on security so to kickart this video all of protocol devs will probably want to get a smart contract security audit at some point a security Focus code review before you launch your protocol so let's start there I've made a video recently on what a smart contract audit is and how to prepare for a smart contract audit that we're going to watch first because even if you don't want to become a smart contract auditor yourself you'll need to know what a smart contract audit is for when your protocol is going to go launch to maintenance so let's start there a smart contract audit is a timeboxed security-based code review on your smart contract system an Auditor's goal is to find as many vulnerabilities as possible and educate the protocol on best security best practices and coding best practices moving forward Auditors use a combination of manual review and automated tools to find these vulnerabilities now why are these so important why is it critical that you get an audit before deploying your codebase to a live blockchain well for starters there are entire websites dedicated to how many hacks happen last year we saw the most value ever stolen from Smart contracts with almost $4 billion stolen due to the immutability of the blockchain once a smart contract is deployed you can't change it so you better get it right the blockchain is a permissionless adversarial environment and your protocol needs to be prepared for malicious users but even more so than that an audit can improve your developers team's understanding of code improving their speed and Effectiveness in implementing features moving forward and it can teach your team the latest and greatest Tooling in the space often just one smart cont audit isn't even enough and protocols go on a security Journey that includes many Audits and many different services like formal verification competitive Audits and Bug Bounty programs we'll break these down in a future video there are a lot of companies that offer smart contract auditing services like trail of bits consensus diligence open Zeppelin Sigma Prime spearit Dow mix bites watch pug trust and of course cyphon additionally there's a lot of independent Auditors that do great work as well a typical audit looks like this price and timeline first a protocol needs to reach out and they can reach out out before or after their code is actually finished ideally they reach out sometime before their code is finished so the otter can have time to slot them in once they reach out the protocol and Auditors will discuss how long the audit will take based off of scope and code complexity the scope of the audit is going to be the exact files and commit hash that's going to be audited how long the audit usually depends on how many lines of code SL complexity you can see a very very rough approximation of how long an audit takes on your screen now of course this depends firm to firm audit to audit and tool to Tool so take these with a very large grain of salt additionally it's this duration that sets the price and same thing at the time of recording Prices range wildly depending on who's doing the audit how many people are doing the audit how complex the code is and more and these initial conversations are really just to get a ballpark estimate and Slot you into the auditor schedule commit hash down payment start date once you have a commit hash you can finalize the start date and final price the commit hash is the unique ID of the codebase that you're working with so the Auditors can know exactly what code they're going to be looking at some Auditors will ask for a down payment in order to schedule you in audit Begins the Auditors will use every tool in their Arsenal to find as many vulnerabilities in your code as possible we'll give you some tricks in a minute to make this a successful step initial report after the time period ends the Auditors will give you an initial report that looks something like this with all their findings listed by severity usually categorized into highs mediums lows informational noncritical and gas efficiencies High mediums and low represent the severity of impact and likely hood of each vulnerability informational gas and non-critical are findings to improve the efficiency of her code code structure readability and best practice improvements that are not necessarily vulnerabilities but more ways to improve your code mitigation Begins the protocol's team will then have an agreed upon time to fix the vulnerabilities found in the initial Auto report sometimes depending on the severity of the findings this might mean you have to start from scratch but more times than not you can just implement the recommendations the Auditors give you this is usually much shorter than the audit itself final report after the protocol makes these changes the audit team will do a final audit report exclusively on the fixes made to address the issues brought up in the initial report then hopefully the protocol and Auditors have a great experience together and we'll work together in the future to keep web 3 secure now there are a few key things that you can do to make sure your audit is successful as possible to get the most out of your audit you should have clear documentation a robust test Suite ideally including fuzz or invariant tests code should be commented and readable modern best practices are followed there should be an established Communication channel between developers and and Auditors during the audit and an initial video walkthrough of the code should be done before the audit starts the most important part of the process is going to be during the audit to get the best results you want to think of you and your Auditors working together as a team one of the best ways to do this is to have a dedicated Channel where Auditors can ask questions to the developers the developers will always and forever have more context over the codebase than the Auditors ever will because they have spent so much more time working on the codebase and the more documentation context and information that you can give to the Auditors the better this way it can be easy for anybody to walk through the code and understand what it's supposed to do in fact 80% of all bugs are actually business logic implementation bugs this means that these are bugs that have nothing to do with some weird coding error and are just somebody not knowing what the protocol should be doing so it's vitally important that the Auditors understand what the code should be doing having a modern test suite and tooling can also make Auditors spend less time fidgeting with your tooling and more time finding issues post audit we highly encourage you to take the recommendations your auditors you seriously additionally after an audit if you make a change to your code base that new code is now un audited code it doesn't matter how small the changes we've seen a ton of protocols saying oh I'll just slip in one line of code and sure enough that's the line of code that gets exploited and often depending on the seriousness of your protocol and how many users you want to use it one audit might not even be enough working with multiple Auditors and getting more eyes on your code will give you a better chance of finding more vulnerabilities what an audit isn't now here's the thing an audit doesn't mean that your code is bug free an audit is a security Journey between the protocol and the auditor to find as many bugs as possible and teach the protocol different methodologies to stay more secure in the future security is a continuous process that is always evolving no matter how much experience someone has people at all levels have missed vulnerabilities on the unfortunate day that that happens be sure that you and your auditor can jump on a call quickly to try to remedy the situation and maybe consider getting insurance for your protocol as well so now with that being said now you have a good idea AA of what a smart contract audit entails and what to expect end to end a smart contract audit is a security Journey end to-end leveling up your protocol so that you can have all the best practices and security know how to deploy your code to a live blockchain forever and of course if you're looking for an audit be sure to reach out to the cyphon team Link in the description and as always stay safe out there and we'll see you next time all right great welcome back so now that you know a little bit more about what a smart contract audit is let's talk about the process that smart contract Auditors and Security Professionals take and the tools that they use security is both for protocol developers and for Auditors you as a smart contract developer need to know all these tools and probably should use all these tools before you even go to audit at the end of the day it is you who is responsible for the codebase that you launch and additionally you often can't just do security at the end you have to have security built in from the architecture from day one for example if you build a car and the car is a total piece of garbage and you say hey cool it's time to race you're probably just going to have to start over and and it's not a very good use of time for you to even go to the audit there are some tools like curity which which have opinionated security and code quality standard for solidity smart contracts and we showed you the simple security toolkit from n XYZ for great places to read before you go to audit and make sure you have have checked off or you've looked at this doc to make sure you're even ready to go to audit but anyways let's talk about the audit process so there is no Silver Bullet but typically the smart contract audit process goes through process of manual review and then using tools and there are a ton of tools Security Professionals use to make your code is secure now manual review is probably one of the most important if not the most important tool that we have in our toolbox manual review is literally going through the code line by line going through the docs and making sure the code actually does what it's supposed to do there's kind of a joke in the developer Community where if you just read the documentation for 15 minutes you'd be way better prepared to actually do code but a lot of people don't do that so step one on any audit is really getting some understanding of what the protocol should do most bugs are actually business logic issues and the only way you'll know if business logic is wrong is if you understand what the protocol or the business should do and repetition is the mother's skill so the more you read code the more you read docs the more you do these audits the better you'll get for example for example if we had a contract like this this caught with test we have this set number function this code technically isn't wrong right it'll compile fine it'll deploy fine but maybe if we read the docs and we read that set number was supposed to set number to new number we would then read this function and go oh my gosh you're setting it to new number plus one that's clear clearly wrong right and the only way we would have caught that bug is by understanding what the function should be doing so that's manual review now let's talk about some of the other tools that we have in our toolbox here the first line of defense is going to be test sues which is why we spent so long in this course writing test Suites all the most popular Frameworks out there have test Suites I don't really need to go over them because you have already done so static analysis this is something we haven't gone over static analysis is going to be automatically checking code for issues without executing anything hence the debugging is static most of these tools were sort of just dumbly look for keywords in specific orders and AI is actually going to be an example of static analysis as well and we'll show you an example of all of these once I get through this fuzz testing we've gone over fuzz testing it involves providing random data as inputs during testing uh we have stateful fuzz testing which we've definitely gone over in this course as well differential testing which we aren't really going to go over but it's a way to actually write the same code multiple times and compare the code against each other but then finally there's formal verification now formal verification is a generic term for applying formal methods to verify the correctness of Hardware or software applying FM means anything based off of mathematical proofs in software often used as a proof of correctness or proof of bug or just mathematically Pro prove that something in your code can happen this can be a little bit confusing obviously um but to me the way that I generalize it is you basically take your solidity function you take your solidity code and you convert it to math and math can be solved math has right and wrong answers 1+ 1 equals 2 right so we convert our solidity code to math and then mathematically prove or disprove it symbolic execution is one of these formal verification these formal methods and symbolic execution involves converting our code to a mathematical expression there's some tools here like Matt mantor Z3 Cur even the solidity compiler actually has a symbolic execution climent there is a fantastic article on hackam D by Paulina who goes over some of these different symbolic execution clients and Compares them to each other I left a link to this of course in the GitHub repo associated with this course symbolic execution is one of these tools that is the most time intensive and a lot of protocols and a lot of audit firms don't even go down this route because even symbolic execution isn't a silver bullet it's not a guarantee that some code has no bugs it's not a guarantee code is bug free but especially if you have some incredibly math computationally heavy process symbolic execution or form of verification might be a good tool to use AI tools AI tools are a work in progress long story short sometimes they're okay and sometimes they're absolutely terrible all right so now that we know some of these tools let's actually see them in action and I'm going to go kind of quick here but what we could do is if we're in the GitHub repo associated with this course we can actually download this Denver security rep now this does not have the- f23 at the end of it because this is a lesson that I've done in the past but it is associated with this course and what we'll do though is we'll just clone it we're not going to build a project from scratch here we're just going to look at some code ourselves so do get clone paste it in do code Denver security we'll open that up in a new tab here and and I want to just show you how bugs can be found with some of these different tools here so in our SRC folder we've got a couple of files here we have caught with fuzz caught with manual review caught with slither staple fuz symbolic CAU with test Etc each of these has a bug in them where one of these methods was going to be how you catch it our first one C with man cut with manual review we'll do a toggle word wrap the way we can catch this bug is just with manual review right so we have this function do math and the comments or the docs here say Dev adds two to number two add and returns it we can then easily read the code and say oh my goodness we're only adding one boom that's an issue that's a bug that's something that we would want to fix that's how we would catch this one next CAU with test Soul this is the one that we saw in the presentation that we gave set number should set the number a unit test would easily catch that this was wrong all right what's next static analysis or Slither now this is something we haven't really gone over but one of the most prevalent hacks in this industry is going to be a something called a re-entrancy attack and you can read more about it in the solidity by example re-entrancy I've left a link to this of course in the get AO associated with this course but there actually tools that will automatically check for stuff like this if I pull up my terminal and I use this tool Slither I've already gotten installed you can go ahead and check out the install instructions yourself but if I run Slither dot it'll automatically compile my codebase and then it'll give this massive print out of a ton of the issues that it found and right at the top right in red it can see hey there's a withdraw issue there's a re-entrancy issue with your withdraw function and then obvious L we could go back update it rerun Slither and this would go away so a lot of these issues have tools that you can just run and it'll automatically detect so slyther is one of these tools that I think everyone should run on their codebase before going to audit what's next we've caught with fuzz which we know what fuzz is we learned about fuzzing we have this massive function we see this here say should never return zero so there's probably a fuzz test so if we look in our fuzz test we actually smartly wrote a test fuzz here where we say hey the return number from that function should never be zero we can then grab that Forge test Forge test d-mt what's it called test fuzz and we see we get a failing test here we see we found that if it passes 1 265 it actually will fail come back to our test here and we can see there's a conditional if my number equals 1265 1265 modular 1265 is going to be 0 + 1 - 1 * 1 is 1 which means it return zero and we don't want this to return zero which means we break our invariant if we call change value with zero it'll set my value to zero up here and then we can call do more math again with 0o we're going to get 0 divid 1 + 0 return zero and boom this will break as well and then finally we have symbolic here where we can actually just use the solidity compiler to do symbolic execution we have these two functions Function One Function One symbolic where we have this revert in here and this is going to be the bug in solidity we can add asserts to our code base and we'll go over a video that explains this more in depth to tell our solidity compiler hey this should not hit and this should hit this conditional should not be hit this one should hit in Foundry in our Foundry doomo we can add information in here to send to the solidity compiler we're going to tell our solidity compiler to use the CHC model Checker time out of 1000 and to look for those assert keywords and if we just run Forge build or Forge build-- fors to force it to rebuild it'll compile and it'll give us this output here saying warning CHC assertion violation happens here meaning it found an issue it found an input such that this assert line hit so if we pull up our terminal we can scroll down we can see exactly we can see exactly what the input is 8088 is the input that will allow that to hit if we look 80 8 8 / 4 does indeed meet this criteria so it would go ahead and revert here so those are some of the tools we have in our toolbox we'll go over symbolic execution a little bit more but let's wrap this lesson up so to talk to us more about the process of manual reviewing we have legendary ethereum smart contract researcher tincho to walk us through his process in a real process of him going through ens he did an audit on ens Just for kicks and ended up getting paid out $100,000 for finding a critical vulnerability so let's learn from legendary manual reviewer Tino this is Tino theum security researcher previous lead auditor at open Zepp and creator of damn vulnerable Defi and today we have the pleasure of talking with tincho going over his auditing process so that you can learn how to make damn unv vable defi to do this we're going to be doing a live mock audit of the ethereum name service GitHub seeing exactly some of the tools and techniques that tinel would use to audit this I don't have a super formal auditing process I really think that everybody will find their own ways I will just show you briefly some things that I do today link to the full interview in the description let's get froggy so this is a repository for Ys the first thing that I will do is obviously go to Repository would clone the repository to my local environment but if you're like very unfamiliar you should probably go to the documentation at least I don't know read the introduction now he says there's no formal audit process but this sounds like a good step one download the code read the documentation read the documentation here we have the architecture is telling us like already some keywords that we will need to understand at some point such as what a registry is what a resolver is already I will get familiar with this probably these are contracts that I'm about to see in the code and so on and so forth one thing that you can do also after reading some documentation is looking at audit reports if we go to the actual code we will realize that there are lots of things wait a minute what the heck is that logo what wonky text editor is tincho using that my friends would be vscodium it's different from vs code vs code is a product owned by Microsoft that actually sends a lot of your usage information over to Microsoft vscodium doesn't do this they have removed I think Telemetry and some things related to Microsoft said he's just been trying it out recently but maybe it's a security Alpha leak so multiple contracts in here already we see lots of folders it's using harut from what I can tell these days I like projects that use Foundry more than those that use harut so in that case what I would do is I created another folder in which I have a Foundry local setup why do you like Foundry better why do you make this Foundry local setup it's faster and I can write quick test only using solidity I will do whatever thing that I want to do here but it's just an easy way to have something quick and dirty to test things quickly bring and use the tools that you're most familiar and best with I think that's super important and don't be afraid to bring your disgustingly horrible dirty dirty tests but anyway already we saw that it's quite complex so what I would do in this case is there is a command light utility that I would use which is called celoc celo will help you count lines of code and so I would use SEO it would give me a nice output that you can actually pass to to a CSV and instead of doing this here what I would usually do is I would move that to a spreadsheet that I have the scope fors right all these files are now ordered here and now I can have a better view in terms of how many files do I have how complex they might be so apparently I have 59 files and now I know the name wrapper will be one of the most complex conts perhaps right because it has more than 700 lines of code another approach to do this scoping phase you can actually use this tool by consensus which is called solidity metric so you can run it on a project and it will actually give you a nice report of the codeb and its level of complexity and then I have a column stating where the thing that I'm doing is not started it's in progress or it's done so this is his next step he either uses solidity metrics or SE loock ranks all the contracts that he needs to audit based on complexity and starts going through it moving contracts from not started to in progress to done a very organized approach when you this alone it might seem silly but when you work in is quite important as the progresses I will be less and less focused on this file because probably this is super complex and will be related to either but most of all it's very useful at least for me at the beginning of the just to understand what am I looking at once I have this table and I usually start with the little Legos and then I go move up in complexity so in this case I will probably I don't know start with the erc20 recoverable contract here it is and it's quite short say okay it's ownable inheriting from open saing asor probably I can take that granted which is out of the scope and I will assume that's working correctly and it has a single function to recover funds okay it has ACC control so this is probably fine as long as they are handling access and controls in their right way this is fine and it's actually doing this right so we start with the small little building blocks or Legos as Tino said and now you're going to see Tino's brain start switching into how can I break this as an aitor you might start wondering where this is good for any token out there right where it's possible to actually execute a transfer on any address that the owner passes here and where that could be problematic for behaved erc20 tokens and if you're familiar with usdt for example that could be problematic in this ah and now we're seeing him drawing on his expertise knowing that usdt is a weird token usdt actually doesn't return a Boolean on its transfer froms whereas a lot of other tokens actually do what the fck usdt when you see that only owner function do you think okay is this a dow is there a single person who controls what are your thoughts at least at the beginning I wouldn't worry about it too much at some point I will read documentation about roles of this but yeah at some point I should probably understand at some point Who's the actual owner okay let's say that you think that this is okay so what I would do usually is I would take notes in the code right so in this case I would say like Access Control okay for example just to have a note saying that I was here or you can have a question like pck said is this governance right and let's say this was an issue so so I would do this shouldn't be I let's say shouldn't be owner another thing that I do to take notes is actually have notes files in the same place very rare notes very having a file where I can quickly dump ideas that I have some point things so go well I would have an issues list here I will start listing I know in line blah blah blah of file blah blah blah list issues take notes in the code in a notes file somewhere just have a place where you can dump thoughts maybe you can even use a note taking plugin I don't use any plugins that's because I don't like having the UI CL too much with stuff yeah I no taking extension was a dumb idea and one thing that you have to be careful when you start with the very little things so it's very easy to go deep into the rabbit hole of the single thing that you are trying to AIT is that for example I have very little knowledge of DNS I'm not like super familiar with the and I got like very like down into DNS because I was just paying attention to this single resolver and that led me to realize that after I know two days I was growing familiar with DNS but I was losing the big picture of actually hey I'm actually fing enss so it's very easy to go deep into the rabbit hole of the single thing that you are trying to audit remember to jump out of the rabbit holes perfect so at some points in during the audit you will realize that you might need to test things so in this case I saw these two functions one is going from my bites thing returning an address and the other is doing the other way around it you might say it's okay but if you're lazy you can actually use Foundry to help you in that so what I did in this case I used my very hungry hacky Foundry rep that I have in here and I actually copied these two functions to a contract like I just took them not even trying to do fancy Imports or whatever just BR copying and pasting them here and I did a quick test H fasting test in which I provide address I pass that address to this for function and the result of that I pass it to the other function and I want to make sure that I always get the same address as said a lot of times yes you're going to write code and not just do manual reviews Teno here wrote what's called a fuzz test which you should absolutely smash that like button because we're going to have a video on that sometime in the future use your tools to validate findings that you have an inkling are wrong in the cas is where I have to set up more complex stuff perhaps having a separate folder with a single project is not that convenient because I would need to set up the whole in a system and that wouldn't be that convenient so in those cases I would go to the actual testing environment of the project if you're doing a private AIT how important is the process of of talking and interacting and and keeping Communications with the client open I would say it's almost fundamental usually developers will have much more context than you as an auditor on what the system is intending to do so you can spend a whole week trying to f figure out on your own where this modifier should be in this function or not but if you actually send a question to the client and tell them hey should this be here or not and they will say yes it should be here you can see it in test blah blah blah you can see them as companions during the audit and you should rely on them you can rely on the client AO protocol is your code good you think so hell yeah my work is done having said that it's also important not to trust too much at the end of the day they are trusting you as the expert so in this in that sense I would advise okay keep the clients at hand ask questions but also be detached enough since they built the code they have spent more time thinking about the code and looking at the code than you ever will ask them questions and don't be afraid to ask questions I guess at this point what's the next step are we wrapping up now are we writing the report up what do we do next the thing is I always get the feeling that you can be looking at a system forever there's always one additional that you can check there's always one additional attack that you can think of one additional potential C vulnerability and everything so what I do is I time bound myself to have a certain level of confidence when you're shipping the report that you did your best and you thought of every single possible attack or vulnerability that you could think of in that limited amount of time time bound yourself when you're going through this code how are you thinking of different attacks like when you're looking at a piece of code how do you you get that context of what different types of attacks to think of yeah I don't have a checklist very difficult to translate experience in doing it have this adversarial mindset of try to at least there's lots of knowledge that can come from oh every single day read vulnerability reports every single day between or reading responsible disclosures that published reading all reports I read newsletters like I don't know I have this constant influx of security related information to solidity that little by little I think you start growing the intuitions the experience that actually help you identify quickly things that can happen in smart contacts and always remember that you can miss things there's no perfect auditor I think that everybody has audited sufficient enough and complex enough systems they have all Mi issues and it's okay security is a is a thing that we have to approach from many different angles and auditing is just one thing that must be done but it's not the only one knowing that you're doing your best in that knowing that you're putting your best effort every day growing your skills learning grow and intuition and experience in you something that I always say is to audit to me is 50% finding M abilities and 50% delivering readable report once the client starts fixing the isses they will send you the fixes for the issues and what you have to do at that point is actually review the fixes and make sure that not only the vulnerability that you highlighted in the report is fixed but actually this have been introduced by the fix and then you wrap up your whole auditing process with writing a very good report and take the time to do so once you give them the report they will go ahead and fix the issues come back say hey we fixed them and then it's your job to make sure that they fix the issues and they didn't reintroduce new bugs let's say you give your audit report you done your time box you've done as much as you can you think you did a good job four months goes by oh my God $100 million hack they've ended it up on Rec what do you do what happens let me approach it slowly okay I would first say I have always been of the idea a security Cod review should be valuable enough beyond the fact that I find or not find a critical issue so I should be able to provide value to whoever is working with me to whoever is trusting me beyond the fact that I did or did not find a obviously the less critical issues that you miss the better the safer and perhaps they miss something and that can happened and has happened and will continue to happen but it's naive to think in my opinion that just because an auditor missed something whole blame of thing is on the o this I think is a really important final thought you as an auditor it is not solely your job to make sure their code is bug free you share that responsibility with the client however this doesn't give you free range to suck at your job people will notice so to understand symbolic execution a little bit more we've got some members from the trail of bits team to teach us about symbolic execution and formal verification formal verification is the act of proving or disproving a given property of a system using a mathematical model symbolic execution is one technique used for formal verification symbolic execution explores different paths in a program creating a mathematical representation for each path or more plainly converting your code to a set of mathematical Expressions is this the Silver Bullet for your auditing Journey let's get froggy I had the absolute pleasure of interviewing traa bits head of engineering Joselyn and security engineer from Trailer bits as well Troy about fuzzing testing methodologies and importantly formal verification I have links to the full interviews with both of them in the description and in this video we're going to summarize a lot of that and focus on what formal verification and symbolic execution actually are but to do that we need a quick refresher on some of the testing methodologies that we use in web 3 if you haven't seen my invariant testing video be sure to watch that first before coming here and to really understand this you do need at least a high level understanding of solidity as well what tools do we have in our toolbox to have high Assurance about our program layer one the unit test obviously you have unit tests which you do a very specific thing like this function does this and you start looking at things like test code coverage like statement and Branch coverage and I think that's kind of the bare minimum yeah Absolut bare minimum in security is a unit test for example if this is our solidity and we have a set number function which should set our number variable to whatever new number is a unit test would be able to catch this and if we're using Foundry we could get an output that looks like this so I'm assertion failed and we can go see our test and see that when we call set number to mind number we assert that we get what we want and if that breaks cool our unit tests have saved us Foundry hard hat apworks truffle brownie and all the most popular Frameworks have unit tests built in Layer Two the fuzz test fuzzing is where you take random inputs and run them through your program as you have to Define things in your code that you always want to hold true and fuzz testing is the new bare minimum for web 3 security because I decree and as Troy said you need to understand the property or invariant of your system to do fuzzing once you have your property defined you throw random data at your system in order to break that property if you find something that breaks it you know you have an edge case that you need to refactor your code to handle for example if I have a function like do more math and I know that this function should never return zero I can throw a whole bunch of random numbers in here to try to get it to return zero I can have a fuzz test that looks like this which passes in a whole bunch of random numbers and tries to assert that we never get zero and we can see from our fuzz test it was able to pick a random number in order to break our invariant or property now like I said we recently did a video on fuzz testing or invariant testing and I highly recommend everybody watch that video because I de create Foundry a kidna and consensus diligence fuzzer are some popular fuzz testing tools okay what's next layer three static analysis so the things that we've been discussing unit testing and fuzz testing are Dynamic testing which Dynamic just means like you're you're actually doing something Dynamic analysis is when we run or we execute our code in unit and fuzz tests we do exactly this we are running our code to try to break it in static analysis we just look at our code or have some tool look at our code for example this code here has a classic re-entrancy vulnerability in our withdrawal function if we run a static analysis tool like slyther it'll automatically detect hey you have a re-entrancy vulnerability and this is great for very quickly picking out very specific parts of your code that are known to be bad practice some popular tools for static analysis are going to be Slither created by the trailer bits team and even the solidity compiler could be considered a static analysis tool so now that we have a little bit of a backstory on some of the popular layers of testing and keeping ourselves secure let's jump into formal verification and symbolic execution now therefore formal verification so on a high level formal verification is going to be the act of proving or disproving a given property of the system this is usually done through a mathematical model of the system in a property there's that word again property you're seeing that almost no matter what you're doing in your testing you need to understand the properties of your system and right there josn gave us some of the keys between fuzz testing and formal verification fuzz testing tries to break Properties by throwing random data at your system whereas formal verification tries to break properties using mathematical proofs and there are many different ways to do formal verification such as symbolic execution and Abstract interpretation for this video we're going to focus on symbolic execution as that's one of the most popular ways currently done in web 3 symbolic execution is then one of the techniques that you can use to do formal verification symbolic execution on a high level is going to be a technique where you are going to have your program and you're going to try to explore the different path of the program for every execution paths you're going to create a mathematical representation additionally if you want to look learn more about symbolic execution outside of web 3 I left a link in the description to an MIT open courseware video which does a great rundown of symbolic execution now let's look at Jin's example of using formal verification and symbolic execution let's say this is our function that we want to do formal verification on and we're going to do symbolic execution to do formal verification well let's go back to what formal verification actually is formal verification is the act of proving or disproving a given property of a system using a mathematical model so the first thing we need to do is figure out what we want to prove or disprove for our demo we should say our invariant is this should never revert and that's what we're going to try to prove or disprove now this might seem like a silly example but you can imagine that this was a function called withdraw money and you want users to always be able to get their money out which would seem like a much less silly example symbolic execution is going to be creating a mathematical formula for this function f from our code we're going to convert this function to a mathematical logical representation of every execution path from our code once we have a set of math functions we can push those into a solver which will tell us if a property is true or false or if our invariant is true or false when we talk about the different Paths of our function we can imagine okay one path that our function can take is going to be a + 1 being returned that's going to be one of our paths but we can also imagine that a + 1 is actually going to overflow and therefore revert if we pass in the maximum U 256 a + one would revert so that would be a second path that our function could take and a symbolic execution tool would find this second path for us programmatically and then of course convert these to a set of mathematical Expressions this set of mathematical Expressions might look something like this a and also not a imagine if you ask somebody can this set of mathematical Expressions be true at the same time the answer would obviously be no it is impossible for both a to be true and a to be false this is what our solver is going to figure out for us but with much more complicated Expressions than this in our example the solver is known as a SAT solver or an smt solver and there many different types of solvers but I'm not going to go too deep into that right now running our symbolic execution tool we would see two paths our first path going to be if we give it the maximum size of a u 256 which try add one to it the function will revert solidity doesn't allow you to add one to the maximum size of a u 256 the other path is anything lower than the max size of un 256 we'll just add plus one and then return so those are going to be our two paths path one a is not 2 ra to the 256 minus 1 and then a returns normally and a is 2 raised to the 256 and it reverts however instead of a b c not a etc our symbolic execution tool will give us an output that might look something like this now what you're seeing on screen is an smt lib language and it's a language specifically made for working with these solvers to solve our mathematical representations of our code I'm not going to go over too deeply what this is doing but you can consider this just a list of Boolean Expressions kind of like a and not a and if a therefore B and A B and C Etc now if you take this code and paste it into a tool like Z3 or run it locally on your machine it'll give you an output that looks something like this sat and sat this first set is saying they were able to find an input for path one and they were able to find an input for path two they were able to satisfy the booleans in those different paths since it was able to satisfy an input for path two and we know that path 2 reverts we know that this invariant is now broken because our invariant is it must never revert and our mathematical representation said hey I've mathematically proven that there is a scenario where path 2 is executed and your function reverts so sat here means we mathematically proved that this invariant breaks now I manually created this smt lib list with the help of chat GPT however symbolic execution tools like mant core hvm and even the solidity smt Checker can give you this smt output but all those tools come with a Z3 built in so they'll even just skip this step and just give you hey is my invariant broken or not even the solidity compiler itself can do this entire process behind the scenes explore the paths convert the paths to a set of Boolean and check to see if those paths are reachable or not using the soul compiler we can run with model Checker engine and we can look for an overflow in small soul. soul and if we run this you'll see the solidity compiler was able to do symbolic execution to find out hey if I add the maximum unit 256 as an input to here you're going to get an overflow and that function is going to revert now obviously reverts are pretty easy to find but we could even add assert a does not equal one rerun this but instead of overflow look for asserts and we would see that again it was able to mathematically find an input to break our assert or our invariant said if you add zero you're going to get one asserts are what you're going to use if you want to use more complicated and more specific symbolic execution rather than just overflow or underflows tool like mantor will also give you an output with the revert as well as a much more hypers specific list of S&T lip that it's inputting into its Z3 solver so a lot of stuff just happened here let's recap we built some solidity we understood our invariant and the next two steps happened at the same time with sulk or manacor we use a symbolic execution tool like the built-in one to solidity to create a set of bluing Expressions that represent every execution path of our code and then we dump them into a solver like Z3 to see if our property could be broken just by running this one function solidity was able to do all those steps behind the scenes for us we go through a full walkthrough of this example with the interview with Joselyn so be sure to check that out as well if you want to learn more and don't be afraid if this seems a little bit complicated be sure to ask questions leave comments in the descriptions and leave a like as well and hopefully I'm going to clear this up for youtime the Ser might not be able to serve this equation too like if the equation is too complex you usually provide a timeout to the solver just because you know if you have to invert hash function you know good luck to do that with a silver well so you're saying this isn't a silver bullet for auditing like any technology even formal verification and symbolic execution abstract interpretation these are not a one-sized fits-all approach using symbolic execution can run into something called The Path explosion problem where there's too many paths for a computer to explore in a reasonable amount of time and a Sol would never be able to finish how practical is it to to take all these steps how hard is this to really do well there are a couple of things to consider the first one is that this specific technique symbolic execution has a couple of limitation as you're going to explore the different path of the program there is a problem which is called the path explosion problem which is basically if you have too many paths to explore in the program it's going to take forever if you have an infinite Loop this technique require significant effort to be used you need to understand how they work and you need need to understand their limitation and how to help them and also significant effort to be maintained at the end of the day I think what really matters are the properties if you want to know if a bug can occur and if the property can be broken you don't necessarily need formal method for that and you can use a further which is way easier to use and provide like kind of the same type of value something that is sometimes difficult for people is really to understand how to create this property and how to create invariant for themselves if someone wants to you know learn a bit more we have this website it's called secur track.com where we go a lot of guidance and best practices and among other we have tutorial on how to use Aina how to define invariant how to think about properties there's a high skill requirement to using these tools effectively at the moment people are working on making them easier and easier like the built-in solidity smt Checker however as Jon's been saying sometimes a sufficiently powerful fuzzer is all you need and if you combine a fuzzer with a symbolic execution backend the fuzzer can pick better random numbers based off of the symbolic execution and maybe you can find all the answers you need without having to do a formal verification test suite and the most important piece here is that even this isn't a guarantee your code is bug free all it does is mathematically prove your code does that one specific thing correctly I'm hoping as AI takes off do doing a lot of this will become much easier and I guess we'll have to see but for now hopefully you learned at least the basics of symbolic execution if you'd like to learn more leave a comment in the description if you want to see more videos about form of verification let me know but the takeaway from this is that you should become a stateful fuzzing wizard thanks all for watching be absolutely sure to go watch the interview with Troy and Joselyn links in the description and we'll see you next time [Music] now for those of you who are looking to become Security Professionals smart contract security Wizards there are a ton of resources you should actually check out I've left a link of course in the GitHub associated with this course to this comprehensive list of known attack vectors and common anti- patterns it's got a ton of different solidity attack vectors that you should 100% know about additionally if you want to learn more on doing security there's a phenomenal game by a developer named tincho called Dam vulnerable defi which is a way to learn offensive security of defi smart contracts in ethereum and they've got these amazing games that you can check out and play to learn security ether not is another game that is absolutely phenomenal that will help you to learn and understand solidity and smart contract vulnerabilities for those of you who are looking to become Auditors definitely be sure to check out solid it which is this amazing tool for you to check out audit reports from the top smart contract Security Professionals in the entire industry of course be sure to check us out at cyphon we do smart contract security and auditing as well if you are building a protocol yourself definitely be sure to check us out for your next project for your next protocol for any and all of you absolutely subscribe to web3 education. deev we have some amazing surprises coming for you in the next couple of months and I don't want you to miss it there's going to be some awesome opportunities for you to participate learn and grow in top security so be sure to put your email in here and this is really just the tip of the iceberg there's so much more to go when it comes to security we are working on more Security based education as well so stay tuned for that but prerequisite for the security course is this monster Foundry course anyway so you have already taken the first step to becoming a Smart contri Security badass as well but all right guess what that's it for the security lesson congratulations I and the web3 community as a whole want to congratulate you for completing this absolutely monstrosity of a tutorial you have done an amazing job to get this far and to watch me talking to you right now and if you haven't finished the course go back and finish it for coming here we have learned so much on this journey and I can say from the bottom of my soul that I am so glad to have you in the web3 space smart contract space the blockchain space the cryptocurrency space we are so excited that you're here I'm really looking forward to seeing you in the web 3 in the blockchain community now a lot of people ask well where do I go now I have all this new found knowledge I'm armed with the intelligence of the web 3 developer space well I've left some links in the GitHub repository to lend you to those next steps but the biggest thing that you can do for yourself right now is go take what you've learned and apply it somewhere this is going to be probably the most thorough course you will ever go through in this space and you can go tutorial to tutorial and boot camp to boot camp all you want but at some point you have to make that leap and you have to dive in and that's where the majority of the growth is going to be anyways so if you're here wondering where to go next go join a hackathon go start jumping onto issues on GitHub repos go start applying for Grants go start applying for jobs and say I took Patrick's massive course here's my GitHub repo work on a personal Project work on somebody else's project take this knowledge and apply it the challenges that you'll run into and the challenges that you'll face really trying to do something without me handholding you is where you're going to learn 10 times as much as what you've learned here I've walked you as deep down this Rabbit Hole as I can take you now it's up to you to go out and do something with it so thank you everybody who helped me create this course thank you for taking this course and I so excited to see you in the community and see what you build and see what we can create with this technology