Main

Learn Blockchain, Solidity, and Full Stack Web3 Development with JavaScript – 32-Hour Course

This course will give you a full introduction into all of the core concepts related to blockchain, smart contracts, Solidity, ERC20s, full-stack Web3 dapps, decentralized finance (DeFi), JavaScript, TypeScript, Chainlink, Ethereum, upgradable smart contracts, DAOs, the graph, moralis, aave, IPFS, and more. Follow along with the videos and you'll be a blockchain wizard in no time! 💻 Code, resources, and support forum: https://github.com/smartcontractkit/full-blockchain-solidity-course-js Please reference the repo for anything you need and feel free to leave issues and participate in the discussions. ⭐️ Course Contents ⭐ ⌨️ (00:00:00) Lesson 0: Welcome To Blockchain ⌨️ (00:09:05) Lesson 1: Blockchain Basics ⌨️ (02:01:16) Lesson 2: Welcome to Remix! Simple Storage ⌨️ (03:05:34) Lesson 3: Remix Storage Factory ⌨️ (03:31:55) Lesson 4: Remix Fund Me ⌨️ (05:30:42) Lesson 5: Ethers.js Simple Storage ⌨️ (08:20:17) Lesson 6: Hardhat Simple Storage ⌨️ (10:00:48) Lesson 7: Hardhat Fund Me ⌨️ (12:32:57) Lesson 8: HTML / Javascript Fund Me (Full Stack / Front End) ⌨️ (13:41:02) Lesson 9: Hardhat Smart Contract Lottery ⌨️ (16:34:07) Lesson 10: NextJS Smart Contract Lottery (Full Stack / Front End) ⌨️ (18:51:36) Lesson 11: Hardhat Starter Kit ⌨️ (18:59:24) Lesson 12: Hardhat ERC20s ⌨️ (19:16:13) Lesson 13: Hardhat DeFi & Aave ⌨️ (20:28:51) Lesson 14: Hardhat NFTs ⌨️ (23:37:03) Lesson 15: NextJS NFT Marketplace (Full Stack / Front End) ⌨️ (28:53:11) Lesson 16: Hardhat Upgrades ⌨️ (29:45:24) Lesson 17: Hardhat DAOs ⌨️ (31:28:32) Lesson 18: Security & Auditing ✏️ Course developed by Patrick Collins. Check out his YouTube channel: https://www.youtube.com/c/patrickcollins Follow Patrick! 🐦 Twitter: https://twitter.com/PatrickAlphaC 📺 YouTube: https://www.youtube.com/c/PatrickCollins ✍️ Medium: https://medium.com/@patrick.collins_58673 💻 GitHub: https://github.com/PatrickAlphaC 🏢 LinkedIn: https://www.linkedin.com/in/patrickalphac/ 🎉 Special thanks to Sjors Ottjes. His amazing project, https://subtitletools.com, helped make the subtitles possible. 🎉 Thanks to our Champion and Sponsor supporters: 👾 Raymond Odero 👾 Agustín Kussrow 👾 aldo ferretti 👾 Otis Morgan 👾 DeezMaster -- Learn to code for free and get a developer job: https://www.freecodecamp.org Read hundreds of articles on programming: https://freecodecamp.org/news

freeCodeCamp.org

1 year ago

If you're interested in learning about blockchain, this is the course for you. Patrick Collins is a veteran software engineer and longtime finance industry developer. Be sure to leave a comment with something you learned from this course. Welcome to the ultimate solidity smart contract and blockchain Developer course, JavaScript addition, we recently did a version of this video in Python that has over 2 million views right now making it the most watched smart contract tutorial on the planet. We'
ve learned a ton from doing that first course. And if you love the Python language, definitely be sure to check that one out. We've taken all the learnings we've got from making that first course, wrapped it up and put it into this JavaScript video for you. If you're looking to get started in web three blockchain smart contracts or any of these terms, this is the course for you. And it's for anybody and everybody, no matter your experience level in programming or in blockchain. Ideally, you know
, a little bit of JavaScript before starting this. But if you don't, no worries, we will help you along the way. And in case you do want to learn a little bit of JavaScript before starting here, there are some fantastic courses on Free Code Camp to learn more, but you absolutely don't have to. And really, any experience with any object oriented programming language will work, right. So if you're brand new to coding, or if you're brand new to blockchain, this is exactly where you should be. And i
f you already know a lot about blockchain or coding, this course will give you even more deep fundamentals on the space. So welcome to the edge of the rabbit hole. So for those of you who don't know, my name is Patrick Collins. I'm a smart contract engineer, developer advocate on the chain link protocol. And I live in breed smart contracts. I also make YouTube videos on my own channel, medium Twitter threads and more. teaching people about smart contracts about coding and about this new technolo
gy. I love helping developers learn, grow and learn about this new Advent. That's blockchain and smart contracts. And I'll be taking you on your journey to becoming a blockchain expert and Wizard of the smart contract developing world. And even if you don't want to become a developer, the first section our blockchain basics, will give you a lot of fundamental knowledge about how blockchain and smart contracts, even work. I am so excited for you to be here. And I hope you enjoy the journey. This
is a data dump, passion educational project of everything I've learned working in this space. And I am 100% certain that if you follow along, you'll come out the other side of this, armed with the knowledge to be a positive force in this incredible industry, solidity and smart contract developers are massively in demand with an average salary of being around $145,000 a year, there is massive economic opportunity from learning this course. And this technology has the ability to revolutionize ever
ything that we interact with, and you can be one of the pioneers ushering in this new age. In our courses. We already have a track record of giving people these educational needs and sending them into their careers in the blockchain and smart contract space. And we are going to give you all of the cutting edge tools and how to use them including working with things like D phi NF TS Dows, ERC 20s upgradable, smart contracts and more. We're going to teach you the skills necessary to build defy app
lications like Ave synthetics and compound, billion dollar decentralized applications, or massively successful NFT projects like crypto punks, or board apes. Dow is like maker Dow or developer, Dow and any of the amazing things you've seen in the cryptocurrency world. In learning these skills, you will have all these economic opportunities at your fingertips and the ability to be a pioneer in completely changing the way we interact with each other. In a fundamental way. Building decentralized sm
art contract applications is building a world that's more accountable a world with unbreakable promises, a faster, more efficient, financially free world, a collaborative community, combining the prowess of philosophy and technology into a new system. We'll learn more about the purpose and the value of smart contracts and decentralized applications in lesson one of this course, and why they're so exciting. Finish this course. And you'll be ready. So again, I want to give a major thank you and a
major kudos to you because you've taken the first step to enter this realm. So welcome to Web three. Welcome to the blockchain. Welcome to smart contracts. And I'll see you at the bottom of the rabbit hole. So let's jump into some best practices for this course so that you can learn most effectively and learn with this course as best you can. You do not want to skip this part. It'll help you solve 80% of your issue. Now, while going through this course be 100% certain to follow along with a GitH
ub repository associated with this course we have a link in the description of this video for you to absolutely click on follow along have open in a tab as you're doing this because it has all the code Sam polls, timestamps a community to interact with and more, it is going to be your Bible for watching this course. And yes, we have a Discussions tab. This Discussions tab is a place where you can ask questions, engage with other developers who are going through this course as well. Get some help
, and etc. Be sure to say hello and meet other like minded individuals like yourselves. Now, blockchain and smart contracts move really quickly. And things are constantly being updated. So to make sure you're always up to date with the latest, when I open up some documentation, try to open up the documentation for yourself as well. And maybe even have the code sample next to you. And as you're writing code, be sure to refer back to make sure that you are keeping pace, and then you have the most
up to date samples, sometimes technology might change, and there might be a way to do something a little bit better. So we have this file called chronological updates, be sure that this is the first place to check when you run into an issue to see if maybe something was updated that you missed, it'll be chronologically ordered. So it's easier to find updates. Basically, this is to say, always refer back to the GitHub repo first. And if you do to find a mistake, or something isn't working the way
you expected, jump into the conversation, leave a discussion, leave an issue, ask questions here, take breaks, I cannot tell you how many people tried rushing through our entire first course in one setting and didn't retain as much information, your brain remembers information much better if you take breaks. So every 25 minutes or half an hour, maybe take a five minute walk. And then every two hours take a much longer break. And if you really want to make sure something drills in, try to go bac
k and reflect on what you did for the lesson prior before continuing to the next lesson. And at the same time, though, learn at your own speed. There is no right speed for this course. If it takes you a day, a week, a month or even a year, it doesn't matter. Learn at the pace that's right for you, you can change the speed at which I talked using the little gear icon in the YouTube video. If I'm talking way too fast for you, you can slow me down. And at the same time, if I'm talking too slow, you
can speed me up, you also don't even have to go in order. You can bounce around topic to topic, if you don't want to learn full stack, you can skip the full stack stuff. If you don't want to learn coding, we can skip the coding stuff. If you only want to go to the advanced stuff, go to the advanced stuff. You are highly encouraged to pause, come back and ask questions. The blockchain and smart contract world is incredibly collaborative. So be sure to use tools like the discussions tab of our Gi
tHub repository, asking questions on Stack Overflow and Aetherium Stack Exchange and tagging relative technologies, making issues on different GitHub repositories that you're working with jumping into discord, Reddit, Twitter, and any other place that these communities and technologies are congregating. And the reason I'm putting so much emphasis on these community aspects is that becoming a solidity and blockchain engineer is so much more than just the solidity part. Being comfortable with all
the tools in this space, including the ones to get help and to give help are essential to being successful here. Networking is massive, and it makes it a ton of fun. As you continue your journey and you get more advanced and you're looking for places to meet other developers. Hackathons are one of the best places to connect with other engineers, the chainlink hackathons eath, global hackathons, and Dev folio hackathons are three great hackathon suites to connect. And no matter where you are in y
our journey, they're great places to flex what you've learned. Alright, so those are some of the best practices for this course. You're standing at the edge of the rabbit hole, looking down, peering into the world of web three and smart contracts and blockchain. If you're like me want to jump in, you want to keep going further. Let's begin our journey into the world of smart contracts. And it all starts with the blockchain basics. Now, I know you're excited to get coding. But before we jump in,
we want to learn some of the fundamentals of blockchains and smart contracts. Understanding these ideologies and these basics are so important, because it'll dictate how you architect your decentralized applications, learning the basics of blockchain and solidity is critical. But if you already know the basics of a blockchain, feel free to jump into lesson two. Now, since you're here, you've probably heard of Bitcoin before. Bitcoin was one of the first protocols to use this revolutionary techno
logy called blockchain. The Bitcoin white paper was created by the pseudo anonymous Satoshi Nakamoto, and outlined how Bitcoin can make peer to peer transactions. In a decentralized network. This network was powered by cryptography, decent Tality, and allowed people to engage in censorship resistant finance, in a decentralized manner due to its features, 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 g
old, 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 A paper we've linked to the white paper in the GitHub repo associated with this course. Now, this was an insane breakthrough in a little bit, we're going to learn exactly how this is all possible and how this actua
lly 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 Vitalik Buterin, released a white paper for a new protocol named Aetherium, which use this same blockchain infrastructure with an additional feature. And in 2015, him and a number of other co founders released the project Aetherium, where people could not only make decentralized transactions, but decentr
alized 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 instruc
tions 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 Aetherium. And it's the 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 Etherium protocol and the Bitcoin protoco
l. It's these smart contracts. Now, technically, bitcoin does have smart contracts, but they're intentionally Turing 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 Aetherium, developers viewed Aetherium as both a store of value and a utility to facilitate these decentralized agreements. Now, the 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 Oracle's come into play. Oracle's 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, you're on chain logic will be decentralized, but you also need your off chain data and computation be decentralized, combining this on chain decentralized logic. With this off chain, 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 hybr
id smart contract or interact with hybrid smart contracts. To some extent, this is where the protocol chaining 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 end, while giving them the feature richness that we need for our agreements. chainlink allows for us to get data to upkeeps, get random numbers or really customize our smart contracts in any meaningfu
l 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 off chain component. Now since the theorems release, a number of different block chains or smart contract platforms have come to light such as avalanche polygon, Phantom ha
rmony, 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 learned 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 a theory and funding mentals will give you the skills that you need to switch chains very easily with literally one line of code. So don't worry about learning a speci
fic 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 the Etherium 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 they'll say smart contract platform, sometimes the
y'll say blockchain, they kind of mean the same thing. Obviously, blockchains could mean store of value and smart contract platform, but you get the idea. Similarly, chainlink 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. chainlink is also blockchain agnostic. So to work on Aetherium, avalanche, Polygon Solana Terra, or really any other blockchain out there. Now, throughout this course, you'll hear the term DA
P 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 three a lot in this video. And in the indust
ry, web three is the idea that blockchain and smart contracts are the next iteration of the web web one being this permissionless open source world with static content, web two 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 three comes back to the permissionless web. But once again, with dynamic content, and instead of centralized servers, running your logic, decentralized network
s, run the logic creating these censorship resistant agreements, that the smart contracts enable is also generally accompanied by the idea that the users own the protocols that they work with, and it's an ownership economy. You'll see what I mean later in this course. And we've talked a lot about the history and about the high level of these protocols and of the smart contracts and what they can do. But what do these smart contracts really mean? What is it when I say trust, minimize agreements o
r unbreakable promises? What is the real value add of these smart contracts? Before we look under the hood, 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? Have you taken this 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 Mark contracts, Blockchain web
three 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 that give rise to unbreakable promises. Yes, you heard that right. Unbreakable agreements and promises. Additionally, they give rise to speed, efficiency and tran
sparency, 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 re landscape markets and agreements as we know them. Unfortunately, you've probably only been bombarded with people screaming about empties and money. Now, some of the memes are fun, but let's forget the bullet and get down to the essence of the space. If you're already in web three. Th
is 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 in there all these things. But outside of all that the purpose of blockchains relates to the age old 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 c
ontract. Your chair was the result of an agreement to buy and sell lumber to assemble and sell the chair to a real tailor 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 they generate it's agreements between them and engineers who built turbines to generate the electricity with insurance you agree t
o 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 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 mon
ey, when you put money in the bank, they promise 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 Pinkie sw
ear 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 you if you buy our MC food and McNuggets, we'll give you a fair chance of winning this money, we 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 were 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 could think about it is that th
at's $24 million that they essentially stole from you and I now if this system was deployed on a blockchain was 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 please have it when I come back. Immediately. You might get that worrying feeling in your chest, something might go wrong. 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? Once all the time. Can I trust this used car salesperson to give me a good car? Can I trust this tag that says machine wa
shable? Or will it make my shirt shrink? Will my insurance provider break their promise of covering my medical bills want to get hit by a bus? I'm Patrick promises he'll go on a hike with me. Well, he actually I actually will. But the issue with our current agreements and contracts is we have to trust the people. We're 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 shit off the shelves and with my girlfriend, I promised to go on a hike. But I need hikes. Where else is has 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 promised 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 t
imes that they didn't have the money they're just last year Robin Hood painted this amazing picture. On user 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 the finance side, but not this asset. This asset, this asset or this asset, the 2008 financial crisis remember that shady deals behind closed doors combined with lies about financial product brought the world to its economic knees, how are you? hyper
inflation in Zimbabwe hyperinflation in Brazil, fair enough. US history is a relentless lesson of trustworthy entities being notorious promised breakers and 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 in 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 very helpful step forward. But these systems often breaks 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 needed the money for is longer. 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 gonna 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. Real basics of it is that the code is executed by decentralized collective lik
e 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, We're not going to do that anymore. In smart contracts and web three in blockchain, you no longer can do that. Typically, these smart contracts are on a decentralized blockchain,
and used in combination with a decentralized Oracle network to get the real world assets and information. And if 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, then you're not interested in getting into the nitty gritty, 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 i
t every single day whenever you log on to 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 VRF 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,000,020 $4 million just by fixing the issue of trust. How does this fix Robin H
ood? 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 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 uniswap. You can swap ERC 20 tokens, which are kind of the equivalent of stocks, but some are som
e are, 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 an automated solvency checks, you can build a bank like smart contract that has insolvency checks bu
ilt in that make it impossible to get there and solve it means brokers 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 b
ased 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 map and say, oh, okay, one plus one equals two. This is what this agreement is going to do for me every single time gu
aranteed, because it's a decentralized autonomous agent has no incentive to be evil, and everything is transparent and out in the open of a big company. And if it was better for me for one plus one to equal three, maybe I would go behind some closed doors and flood some numbers and come back and be like, hey, one plus one equals three 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 singl
e centralized entity that they're going to do the right thing for you, versus a decentralized untampered double collective, which one you're gonna 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 relandscaping entire markets and continue to do so the traditional financial world is already getting its lunch eaten by defy or decentralized finance. There's already over $20
0 billion of people's money in these protocols to help have a more fair, more accountable, more transparent financial system. This defy movement is one of the main reasons I got into this space because we desperately need to move away from where we are right now. And and 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 bloc
kchain because of all the innovations and because of all the advantages that it has as we grow and as we get better as we get closer to this vision of having 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 gotta be honest with you guys. blockchains and smart contracts and cryp
tocurrencies can actually do more than just trust, minimize agreements. 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 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. Even in just this introduction part, we've learned a ton. So let's do a quick summary of what we've l
earned 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. Aetherium and other smart contract platforms take this blockchain technology one step further, enabling people to make smart contracts and decentralized trust minimized agreements, the smart contracts and decentralized applicat
ions 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 on chain logic with our off chain, 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 co
ntracts have. Now these digital currencies like Aetherium, and Bitcoin have value. Even without the smart contract part, having a censorship resistant, decentralized store of value is naturally powerful in its own right, we have some links in the GitHub repository that will 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 agre
ements, 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 1000s of node operators running the same software running these algorithms running these smart contracts that make the netw
ork 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 the 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 will be able to see and just not use, everybody has perfect information and has to play by the same rules. Now additionally, thi
s 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 l
ong, 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, 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 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 100 nodes or a few 1000 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 in your assets is your private key. Which is basically your password for all of this. And as we've discussed in the video, the smart contracts remove this counterparty risk, remove this centralized intermediary, remove these trust gateways that we have to do in web two. 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 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 piece, these unbreakable promises, make interactions so much be
tter. In a purely web two 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 did they generate 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, d phi d phi 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, you 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 at the time of recording. defi has around $200 billion in assets under management and is quickly
growing. If you're really excited about defy we have a ton of defy 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 engagement is much easier. The rules are black and white. And you can see everything directl
y on chain voting and governance technologies completely decentralized in 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 incoming lessons. So be sure to watch those NF T's Stanford non fungible tokens and can really be kind of described as digital art or just a unique asset, they can do so muc
h more, but we'll keep it high level for now. Projects like board apes and crypto 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 NF T's 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'd be the one to pion
eer the next industry or the next billion dollar idea you've learned so much already. But now that we've learned a lot of this high level 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 Aetherium website aetherium.org We are going to make a transaction
on a test Aetherium blockchain I'll explain what that means in a little bit. This is going to be our first transaction that's made on the blockchain. Now again, this process that we're going to follow is going to work the exact same with polygon, avalanche Phantom and all these other EVM compatible blockchains. I'll explain what that means in a bit too. For now, just follow along and have fun in order to make a transaction on any of these blockchains. The first thing that we need to do is we nee
d to set up a wallet. So I'm gonna go ahead and go to meta mask because it's one of the most popular wallets and one of the easiest to Use, we're going to go ahead and download it. I'm using the brave browser, but it works for Chrome, Firefox or really any other browsers. And it's just going to be a little extension in the top right hand of your browser. This way, we can really easily see it any times what we have in our wallet, will still are all of our Aetherium based currencies. So I'm gonna
go ahead and install meta mask for brave, add to brave, add extension. And now we can go ahead and get started with working with Brave, this is the first step you absolutely need to take when starting your journey and one of the easiest steps to take. So we're gonna go ahead and get started. And we're going to create a brand new wallet. So we're gonna go ahead and hit create wallet. If you already have a wallet, you can actually import it via I have a seed phrase, and we'll talk about the seed p
hrase or secret phrase in a little bit. So let's go ahead and create a new wallet. And sure, we'll agree to help out Metamask now we will create our password make sure that this is really secure. For the purpose of this demo, my passwords are just gonna be password. But please don't have that be your password. You may also get a video like this teaching you about your secret recovery phrase. This is the same thing as your pneumonic. But see your recovery phrase is a lot more clear as to what it
is. And again, to give us a ton of different tips on how to actually store it and keep it safe. The main takeaway from this is never shared this absolutely never shared this. So we're going to go ahead and click reveal secret words. I'm showing you guys here because this is just a demo and I don't really care. However, if you show this secret phrase to anybody else, they will have access to all the funds in your application. So everything that we're going to do in this tutorial, we're going to u
se fake money, we're going to use not real money, so it doesn't matter. Now for the purposes of testing and developing, I always recommend using a completely separate meta mask, a completely separate Wallet. So for going throughout this entire course, if you already have a wallet, or if you already have a meta mask, please just set up a new one, create a new profile, create a new meta mask, and this will be your wallet that you use for the duration of this course. However, if you're going to act
ually put money in here, you absolutely need to have this written down. Because if you lose access to this, and all your private keys, which we'll talk about in a little bit, you will lose access to your wallet, and you will lose access to all your funds. So they give some tips like store this phrase and a password manager like one password, write this phrase down on a piece of paper, put it in a secure location, memorize it, whatever you want to do, just make sure you have this backed up somewh
ere, I'm just gonna go ahead and hit download this for now, it's not best practice to save to your computer, it is much better to use a password manager or write it down on a piece of paper or something. So we're gonna go ahead and hit next. And it's going to ask us to verify that we actually have it written down. And we're gonna go ahead and hit confirm, and great and gives us a couple other tips. Remember, definitely take these tips very seriously, especially if you're gonna use this for real
money. Like I said, For this demo, we're just going to use test money. So it's not as big of a deal. But if you put real money in, you absolutely need to backup this seed phrase or secret phrase or we're going to refer to it as our pneumonic phrase. Awesome. Now we can see the interface of our wallet here full screen. And depending on your browser, you can actually come up and pin it to your browser so that you can just click it up in the top right, and it'll drop down and you can see the same i
nterface here our pneumonic phrase that secret phrase, those that secret 12 words that they gave us have given us access to a new account, the address of our account is located right here. In fact, if we click it and copy it to our clipboard, and go to a tool called a block explorer called ether scan, we can actually paste our address in here and see details about our account. Ether scan, like I said, is what's known as a block Explorer. And it's a way to view different addresses transactions an
d other happenings that happen with a blockchain. If we look at this address that we just created on ether scan for Etherium main net, we can see no transactions have happened. There's really no analytics, there's no comments, there's no balance, there's no value, because it's a brand new wallet, and this address that we just punched into ether scan represents our unique address our unique wallet only identifiable for us. We'll talk about ether scan a little bit more in a bit because it's a tool
that we're going to use quite often in wallets like meta mask, you can actually even click right here and create even more accounts. So let's go ahead and create a new account. We'll call this account two. As you can see, this one has a different address. So if we click this one, we go back to ether scan. We paste the address in here. We hit Enter. We can see another address again that's uniquely identifiable to us, right here. It is zero balance, no value, no transactions now If we go back to
our Metamask, and we click the little button, we can see we have two different accounts in here, it's the same. If we hit the extension in the top right, click the button, we have two different accounts. The 12 word secret recovery phrase allows us to create multiple accounts, all with the same secret recovery phrase. So that secret recovery phrase will give us access to both account one and account two and any other accounts that we create by hitting this Create Account button, because it gives
you access to all the accounts in your meta mask. Now, these addresses of both of our accounts are the public unique identifiers, but they also have a private unique identifier only identifiable to us. Similar to the pneumonic, these are private identifiers we never want to share and we never want to give out their private This is known as your accounts private key. So the mnemonic will give you access over many of these accounts, the private key will give you access to just one of these accoun
ts, we can see it by hitting these little three dots, going to account details and export private key, you'll just have to punch in your password here. And you'll be able to see your private key. This is going to be your private key for your account, you can think of your private key as a password for your account that lets you create transactions. Now the reason that I'm showing mine on screen is because I'm not going to put any real money in here. And this is just going to be a burner account
for this tutorial. And I highly recommend once again, you use a burner account, you use accounts that you never put any real money into. And along the way, I'll show you how to make sure that you don't do that. But normally, it's not a good idea to show or share your private keys or your secret recovery phrase, if somebody gets a hold of this private key, they will have access to my account one. However, they won't have access to my account to if they get a hold of my 12 word recovery phrase or
pneumonic they'll have access to both accounts. And this is why when people say keep your private keys safe, your keys, your Bitcoin, your keys, your Aetherium, they're talking about both your mnemonics or your secret recovery phrases. And your private keys keep those private, your public addresses are totally public. And anybody can view your accounts on something like ether scan, or any other explore. And it's totally okay for people to share their public addresses. If you lose your private ke
y, you lose access to one of your accounts. If you lose your mnemonic, you could potentially lose access to all your accounts. Basically, what I'm trying to say is back these up and keep them in safe places for this course it's okay if you lose one, since we're not putting any real money in them. But in the real world, be sure to do this. And great. Those are some of the main security considerations here. Now, if you look up in the top right, right next to that account button that we've been cli
cking, you also see this thing saying Etherium main net, this is our networks tab. And if we click it, we can see a list of all the different networks that we currently have access to a Etherium main net is the main network of Aetherium. And this is where real money is spent and used for transactions. For this course, we're not going to be working with the Etherium main net, we're instead going to be working with something called a test net. Since we're engineers, oftentimes, we're going to want
to test and see what our code is actually going to do and how to interact with it. We're going to use a combination of local networks and test networks to actually do this to actually test our smart contracts. We're mainly going to use local networks. But we'll get to that in a little bit to see some of the test networks that come default with meta mask, we hit show slash hide test networks, this will bring us into the settings page. And we just hit select this to show test networks in the list
. And we just hit on Now if we scroll back up, we'll close out of the settings, we hit the network's tab again. Now we can see all of these other networks here like ropsten, Koven, Rinkeby, and Garelli. These test networks or networks that resemble Aetherium, or polygon, or Avalanche or phantom or any of these other blockchains. And we can actually switch our accounts to one of these other test networks. Let's click rink B, for example, we can see that on the Rinkeby test network. We also have z
ero Aetherium we have no money or nothing in here, we have a blank Rinkeby wallet. These test nets work nearly identical to how Aetherium main networks except for they run with not real money. They run with fake money as a way for us to learn and interact and see how these different smart contracts actually work together at the time of filming. rink B is one of the most popular test networks along with COVID. So we're going to work a lot with Rigby In this tutorial, however, be absolutely sure t
o check our GitHub repository to make sure that you're always up to date with the best test network for following along with the tutorial here since their test networks people are running them out of the goodness of their hearts. And sometimes the best ones actually change so, so be sure to follow along with the GitHub repository. We might also use COVID From time to time or maybe even Grilli. So we're going to show you how to use a couple of these different test nets. In fact, if we go to the G
itHub repo associated with this course, we can see recommended test net is indeed currently ranking. So that's what we're going to work with should this change, you should be able to follow along with another test. And we'll leave notes as to how to continue. Now what we can do actually is we can go to Rigby ether scan, we can go to, you can look up Rinku ether scan, and it looks like it's the first thing that shows up Rinkeby dot ether scan.io, we can punch in this same address, copy and paste
it. And we can see some of the details of this address on the Rinkeby ether scan. Like I said, right now, it's totally blank. This networks interface later on is also how we're going to be able to work with polygon, avalanche, etc, we'll just have to add networks. But we'll get to that in a bit. And just to reiterate, test nets are free and for testing our smart contracts and main net networks cost money and are considered live. Now I also do want to put a caveat here that we do want to keep in
mind that these test nets are being run at the goodness of people's hearts. So we don't want to abuse them, we want to use them to learn and then move on. So try not to send a billion transactions on one of these test nets. In fact, what we're going to do right now is we're going to send a transaction on the Rinkeby test net. And this will show us exactly what it would look like on a main network. In order for us to simulate one of these transactions, we're going to go to what's called a faucet.
And if you go to the GitHub repository associated with this course, right underneath the recommended test net is going to be a test net faucets, which is going to show us where the most up to date faucet location is for us getting test net Aetherium. So here we are at faucets dot chain dot link, which again is the recommended faucet, and what we can do is we can actually put our wallet address in and get some test net link or test net Aetherium. Now what we are gonna have to do is we are gonna
have to connect our wallet to the Rinkeby network. So we're going to come down, we're going to switch from COVID to Etherium. Rigby, and then we're going to make sure our meta mask is on the Rinkeby test network here. Once both of those are set up, we're gonna go ahead and hit Connect wallet. And we're going to choose meta mask. Once we do that, our meta mask is actually going to pop up and say would you like to connect to this website, connecting to a website is how we give these websites in in
terface to interact with our wallets and interact with our meta masks. Don't worry, we're not sending any transactions like this, we'll get to that in a bit. So we just we can pick an account we want to connect. Let's choose our account one, we'll hit Next. And then we'll go ahead and connect. Now that we're connected, we can actually see our account connected up here. And that little warning is now gone. And our wallet address is automatically placed into here, we're going to make our first tes
t transaction. And for now, we don't need test link. So we're going to leave that off. But later on, we're going to come back and get that test link. For now we're just going to need 0.1 test Aetherium. So let's go ahead and complete the security by choosing the traffic lights. And we're going to hit Send Request. What this is going to do is we're asking this faucet to send us 0.1 test Aetherium test net faucets are ways for us to get money into our wallets on a test net. And this is why this te
st and Aetherium isn't worth any actual money. Since we can get it for free. These don't exist on Main net, you can't get real Aetherium or real money for free on a main network. So we're on Rinkeby we're getting fake Rinckey Aetherium. And we're gonna go ahead and hit send request. Once we hit Send Request, this transaction hash is going to pop up here, and it says transactions have been initiated waiting for confirmation. This means that some other wallet is actually going to send us 0.1 test
eath. And this is the transaction that it's doing to do that now we just have to wait for our transaction to finish verifying and finish going through. Now if this doesn't work right away, I would recommend Wait a minute and then just try it again. But what we can do is we can click this transaction hash. If that transaction doesn't show up, we can also just close this. And we can copy our address here. And actually we already see 0.1 eath in our wallets here. But we can go back over to Rinkeby
ether scan, paste our address and and we can see that we now have 0.1 ether as a balance. We can also see that we have a transaction with all this information going into our wallet. That's what this green is for. If you click that transaction link, you'd get something like this, but If you didn't, don't worry, because on the ether scan, if you click the transaction hash in the transaction list, you can also see all the details like that. So now in our meta mask, we have 0.1 eath. Again, this is
fake Aetherium. And we have a transaction associated with our wallet now, which is awesome. Again, though, if we switch networks, if we switch networks back to Etherium main net, you can see that we have nothing on a theory main net. Or if we go to ropsten, we also have nothing, we only have this 0.1 eath. On the Rinkeby test network, if you want to practice working with another test net, and the faucet that we're using, has multiple test nets. Let's go ahead and try it during this section right
now is completely optional, you can watch or you can follow along. But for example, I can see in my wallet that we already have COVID supported, so maybe I'll switch to COVID. Maybe we'll switch to COVID. In the drop down here, we'll remove test 10 Link, because we only need test eath. We'll hit I'm not a robot, and we'll send request and the same things will pop up this time, this is going to be for the COVID test net. And once our transaction finishes going through. Now, same thing on COVID.
Here, like what we did with rink B, once our transaction finishes going through, we'll see 0.1 test eath on the COVID network, if you want to go ahead and try working with another one of the test nets. Like maybe, for example COVID recommend you go ahead and giving it a try. But it's completely optional. And I would always refer back to the GitHub repo to make sure you're working with the most up to date faucet and test net. And if we look back at ether scan, we can actually see more details on
what actually just took place. What actually just happened, how did our Metamask get a balance of 0.1 eath. All of a sudden? Well, if we looked down in the transaction section, we can see that there's a transaction here, some address sent us 0.1 ether. And if we click the transaction hash, we can see more details about what actually went down with this transaction. Now understanding what's going on in this transaction is essential to learning and being a smart contract developer or just engaging
with the ecosystem. So let's learn the first bit at the top is this transaction hash. This is a unique identifier for this blockchain or this test net that identifies this exact transaction. This transaction hash identifies sending 0.1 eath to our address, we can see that the status of this transaction was successful, it didn't break. In any case, we can see the block number that this transaction was included in and we'll get to blocks in a little bit, we can see the timestamp which of course i
s when this transaction occurred, we can see which account it was from which if we go ahead and open in a new tab, we can see that this is the account that this transaction came from. And it's got 3 million ether. Of course, this is fake Rinckey ether. So it doesn't really matter, we can all see who it was to, which again, is just us. This is our wallet address 0x 106 X blah, blah, blah, cero x 1066, blah, blah, blah, right, the value of this transaction, of course, is 0.1 ether. Now what's all
this that we see as the value so obviously, the value is 0.1, because that's a mode which we sent. But we see this transaction fee. In this gas price, we hover over the tooltip, we can see if you zoom in on your ether scan, you see amount paid to the miner for processing the transaction. And we see a gas price which is cost per unit of gas specified for the transaction and ether and gray. The higher the gas price, the higher the chance of getting included in the block. Now if we scroll down even
more, and we click See more, we can also see a ton of other information here. For now we're just going to click to see less and just focus on these two. I'll explain all of these in a later session. Let's talk about just the concept of transaction fees and gas for a second. Remember how I said the blockchain is run by all these different nodes will all those different nodes are running this blockchain because they actually get paid for all the transactions that happen on these blockchains whene
ver you make a transaction, there's a node or a miner or or a validator somebody running the blockchain software is gonna get paid a tiny bit of Aetherium or polygon or whatever blockchain that you're running on, they're gonna get paid a tiny bit of that native blockchain currency. This payment is obviously to incentivize people to continue to run nodes and they calculate how much you pay and how much the node operators get paid based off of how much gas you use. So there's this concept of gas.
Gas is a unit of computational measure. The more computation a transaction uses, the more gas you'd have to pay for. For example, we do hit click More just really quickly. We can see this section say A gas limit and gas usage by transaction, there was a limit of 60,000 units of gas on this transaction, and 21,000 or actually use. So this transaction use 21 units of gas. Now for very simple things like sending ether, the units of gas are usually pretty cheap. But maybe for more complex things lik
e like minting NFT, depositing to some defy contract, etc, maybe those will cost more gas because they'll be more computationally expensive. And this is a little confusing right now, don't worry too much about it. But just know that we use 21,000 gas here. And if we pull out the calculator 21,000 gas times this gas price right here, times the gas price, we get the exact same as we see for the transaction fee. So gas price, times how much gas you used, is the transaction fee. So whoever sent us t
his 0.1 ether, also paid 0.0000525, etc Rinkeby ether to make this transaction. Now, each blockchain has a different way of actually calculating how this gas stuff works. So that's basically going to be the high level of it. So we're going to focus just here for now there's a total transaction fee. And then there's obviously the gas price. After we cover how blockchain works, I'll explain what this burn stuff is these gas fees and all these other stuff. For now, just know that anytime you make a
transaction on chain, you have to pay a little bit of what I call transaction gas. So for example, if we go to our Metamask, we have two accounts right here, we have account one was 0.1, Rinckey eath, and account two was zero. Rigby. If I were to send 0.05 Rinckey eath. From this account to my other account, how much rinky eath Do you think I'd have left? Well, let's go ahead and try it, this will be the first transaction that you're actually creating that you are going to spend the gas for. So
if we go ahead and hit send, we'll hit transfer between my accounts. count two, we'll do 0.05. Next, we can see some information here about what's actually going on Metamask has some new advanced gas for UI and settings, we're also going to turn the song, so go ahead and click that enable enhanced gas UI, turn that on, and then go back. And again, this is going to be the experimental tab. But it could also just be in the General Settings tab. Depending on when you actually run this, we can see
a little notification here. Again, this depends on what version of Metamask we're using. And we get this little drop down that says Here are some of the different type of gas fees that you can actually pay. The reason that gas fees might change, as you can see here is that depending on how busy the blockchain is, you have to pay more gas. 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. That's a bit of an over
simplification of what's happening. But don't worry too much about it for now. Now, if we want to send the 0.05 ether to our second account, we can see this gas estimated section, which is saying it's estimating, we're going to pay 0.00004792 gas in addition to sending the 0.5 eath. So at the bottom, we have amount plus gas fee. And this is going to be the total amount that we're going to be spending on this transaction 0.05 is what we're sending. And we also have this gas piece. So we go ahead
and confirm, we now see we have a transaction pending in our Rigby ether scan. And if we click on it, we can even hit View on block Explorer. And a Rigby transaction hash will pop up and depending on when you click it, it might say indexing, this means that ether scan has received your transaction and is trying to place it. If you don't see anything here, it means that maybe the transaction hasn't gone through yet. Maybe you need to wait a little bit more. Or maybe you need to go back to the Git
Hub repo and pick the recommended testament and faucet. So you might have to wait a minute or so for this to actually finish indexing. After a minute or so we can see that this transaction has indeed passed. And we can see a lot of the same information that we saw on our last one, this time with 0.05 ether. And now if we look in our meta mask, we'll see we can see account one has 0.05 It's rounding up a little bit, we click on the big button, we can see it actually has 0.049953, etc. And our oth
er account account two does have exactly 0.05. This is because we spent a little bit of Aetherium on gas to send this transaction. And now with just this little bit of information, you know how to actually interact with applications that use the blockchain, how to send transactions and a lot of the non technical details. 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 Etherion protocol.
So if you don't want to learn how to code anything, you can go If you can start interacting with Aetherium and interact with protocols with just as much information. However, I know most of you guys are here to learn how to code. So let's look under the hood of Aetherium. And what is actually going on with these transactions, and what these gas and what 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 timestamp 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 walk through blockchain one on one, it is right on their site. So if you're looking for another explanation, definitely check out his video, it i
s absolutely fantastic. But the first thing that we really need to do in order to understand blockchain or just on really anything, and everything that's going on here working first really need to understand this Sha 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, the hashing algorithm used is Sha
256. Now Etherium actually uses this, this right here for its hashing algorithm, which isn't quite Sha 256, but as in kind of this SHA family. But it's really just another way to hash things. And the specific hash algorithm doesn't matter so much. So this example, you just shot up to six, but you can imagine it's the same as the Etherium. Hash, they're just going to 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 the 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 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 gonna be the same, 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 purposes, we can pretty much put any length in here. And you'll see to that every time I type in Patrick Collins, this hash is always gonna be this seven e five D, right? I'm gonna delete I'm gonna do Patrick Collins, again, you're 75 B is always this, this unique hash is always going to be unique, right, it
's always gonna be this fixed length string here. So now we can take this idea while putting this data in here, we can move on to 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 t
hese to get to get this hash, right, we're gonna put all three of these, we're gonna say all three of these are combined. Together, we're gonna put every all three of them into this hashing algorithm to figure it out. So if I type a bunch of stuff here, we can see that block one with nonce, you know, this nonce, 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 min
d button, it's actually gonna take some time, it's gonna think for a little bit. And we can see that the nonce here actually changed, right? The nonce is different from what it was before. And this hash now starts with four zeros. Okay, and then the back turn 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 the miners had to solve was they had to find a nonce,
or or a value in this nonce section that when hashed with at block number one with this data, it would start with four zeros. So the problem here the miners 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. 3456 Okay, five, well, that started with one zero, but it's not four. And they have to keep trying all these numbers until they ge
t 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 yet. Aetherium has a different problem for miners to solve A bitcoin is different problems from yourself, but this concept is going to be the same. So they have to take it, one block is going to be this, this, this concept is going to be all this data, it's going to be the block number. And it's going to be this nonce, right. And s
o this nonce is the solution 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, I do this again, hit mine. And the nonces changed, right? And went from one to 33,128. Because this is the nonce that allowed this hash to start with four zeros. And so that's what's happening. When blockchain miners are mining they're going through this process is very computationally intensive process of trying to find a nonce that fulfills
whatever the problem is. So that's really it, actually. So that's a block. 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 nut 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 blockchain 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 blocks, right, each one of these represents a different block, but we have an additional column here, we have additional variable here. So like before, you know, we have block nonce and data, right, we have blocked nonce data, we also have this thing called previous right, and so this is actually gonna be pointing to the previous hash of the last block. So for example, if we go to the last block in this blockchain, it says previous 008.
And if we look at the hash of block number four, is 00008. And then we look at its previous it's four zeros, B nine, we have four zeros, B, nine, 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 were the previous hash points to a hash that doesn't actually exist. Now,
as you can imagine, kind of the same as how this block worked, how the block nuts and dated all go through the hashing algorithm in the blockchain, the block nonce data, and previous hash all go through this hashing algorithm to figure out what the hashes okay? So if we go to over here, you know, for example, if I type in Patrick, obviously, this is now no longer valid, right? Because this nuns combined with the block the data in the previous hash, aren't going to solve our problem of having fou
r zeros at the at the start, right. So I'm gonna go and fix that. And that's, that's kind of an easy way 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 read, both of these are now invalid, right? Because the block hash with the nonce hash with the new data, which is my name, Patrick has 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 this previous block. And now it is wrong, and it is messed up and now, and now it's nuts with this previous hash is also wrong. Right? And this is where when we talk about blockchains, being immutable, this is exactly how it's immutable, right? Because I go back and I change anything, you know, if I've just typed a right here, the entire blockchain is now invalidated. Because none of these are going t
o have nonces 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 it was here, originally, we can go ahead and mine these, mine all these but as you can see, you know, this is going to start getting very computationally expensive, because I have to go redo basically the entire blockchain. And the farther and farther down the line you get, the harder and hard
er it becomes to, you know, rehash and redo all these different block chains 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 remind 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, the past will, okay, great. All I got to do is change the state of here. And then you know, mine, each one of these, yo
u 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 makes it incredibly powerful. So we're gonna go to the distributed tab here, which is also referred to as the decentralized tab here, and it's going to show us what a blockchain looks like in a decentralized manner. So we have this exact same initial setup here we have to Shoo
t a blockchain, we have our first blockchain, which is kind of exactly as the one from here. But we also have more than once we have peer, a peer beam, and PRC and when people are talking about Peer to Peer, peer to peer transactions through the talking, 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, or by looking at this end, hash here, right, or by looking at where we are 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 so this last hash is encompasses everything in here, right? And we can look, we can look at the hash of Piercey, which is four zeros, and then E four B, we can look at the latest hash appear B, which is four zeros, E for B, and then pure A, which is four zeros, E for b. So all of these peers, all of these nodes, all of these decentralized, you know these independent, all these independent users run
ning 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, the rest of their blockchain is invalidated. And they have to spend a lot of computational power to catch up to speed. So let's g
o ahead and humor it. Let's say that they did, they ended up catching up. 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 some that Peer 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
and hash at block number five. So pure A has this new hash. Now, there's a 09 BC. But pure B has a different hash 00, e for B, right? So who's right? Is it disappear a with their new stuff? Or is it pure B? Well, that's where the decentralized data comes in. Because then we can look at Piercey Piercey, also as E forby. So if you're being Piercey will say, Hey, you're a, you're wrong, get out, right. And pure A will stop being able to participate in the mining rewards because they have essentiall
y forked 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 pure B, and pure C have nothing in there. So that really shows why in these blockchain worlds in this decentralized world, there really is no centralized entity, you know, pure A, you know, might have been maliciously motivated to change. You know, there's this block number three, however, democracy rules, right, the maj
ority rules in the blockchain, pure vmpfc will say, hey, you know, the, that's cute and all puree. But you're wrong, right? That's not right. Now, it might be a little abstract, that you just look at data and you know, as 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 with pure a pure B Piercey. Except and the difference is, instead of having kind of this, this data section, we have this TX This transaction section, right? And this represents all the transactions that are happening in this block, right? So we're sending $25, from Darcy to Bingle, or to Bingley force toward dollars and 27 cents here. 1922, right. And it's the exact same thing. So this, all these transactions are gonna get hashed in t
he exact same way 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, if I want to say, hey, I really wanted to give Jane a lot more money from Elizabeth, so I'm puree and I go back and I change it to 100. Well, now, you know not only do I does my whole blockchain get invalidated because that was so so long ago, but I'm not going to match any of these other chains. Right? And so my blockchain is going to be e
xcluded from the overall blockchain. So and let's let's go ahead and fix this. And it's the same thing if down here if I become malicious, and I want to send you know, I want Miss Audrey to have less money. Maybe I want to send $1 And they go had in mind it the same thing here, this hash now this two a one is not going to match the rubies rubies hash of BBA. And it's not going to match Pierce's hash of BBA as well. So the two of them are gonna say, hey, this, your blockchain is invalid, it's not
matching the majority, you know, you're out, right. So that's really how 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, to kind of cryptographically prove, you know, where, where stuff lies. Now, the way the blockchain works is, instead of random stuff, put in the Status section, it's actually going to be solidity code in here to finding ways to interact with different blocks and different p
rotocols 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? 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 us money here. How do we know that Darcy sent $25. To Bingley? Well, this is where we get into private keys and public keys. And that's what we're going to go into. Now. Let's jus
t do a quick recap of what we've learned in this section. So far, right? We've learned that Aetherium actually runs on this hit check 256. But we use Sha 256. For this demo, it doesn't really matter. We're just talking about hashing algorithms. So again, 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 and a blockchain is basically a combination of a block, nonce transaction and 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 essent
ially 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 then we'll compare against each other to see which blockchains are acting honestly, and which ones are acting maliciously, in the blockchain world majority rules. The nonce here is the answer used or the number used to get this hash. Now nonce is kind of an overloaded term, it's actually used for a number of different reasons. In th
is case, we're using it to solve this problem of getting four or five zeros at the stop or the hash. However, in Aetherium, it will 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 private keys 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 wa
s Darcy? Who was the one to send $25? To bangli? Right? How do we know that actually happened. And this is where all those pieces that we just learned about in our test net, in our meta mask 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. A private key is you know, as it kind of states is a key that you really want to keep se
cret, because you're going to be using this as kind of your your secret password for all your transactions where I can really pick, you know, any, any, any private key, anything that I want. And with it, this algorithm, or they're going to use an algorithm for Aetherium. Bitcoin, they both use this elliptic curve, digital signature algorithm, 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, some of the hash knowledge that we just learned combined with some other pieces to kind of get this this public here. So I'm not gonna 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 private, we don't want people to see this, we're goi
ng 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 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? Let's say we have this, this message that we want, right? We'll say hi world, right? We want this To be the message, what's gonna 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 using this Shea 256 hash 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 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, and so this is the this is that, Oh, 403. This is that same public key, using this, using this public key, anybody can verify, let's go ahead and sign again, anybody can verify that the signature is yours, right? So you have a public a private key, just for you. So you can sign things and a public key 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, all they have to do is verify that this signature against your public key and very easily, this whole thing turns red, because it isn't verified, right, that the algorithm says, hey, 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 se
nd $400, from, you know, my address to another address, using my private key, I can sign that transaction. And anybody else in the world can then verify this transaction, right. And this is why when people say Hydra keys, you know, protect your keys, this is what we're talking about in our accounts here. Right? If we go to settings, and again, the only reason that I'm showing you guys, my pneumonic, and my private key is because this is a, this is a dumpster account, I'm going to throw this away
at the end of this video, or I'm just not gonna put any real money in it. But when we look at our Metamask, here, we have this pneumonic phrase, which allows us to easily get these different private keys, right? So pneumonic phrase combined with, you know, whatever account number will get us a private key. So mnemonic phrase combined with one, we're gonna get this private key. And this is when we look at account details, export private key. That's where it confirm, this is going to be the priva
te key that we're going to use to sign our 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 that it works the exact same way, right. And so this is why it's so important to hide your private keys and hide your mnemonics now, your Aetherium address is actually a piece is actually a piece of your public key. Now, to get our address in Aetherium,
all we have to do is take this public key that we've created with our private key, hash it using that same Aetherium hashing algorithm, and then take the last 20 bytes. And that's how we'll actually derive to our 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 it too. But just know that that is essentially how kind of these addresses are derived or there's some derivat
ive of the public key, right, because the public key is public. And you know, using the public key and kind of any public way is totally fine, but not the private key. So that is how we sign our transactions. Note though, this isn't how we send the transaction. So so this is just going to assign it create a transaction for us to send, we'll learn later on how to send these transactions. Cool. 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 signed by you is in fact signed by you in our meta mask. Our private
keys are located in this account details section you just hit show private keys and type in your password. And you'll get your your private key here. A quick note here is oftentimes when using your private keys somewhere, they want it in hexadecimal form. So if we're going to use our private key for something like brownie, which we'll go into later, we need to actually append a 0x to the front but We'll get into that later. And the address of your account is derived from this. So if you think a
bout your private key creates your public key, which then can create your address. And there's a little barrier 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 that we know a little bit more about what's going on underneath the hood of these blockchains, let's go back at 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 bid, which is the costs 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 use, which might be a little bit confusing here, let's actually break down what's goi
ng on on Aetherium with ERP 15, five nine in place. And again, this is going to be specific to Aetherium, 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 the specific instructions are, it might actuall
y 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, we go to our Metamask. And we click Send to transfer between accounts again, and we pick you know, 0.01 eath, or something next can actually hit this little button 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 Aetherium takes exactly 21,000 Gas Metamask just defaults to setting into that. Well, 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 Aetherium, according to EE IP 1559, every transaction on Aetherium 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 gateway. So what is a gateway? If we come to the site eath converter.com. And again, there's a link to this in the GitHub repository, we scroll down we can see way gateway and ether five put one ether in here, I can see how much one ether is in terms of way. And in terms of way, one ether is equal to 1-234-567-8990. So that's that's 1 billion way is going to be one ether. And then
1-234-567-8910 1112 1314 Did 16 Seven, eight team and then 18 zeros is away. These are just easier ways of referring to really, really small amounts of Aetherium. So if we look at our gas fees, we see that the base fee is 0.00000004 Go away. And this obviously would be an even smaller number if this was in units of weigh. So if we take this number, and we put it into our calculator, we can see that this is equal to 40 weigh or 0.0000 a whole bunch of zeros for ether. The max fee here refers to t
he 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 maximum was 2.2132 something something and the gas price we actually paid was up here. Now your transaction might of course be a little bit different than 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 currentl
y in Aetherium, 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 Aetherium 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 Aetherium is removed from cir
culation forever, or it's considered burnt. So currently, in theory As part of your Aetherium 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 burnt amount. And this is how much Etherium was paid to Aetherium miner for this transaction, you'll see down here your transaction type to ERP 15, five, nine, this is the eip 15 five nine version of these transactions. Lik
e I said, every blockchain is going to have a different fee burning and fee and gas process. And they're all going to be a little bit different, but the some 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 Aetherium will go up and down depending on how many people are sending transactions and how many people want to be included in a b
lock. 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 15, five, nine 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 s
croll 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 etc. The reason that they wait for these block confirmations is because they want to make sure that that transaction is ac
tually 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. timestamp 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 blocked 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 us 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 gonna 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 ERP 15 five nine transaction, we can see our nonce here, which was not zero because the transaction that I'm showing is our first nones. And then of course, we can see the input
data for transactions that are just sending Aetherium, 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 Freako 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 rewatching and re listening to the parts that you d
on't quite get an 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 doin
g 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 at decentralized blockchain, it's 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 will be we
bsite 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 a peer, a peer, B Piercey. 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 pure A's pure BS pure 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 cr
eates 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 for 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 decentralized. In fact, you can go to GitHub right now, and run your own Aetherium node in a few seconds. Now in the traditional wo
rld, 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't, because they are 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 doesn't matter, the blockchain and the system will persist so long as there is at least one node always runnin
g. And luckily for us, most of the most popular chains like Bitcoin and Aetherium, have 1000s and 1000s 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 even punish it in some systems, because they can easily check everybody else's node and see, okay, this one is out of sync with the majority. And yes, majority rules when it comes to the blockchain. Each blockchain keeps a full list of every transaction and inter
action that's happened on that blockchain and we saw if a node tries to act maliciously, then all their hashes are going to be way out of whack and they're not going to match everybody else. This gives blockchains this incredibly potent immutability trait where nothing can be changed or corrupted. So in essence, we can think of a blockchain as a decentralized database. And with Aetherium, it has an extra additional feature where it also can do computation in a decentralized manner. Now let's tal
k 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. 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 steak 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 sin
gle 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 change is 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 wer
e doing, or where the proof of work algorithm is what's known as a civil resistance mechanism. And this is what Aetherium and Bitcoin currently use. Please note that depending on when you're watching this, if eath two is out, then it's no longer proof of work. 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 o
ther nodes can verify that it's accurate civil resistance is a blockchains ability to defend against users creating a large number of pseudo anonymous identities to gain a disproportionately advantageous influence is over set 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 little bit more in depth first, in proof of work. This is civil resistant, because a single node has to go through a very computationally expensive process called mining, which we demonstrated earlier to figure out the answer to the blockchains Riddle of finding that correct nonce, or, or whatever the blockchain system has in place. And 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 nonce with that first four zeros. But again, each blockchain might change the riddle work 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 blockchain to be. If a system wants to block time to be very, very long, they just make the problem very, very hard. If they wanted to be very short, they make the problem a lot easier. We'll talk about civil attacks in a little bit and how they can affect the system. But with proof of work, it's a verifiable way to figu
re 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 actually the real blockchain and the true blockchain now on Bitcoin and Aetherium, they both use a form of consensus called Nakamoto
consensus. And this is a combination of proof of work and longest chain rule, the decentralized network side 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 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 a
dditional blocks added on after our transaction went through in a block. So if we see confirmations as to 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 Aetherium. One c
urrent 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 was getting this transaction, and this transaction fee is going to the miners or the validators in a proof of work network? They're c
alled miners and in the proof of stake network, they're called validators there are a little bit different. And we'll get into that when we talk about proof of stake in this proof of work 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 real is gonna get that transaction fee, they're gonna 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 gray 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 halving before the halving 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 Aetherium the block reward is giving out
Aetherium and a 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 block chains 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 trends. Action fees. Now
this gas fee, again is paid by whoever initialize 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 steak. 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 c
an happen in these blockchain worlds. Let's talk about the first one being the Sybil attack. The Sybil attack is when a user creates a whole bunch of pseudo anonymous accounts to try to influence a network. Now, obviously, on Bitcoin and Aetherium, this is really, really difficult because user needs to do all this work in proof of work or have a ton of collateral and 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 w
e saw as part of our consensus protocol, these block chains 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 can do what's called a fork in the network, and bring the network onto your now longest chain. Now Sybil attacks, obviously, are when a single node or a single entity tries to affect the d
ecent reality 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 steak. 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 and add to the longest chain, the other nodes will follow this longest chain tha
t 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 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 want it. This is what's
known as a 51% attack. And it's happened on blockchains like Ethereum classic, which is not Aetherium. This is why the bigger a blockchain is, the more decentralized 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 node 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 th
e Sybil attacks and keep our blockchain is decentralized and secure. However, it has some drawbacks 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 and 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 t
o 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 thriving. Some of them are like avalanche, LaLana, Polygon, polka dot and Terra and additionally Aetherium is decided to upgrade to eath. Two, which will have this proof of stake algorithm as well, it will also have some other features, which we'll talk about in a bit. Now as a quick aside, all the tools t
hat we're going to learn here are still going to work in eath. Two, so depending on when you watch this, everything here is still valid. 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 Aetherium. two nodes put up some Aetherium as a stake that they're going to behave honestly in the network,
if they misbehave to the network, they are going to be slashed or remove some of their steak. 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 actu
ally just validating other nodes. Now, unlike proof of work, which every node is racing to be the first one to find the block, and 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 nodes to verify if a proposal or a transaction is honest. Now randomness is a really important topic when we're talking abou
t blockchains. Because keep in mind, these blockchains are deterministic systems. They're walled gardens from the rest of the world. And as you know, a deterministic system by definition can't have random numbers. So how do we choose the random validators in the system? While it changes from blockchain to blockchain, and actually choosing the node will change blockchain to blockchain, but eath two, they're using what's called Rand doubt, at least for the original implementation. This is a decent
ralized autonomous organization that collectively chooses the random number and collectively chooses which node is going to run. Next, we aren't going to dive too deep into this because there's a good chance that this might change in the future. But we will go into randomness solutions and blockchain later on in this course. 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 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 cost to participate. Now, this gets into a little bit of a philosophical battle on how decentralized is decentr
alized 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 very, very decentralized and very secure. This massive environmental impact improvement is one of the two main reasons why eath is shifting to eath. Two, it reduces the environmental impact by up to 99%. Now, these are the main pieces of proof of
work and proof of stake. But I did want to talk about another concept that's really important in these ecosystems. And that is scalability. When we were talking about gas prices, we were saying that the gas prices can get really high if a lot of people want to send a transaction, because a block only has so much black space, and the nodes can only add so many notes. So when a lot of people want to use a blockchain, the gas price skyrockets. This is not very scalable, because if we want to add m
ore and more people to these blockchains, it's going to cost more and more to use the blockchains. Because more people are going to want to get into these blocks. This means that there's kind of a ceiling to how many people can use the system because of the financial constraints that will get imposed as gas prices keep rising. Aetherium too is not only attacking the environmental impact of proof of work by switching to proof of steak, but they're also implementing this new methodology called sha
rding. And sharding is a solution to the scalability problem, a sharded blockchain really just means that it's going to be a blockchain of blockchains there's a main chain that's going to coordinate everything amongst several chains that hook into this main chain. This means that there's more chains for people to make transactions on effectively increasing the amount of block space that there is sharding can greatly increase the number of transactions on a blockchain layer one now there's anothe
r term that might be the first time you heard it, a layer one, we're going to talk about layer one and layer twos in terms of scalability really quickly as well. A layer one refers to any base layer blockchain implementation Bitcoins, a layer one Aetherium the layer one avalanches, 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 the blockchain. Some examples of layer twos are going to be chain link arb
itrage, or optimism. Arbitrage and optimism are very interesting because they are layer twos that also look to solve this scalability issue. Arbitrage and optimism are what's known as roll ups and they roll up their transactions into a layer one like Aetherium, we're not going to go too deep into roll ups and how they actually work. But all you really need to know is that a roll up is kind of like a sharded chain, they derive their security from the base layer from the layer one like Aetherium.
And they bulk send their transactions onto the layer one, they solve some of the scalability issues by being another blockchain that people can make transactions on, still on kind of this base Aetherium layer. Now they're different from side chains. Because side chains derive their security from their own protocols, roll ups, derive their security from the base layers. So arbitrage and optimism, for example, is going to be just about as secure as Aetherium. There's some fantastic guys in there t
hat go a little bit deeper into roll ups and I've left a link in the description for you. All right, so we just talked about a lot of stuff. So let's do a quick recap before moving on. Aetherium and Bitcoin are currently both proof of work blockchains that follow Nakamoto consensus, however, Aetherium is moving to Aetherium two, which will be a proof of stake sharded blockchain Sybil attacks are prevented due to protocols like proof of work and proof of steak 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 roll ups are solutions to scalability issues on layer ones. Layer One is any based blockchain implementation like Bitcoin or Aetherium. 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 a Again, gas prices
or how much it costs to interact with the 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 gotten a lot of t
he basics and the fundamentals 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 the 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. Now that we're getting to the coding sections, I need to stress to absolutely use the GitHub repository associated with this course. If you come to the GitHub repo, and you scroll down
, and you click the lesson that we're on right now, we're on lesson two. Welcome to remix, simple storage. If you click on it, it'll give you a ton of timestamps and, and other helpful links associated with this lesson. Additionally, the biggest piece is that all the code will be available right underneath the lesson title. This will have all the code that we're going to be working with, as well as some more additional information on how to work with the code. Please, when asking questions and e
ntering in discussions, though, please ask your questions and the full blockchain solidity course repository. Thank you. And if we're at the top of the repository, and we scroll down, we have the resources for this course section. Which brings us to the GitHub discussions in which you can ask questions in the GitHub discussion section of this course. Additionally, on Stack Exchange, Aetherium, or at Stack Overflow. I'll talk a little bit about how to format questions and ask questions the best w
ay so that you have the highest chance of getting a good answer in a later lesson, I highly recommend you pause and make accounts for Stack Exchange Aetherium, Stack Overflow, and GitHub right now, if you haven't already, links to them, of course, can be found in our GitHub repository. Typically, for each coding section, I'll start it off by giving a quick overview of the code of what we're going to be working with and what we're going to be building towards, since everything that we're doing is
going to be project based. And that's how we're going to learn. For our first one and remix though, we're going to skip over that because there's a lot of stuff to get used to. Now, I highly recommend that as I'm coding this. And as I'm doing all this in remix, you follow along with me and you code along with me. Remember, you can change my speed if I'm coding too fast, or if I'm coding too slow. To start, we're going to jump into a tool called remix. If you're unsure how to get there, there's
a link to remix in our GitHub repository. This is where we're gonna be writing all of our code. So welcome to the remix IDE, or integrated development environment. This is where we're going to learn how to code and interact with our smart contracts. If you want, you can go ahead and accept help out remix. If you've never been here before, it'll give you a quick walkthrough of some of the tools that remix actually has, we're going to skip over them for now. Because I'm gonna explain everything th
at's going up. Remix is such a powerful tool because it has a lot of features that allow us to really see and interact with our smart contracts. Eventually, we're going to move off of remix, actually to a local development environment. However, remix is absolutely fantastic for learning the fundamentals of solidity. And I highly recommend everybody start with remix when they're getting started. When you come to the remix IDE, there's a whole lot of different things that are popping out to us. Th
ere's a lot of different plugins as well. Since we're going to be working with solidity, which is going to be the language that we're using to develop our smart contracts. We can go ahead and get started by clicking the solidity plugin, and a couple of other tools will show up on the side. Even if you don't click the solidity plugin, you'll still be able to code solidity smart contracts, the left hand side is where we're going to start to actually interact with things. The button on the top most
of the left is our files or explore directories, remix comes boilerplate with some different contracts, some different scripts, some different tests, and different dependencies. We are going to minimize this a little bit. So if you want to go ahead and right click and delete some of these folders other than the contracts folders, feel free to do so. Or if you kind of like them there, feel free to leave them as well. We're going to leave our contracts folder and we're going to delete the differe
nt files inside of it just so that we can start From a blank slate. Most projects come with something known as a readme. Usually it's a readme.md, which usually explains how to actually work with code. But for our purposes, we're going to delete this as well. And you can just follow along with me. Now we have a blank remix Setup, click on the contracts folder and click the little page icon to create a new file, a little box will pop up and you can start typing text into it. We're going to type i
n simple storage dot Sol, dot Sol tells our compilers that this is going to be a solidity file, and that we're going to code solidity in this solidity is the primary coding language of smart contracts. There are a few other smart contract languages as well. But solidity by far is the most dominant smart contract coding language out there. And now we have a simple storage dot soul contract on the right that we can actually start coding our solidity with. So let's start coding some solidity. Now i
f you click on this button right below the files button that looks like the solidity logo, you'll see a bunch of stuff pop up in here. These are different parameters for us to actually compile our solidity code so that we can run it. So the first thing that you're going to need in any solidity smart contract is going to be the version of solidity that you're going to use. And this should always be at the top of your solidity code, solidity is a constantly changing language, and it constantly upd
ating language. Because it's relatively new compared to other languages, we need to tell our code, hey, this is the version that I want you to use, we can add the solidity version by doing pragma. solidity. And then the version that we want to use, if we want to choose a very specific version, we could say zero, point 8.7. The most current version to date is 0.8. Point 12. But getting used to different versions of solidity is good practice, and different versions of solidity are considered more
stable than others. Zero point 8.7 is one of those versions that is considered more stable. These double slashes here are what's known as a comment, there are places where you can type stuff that won't actually get executed in won't get compiled and isn't really considered part of your code. For example, I could write Hello all. I'm Patrick. And if we were going to run this code, this part of my code would get completely ignored. So this double backslash is how we do what's called comments. And
as we're coding, and as we're building our projects, be sure to use this comments tool to your advantage every time you write a new function, or you learn something that you didn't understand, or you learned something new that you want to remember, put it in a comment in your code, you're going to be most effective at taking notes in this course, by making them comments in your code and then saving your code so you can refer back to it later. So leave comments in your code, leave notes in your c
ode. And that will be one of the best ways for you to understand what you're coding when you want to refer back to it later. Now when it comes to the versions of solidity, there's actually a few different ways we can actually write it, we can say we want to use only zero point 8.7. And this is how we would write that. But maybe we're okay if we use a more new version of solidity than zero point 8.7 to tell our code that we're okay with a more new version, we can put a little caret here. And this
is how we tell solidity. Hey, any version of zero point 8.7 And above is okay for this contract. This means zero point 8.8 would work zero point 8.9 0.8 point 10, etc. But if we wanted to use just 0.17, we would type in like that if we want to use solidity versions between a specific range, we could do something like this, we can say we want our solidity version greater than or equal to zero point 8.7 But less than zero point 9.0. This means that any compiler between zero point 8.7 and zero poi
nt 9.0 would work. This means zero point 8.8 would work. Zero point 8.9 would work 0.8 point 10 would work. But zero point 9.0 would not work because it is not strictly less than 0.9 point 00 point 9.1 would also not work. To keep things simple for us, we're going to use zero point 8.8. And every line of solidity that's completed, every completed section needs to end with one of these semicolons this is how you tell solidity it's the end of the line. Also at the top of your code, you're always g
oing to want to put what's called an spdx license identifier. This is optional, but some compilers will flag your warning that you don't have one. This is to make licensing and sharing code a lot easier. We have a link to more about how licenses work in the section of this lesson in our GitHub repository to do an spdx license identifier, we just say spdx license identifier, and we're gonna choose MIT, the MIT license is one of the least restrictive licenses out there. So we use the MIT license f
or most of our code samples once you have a version and once you have Is this much written, we can actually go ahead and write to our compiler tab and scroll down and hit Compile, that little turn thing will go. And in a minute, we'll see, this contract is attempted to be compiled. Since we actually don't have a contract, we see no contract compiled yet, but we see the compiler automatically switched to zero point 8.8. compiling our code means taking our more human readable code like pragma, sol
idity and transforming it into computer code, or very specific instructions for the computer to use. We'll go over what a lot of this machine level code or this computer level code is doing in a later section. If you're using a Mac, you can also hit command S, and it will run the compiler for you as well. On Windows, it might be Ctrl S, we can actually choose the compiler version that we want to use. However, if we tell in our code to specifically use zero, point 8.8, and we hit the compile butt
on, it'll automatically switch to zero point 8.8. However, if we use the carrot thing, we get specifically say, hey, we want 0.8 point 10, we can hit compile, and it will compile with 0.8 point 10. Because again, remember, the carrot says we want to use at least zero, point eight, all the way up to the latest version of 0.8. Now let's stay on zero point 8.8. The next thing that we're going to do in our code is define our contract. And to get a full screen view, you can go ahead and hit the compi
ler button to get rid of it there. To start defining our contract, we're gonna go ahead and write the word contract. This tells solidity that the next pieces of code is going to be a contract contract is a key word in solidity, and it tells our compiler that the next section of this code is going to define a contract. You can think of a contract similar to a class in any object oriented programming like Java or JavaScript. Let's go ahead and give our contract a name here, we're going to call RS
simple storage. And then we add this little open and close curly brackets. Everything inside this open and close curly brackets is going to be the contents of this contract. Simple Storage. Now, if we go ahead and hit command S or Ctrl S, we can see this little green checkmark show up. And if you don't, you can always go back to the compiler tab, scroll down and hit Compile and see the little green checkmark. That little green checkmark means that our code is compiling successfully. And we don't
have any errors, we could hypothetically deploy this contract right now. And it would be a valid contract. So congratulations on writing your first contract. Now solidity has multiple different types or primitive data types. And if you go to the solidity documentation, which again, is in our GitHub repository, you can read more and learn more about the different types that are in here. The four most basic types are going to be Boolean, you int, int, and an address or bytes, which is a lower lev
el type, which we'll talk about a little bit later. A boolean define some type of true false, a you int is going to be an unsigned integer, which means it's going to be a whole number that isn't positive or negative. It's just positive, we have an integer, which is going to be a positive or negative whole number. And then we have an address, which is going to be an address, like what we see in our meta mask here. There are some other types as well that you'll learn later on. The reason that we h
ave these types is we use them to define what different variables are. Variables are basically holders for different values. For example, we could create a variable called has favorite number to represent if somebody has a favorite number. And we would put this bull keyword before has to renumber say, Okay, we have a variable called has favorite number, and it's of type boolean. So this has favorite number is going to represent a true or a false to set its value, we could say has favorite number
equals true. Now has favorite number is going to be true. We could also say has favorite number equals false. So this Boolean has faded number is now going to be false. For uns we could say you went favorite number equals and then set a number 123. This means that our favorite number is going to be 123 You'll enter is special because we can actually specify how many bits want to allocate to this number bits and bytes are pretty fundamental pieces of information for computer science. We're not g
oing to go over it here. However, there's a fantastic video in the GitHub repository that explains it more. Basically, it's how much storage or memory to allocate to this number. How big can it get, if we say a you int eight can have eight bits all the way up to you went to 56. If you don't specify how big it is, it automatically defaults to you into 256. Oftentimes, it's better when writing our code to be very explicit. So usually you'll see me just do you int 256 to represent a un 256. We coul
d also do an int favorite number equals 123 or an int 256. I'm just Going to go ahead and add this Boolean back here, we're going to change this back to UNT to 36. And let's change our favorite number to five here, we could also do something called strings, string, favorite number in text equals five strings represent basically words, and you can represent them by putting them in these quotes, it's going to be some word or phrase, or really, really just kind of any combination of keystrokes in h
ere, our ends can be positive or negative. So we could say, negative five or positive five, both are going to be valid, since we can also do address my address equals and grab our address, right from Metamask. And paste it in, you'll notice that we end all of these lines of code with the semicolon. We also have bytes objects, or a bytes 32, again, representing how many bytes we want them to be. And this says that we have called favorite bytes, and we're just gonna set it equal to cat. So strings
are actually really interesting, because strings are secretly just bytes objects, but only for text to a cat is actually a string, but can automatically get converted into one of these bytes object bytes, objects typically look like 0x. And then some random letters and numbers that represent the bytes object, but cat can automatically get converted down to bytes. We'll talk about bytes more in coming sessions, you can also do bytes, two bytes, three bytes, five bytes 22, you get the picture for
our uns and our into the sixth lowest we can go is eight bits, because eight bits is a byte. And we can go up by steps of eight. So we can do 816 32, etc, all the way to 256. For example, down here, we can't do bytes 64. And if we go ahead and try to compile this, we get a little red thing here. And if we scroll down, we get a declaration error identifier not found or not unique. Bytes 64 favorite bytes equals cats. And we even got a little red warning sign here in our remix. This is remix tell
ing us there's something wrong with this line. So we can switch back to bite 32. Since byte 32 is the maximum size that a bytes can be, you could also do just a bytes object, which means it can have any size, but we typically want to be explicit. And we're going to stick with bytes 32 For now want to learn more about the different types and how to use them and all the different features with them, be sure to check out the solidity documentation. For now for our simple storage, let's say we only
want to store numbers. So let's go ahead and delete everything except for the favorite number section. Now in solidity, if I do this, and I remove the equals five, this favorite number actually does get set to a default value, the default value for solidity is going to be whatever the null value is, which in solidity is case zero. So saying you Intuit six favorite number is going to be the same as saying you 256 favorite number equals zero since it gets initialized to zero. So for now, let's not
initialize it to anything. So that favorite number will automatically start off as zero. Now, if you get confused, as you're coding along, and you're following along with me, be sure to write comments in your code so you know what's going on. So maybe, for example, a great comment here would be this gets initially alized to zero. And then if that's even confusing, you could say, this means that this section is a comment. Now let's go ahead and create a function functions or methods are self con
tained modules that will execute some specific set of instructions for us, when we call it if you're familiar with Java, or Python, or JavaScript or anything like that functions work the exact same way functions get identified by the keyword function, let's create a function called store that will change the value of favorite number to some new value. And the number that we're going to change it to is going to be variables that are passed to our store function here. So we're going to allow our s
tore function to take a variable of type un 256. And we'll call it underscore favorite number, we'll make this a public function, which we'll get to in a minute. And all we're going to do is we're going to set favorite number equal to whatever variable that we just passed. So now we have this function called store, that it takes some parameter that we're going to give it and it sets this favorite number variable equal to whatever number that we give this function. Now to see this actually in act
ion, let's deploy this to an even thicker blockchain than a test net. We're going to actually deploy this to a local network or a JavaScript VM. And first before we can even do that, let's just make sure that it's going compiling correctly looks like we have a green checkmark, which is good. And we'll come down to this button here, which is our deploy and run Transactions tab. Our deploy and run Transactions tab has a ton of different configuration pieces for actually deploying this contract. Fi
rst, we want to make sure we are on the JavaScript VM London piece here, JavaScript VM means we're going to be deploying to a fake local JavaScript VM. The JavaScript VM is a fake local blockchain where we can simulate transactions really quickly without having to wait for them to go through on a test net, don't worry about the London versus Berlin piece here for now, injected web three and web three provider we'll talk about in a little bit. We also have this account section here. When we run o
n our fake JavaScript VM, we're given a whole bunch of fake accounts from where to deploy from, and we're given 100 eath. For each one of these fake accounts, you can kind of think of it similar to our meta mask account in meta mask, except for the difference here is that this is this fake JavaScript VM Aetherium that we're given. For our transactions, including deploying contracts, we're actually given a gas limit, there's also values we can send, and we can choose our contracts. Right now we o
nly have one contract, simple storage, so that's going to be the one that we're going to deploy. So on the left hand side, to deploy this to our fake JavaScript VM, we're gonna go ahead and hit the Deploy button. And if we scroll all the way down to the bottom, now, we can see a contract was deployed. It says simple storage at x, blah, blah, blah, blah, blah. And we see this orange button store with come this grade text you in 256, underscore favorite number on our fake local blockchain, we're a
ctually given an address every single smart contract, it has an address, just like how our wallets have an address. So if we hit this copy button here, and we put it into a comment, make this a little bit bigger, we can see that the address of this contract that we just deployed, is located at this address. Additionally, if you pull up the slider over here, you'll be able to see this little green checkmark with all this information about this deployment. And you can hit the little drop down and
see a whole lot more information about this. Something you might notice is you'll see some familiar keywords like status, transaction hash, from to gas, etc. When we deploy a contract, it's actually the same as sending a transaction. Remember, anytime we do anything on the blockchain, we modify any value, we are sending a transaction. So deploying a contract is modifying the blockchain to have this contract, it's modifying the state of the blockchain. And if we had sent this on a Rinkeby, or COV
ID, or main net network, we would have had to spend the gas to actually deploy this contract. And this is the simulation of how much gas and the transaction hash and from and to and all this other stuff about our transaction had, we actually deployed it to a real network. But since it's JavaScript VM, it's all fake information. Now we have this big orange button store, this big orange button resembles the store function that we just created. So if we add some number into this store, like 123, an
d we hit the Store button, we actually call this store button. And we actually execute a transaction on our fake Jasika. Blockchain to store the number 1234 favorite number. And if we scroll all the way up to our account, now, you'll see that we have a little bit less ether in our fake account. This is because we spent the gas to actually call this contract. And if we pull up this bottom bit here, and I call this with five I call store, you'll see it flashed for a quick second, we sent another t
ransaction to store the value five in our favorite number. Now the question might be having is, that's really cool, Patrick, but I can't see what favorite number actually is, how do I know that those transactions are actually going through? Well, right now, the visibility of our favorite number is set to private, so we actually can't see it. And we'll talk about visibility in just a second. To make it so that we can see it. We'll change our favorite numbers visibility to public. So let's go ahea
d, we'll recompile we'll go back to the deploy tab. We'll click the little x here, which is to say let's get rid of this contract. And it just gets rid of it from our window here. It doesn't actually get rid of it from the blockchain, because again, they're immutable, well, kind of immutable, since again, this is kind of a fake simulated chain. But we go ahead and compile, and now we hit Deploy again. And if we scroll down, our new contract, will now have two buttons. One is the orange button fo
r store. But now we have a New Favorite button. This button represents this public variable favorite number, and it resembles a function saying, Hey, show me what favorite number is. So if I were to click this favorite number button, what do you think will show up? Well, do you remember what this gets initialized to? Well, let's click it now. We do indeed See that zero shows up, we see that this is a YouTube ID six, and the value stored in it is zero. Now, if I were to change that number to five
by calling the store function, and now hitting favorite number, we do indeed see, favorite number gets updated to five functions and variables can have one for visibility specifiers, we have public, private, external, and internal. Public is visible externally and internally, meaning anybody who interacts with this contract or sees this contract can see what's stored in this favorite number function. You'll see here in the solidity documentation, it says it creates a getter function for the sto
rage slash state variables. When we add this keyword public to favorite number, what we're actually doing is we're creating what's called a getter function for favorite number, we're basically creating a function that says to return the value of favorite number, and that's why this blue button pops up. Because this blue button is a function that says, hey, return the value of favorite number private means only this specific contract can call this function. Now for storage, it doesn't mean only t
his contract can read what's stored here. And we'll get into that a little bit later. But by that means, this is the only contract that can call the favorite number function. Private functions are only visible to the current contract. External functions are only visible externally, meaning somebody outside this contract can call this function. And then internal means that only this contract and it's children contracts can actually read it, but we'll get into that a little bit later, too. So oddl
y enough, variables are just function calls. Now, the reason that we didn't see favorite numbers show up on the left hand side, when we first deployed this without the public keyword. When we don't give a visibility specifier to functions or variables, they automatically get deployed as internal. And as we know, internal functions and variables can only be called by this specific contract or derived contracts, which again, we'll get into later. So let's just keep it public. For now, the reason t
hat we're prefixing, our parameter here with an underscore is a way to tell us, hey, this variable here is different from the favorite number global, there are some different naming conventions that are used for parameters. And as we get later into the course, will understand more and more of what good names are parameters are, every time we call this store function. And we change the value here, we're actually sending a transaction because remember, every single time we change the state of the
blockchain, we do it in a transaction. And we can see all the details here. If you go over to the transaction details in the logging area of your remix, you can actually scroll down and you can see the transaction cost in units of gas, you'll see a number of something around this. And you'll notice it's more than that 21,000 number from sending Aetherium. That's because we're doing something more computationally expensive. We're actually storing a number over here. Now what do you think will hap
pen if we do more inside of the store function as well. So instead of just storing this number, maybe what else we do is we will store the number here. And then we'll update our favorite number will say favorite number equals favorite number plus one. Since we're doing more stuff, now we should see this store function actually become more expensive. So let's go ahead and recompile we'll do delete this will redeploy. We now have a new contract will store five again. Now if we look in the details
of this transaction, and we scroll down to execution costs, we do indeed see the amount of gas has greatly increased. And that's because we're doing more things, this store function is now more computationally expensive. And like I said, each blockchain has a little different way of how they actually calculate gas. But the easiest way to think about it is, the more stuff you do, the more expensive that transaction is going to cost. So let's go ahead and delete this line to continue our example.
Now let's talk about scope for a second, our favorite number is basically in something called the global scope, meaning anything inside of these brackets can access this favorite number variable. But what if I did something like this? What if I made a un 256 called Test var? And I set it equal to five? And then I created a new function called something will have it take no parameters and be public? Could I access the test var and then change it to something like six? Can we do that? Well, let's
go ahead and see what happens when we try to compile this. We actually run into an error. We had expected primary expression right here. Oh, well, that's because I have the double question mark. Let's try now. We get undeclared identifier. Our something function doesn't know about this test var when you create variables, they only can be viewed in the scope of where they are. Now if that's a little confusing, just look for the curly brackets. These two curly brackets encompass this whole We'll s
ection here write, the opening one is up here, the closing one is down here. So if I create a variable directly inside of these curly brackets, that means everything in here can access it. However, test var was created inside of these curly brackets, which means that only stuff inside of these curly brackets can access test var, since our functions something isn't inside of store, or something function won't know about test var. So that's how scope works, you want to look to see if your variable
that you created is inside of these curly brackets. And that's how you can know if other functions can work with them. So this is why this fails. Now, like what we saw in the documentation, when we add this public variable to favorite number, we're secretly adding a function that just returns this favorite number, we can also add our own function that also returns the favorite number to resemble the function that's getting created in the backend. So we can say function, we call it retrieve, and
we make it a public view. And we'll say it returns, you went to 56. or explain what that means in just a second. And we'll say return favorite number. Now, I'm going to hit command S, which again, I'm going to do that a lot throughout this section. But just remember that that's equivalent to me going to the compile tab and hitting compile. Now if we go to the deploy tab, delete our last one, deploy a new one, we now have a retrieve function, which is going to return the exact same thing that ou
r favorite number is going to return. Again, if we update this to five, called favorite number and then retrieve they both now return five. Now as you can see here, these two functions are blue, but this function is orange. What's the difference? Why did these have these different colors? Well, the key lies in this view keyword here, there are actually two keywords in solidity that notate a function that doesn't actually have to spend gas to run. And those keywords are view, and pure. And let's
also get rid of this variable here. A function that is a view function means we're just going to read state from this contract, we're just going to read something off of this contract. For example, our retrieve function right now is just reading what favorite number is, a view function disallows any modification of state. So you can't update the blockchain at all with a view function. Pure functions also disallow any modification of state. So we couldn't update our favorite number. Not only that
, but they also disallow reading from the blockchain. So we couldn't read favorite number either. Instead, what you might do with a pure function is maybe something like function, add public here, one plus one, or return, one plus one, this would be turns you into 36, maybe something like this, maybe there's some math you want to use over and over again, maybe there's some specific algorithm that you want to implement that doesn't actually need to read any storage, etc. Now, if we call a view fu
nction, or a pure function by itself, we actually don't need to spend any gas. Since we're just reading from the blockchain. Remember, we only spend gas we only make a transaction if we modify the blockchain state. So you'll notice in our little console down here, that if I call retrieve this call things comes up. However, it looks different than when we call the store function. And we call the store function, we get this little checkmark, we get a hash, we don't get a little checkmark. And we d
on't get a hash with the calls. That's because clicking these blue buttons doesn't make a transaction. This is saying, Hey, we're just going to read off chain, we're just going to read this value. However, if you look in the details of this call, there's this execution cost bit here. So what's going on? Well, we can read this part right here, cost only applies when called by contract. If we do have a function that calls retrieve, if there's a function that is updating state that calls a view or
a pure function, that's the only time it'll cost gas. So for example, if our store function which is not a view function, were to call retrieve at some point, then we'd have to pay the cost of the Retrieve because reading from the blockchain cost this computation and cost gas calling view functions is free, unless you're calling it inside of a function that costs gas, in which case it will cost gas. So if we leave it here, we delete this recompile redeploy. We had favorite number retrieved, they
both still cost nothing. But if we add, restore eight in here, we can see, we can see our execution cost has gone up from what it was without retrieve, which we can go ahead, we can compile, I hit command us to compile here, we can deploy. Let's go ahead and store again. We'll click on that transaction, we can see that it's much cheaper without that retrieve function in there. And again, our favorite number variable as long as it has this public visible solidity, it also is counted as a view fu
nction that returns a un 256. The returns keyword means what is this function going to give us after we call it so we say this function is going to give us this function is going to return a un 256. When we call retrieve, it's going to return or give us a utility six. This is the result of calling the function this six is the result of calling arbitrary function. Now our contract is good as it is, it allows us to store a single favorite number. But what if we want to store a range of favorite nu
mbers? Or maybe we want to store a whole bunch of different people who have different favorite numbers? Well, how do we do that there are several different ways that we can approach this, one of the ways we could start approaching this is by creating what's called a struct of people. Or we create a new type. In our solidity, we can create a people object that holds both someone's name, and their favorite number. To do that, we say struct people, you went to 56, favorite number, and a string name
. Now we've created a new type called people kinda like you intuited six, or Boolean, or string. Now we have a people type that we can use. Now similar to how we created a un 256 public favorite number, we can do the exact same thing. But with a people, we could say people public, we call this person, and we can create a new people and assign it to this variable person. So we'll say equals people public person, equals, and we'll add parentheses here to signify we're creating a new person. And si
nce we made this a struct, we add little curly brackets here to let solidity know that we're going to be grabbing from these struct variables, we'll say favorite number is going to be two, and the name is going to be Patrick semicolon, and then we can hit Ctrl S, or we can go ahead and compile. Now if we go ahead and deploy this we now have a new person, since this, again, is a public variable, it has a getter function called person. And if we click person, we see our new object, the favorite nu
mber is two. And then the name is Patrick, you see this zero and this one, because these are showing the index of the different variables. But those of you new to computer science, typically in computer science, let's start with the number zero. So what are zero with index, we have you in 256, called favorite number, which is saved at two. And then at index one, we have a string, which stands for the name of Patrick, whenever you have a list of variables inside of an object in solidity, they get
automatically indexed. So favorite number gets indexed to zero, and name gets indexed to one. Interestingly enough, if you have a whole bunch of variables inside your contract, like we have public favorite number, this favorite number, actually, technically is getting indexed at the zero with storage slot. And if we were to make another one of these, maybe you want to get six public brother's favorite number, this would technically be indexed at the first slot. And then if we were to make one m
ore, maybe sister's favorite number, this would be the next add the second slot. So favorite number at zero, this add one, and this a two, but we'll learn more about that much later in the course. Similarly, favorite number is index zero name is index at one. Now what we have is great, but if we want a whole lot of people are we gonna have to keep copy pasting and changing the people's name person to their favorite one, number one, number three, will name them ally. Person three, their favorite
number will be seven. Their name will be Chad or something. This obviously isn't great way to create lists and large number of people's because we have to statically keep typing them in. So a much better way to create a list. And let's actually just go ahead and delete Patrick to a much better way to create a list is to use a data structure called an array. An array is a way to store a list, or a sequence of objects, creating an array works the exact same we've seen to initialize other different
types. Typically, we do the type of the object, the visibility of the object, and then the variable name. We do the exact same thing with arrays. We'll say we want a people array. These little brackets represent that we want an array of people. We'll give it a visibility of public and we'll call it people you could do the same thing with you and 256 for example, you could say you went to 56 public favorite numbers list and just add this little array key here. And now favorite numbers list is go
ing to be an array or a list We're going to comment that out for now. Now if I were to go ahead and deploy this contract, let's go ahead delete the last one, let's redeploy. We now have this blue people button here. Remember, since it's public, and it's a variable, it automatically is given a view function, it's given one of these blue buttons. And instead of just having a single button where the value shows up, it's giving us a form to fill out, it wants to take a un 256 as an input parameter.
So if I put zero, I get nothing back, if I put one, I get nothing back. No matter what you put in this box, right? Now we're gonna get nothing back. This is because our people array or our people list is currently empty. And the value that it wants is going to be the index of the object that you want. So for example, if at index zero, I had Patrick, it would show Patrick for zero, if it didn't x one I had John, or actually better yet, to Patrick. Seven, John, etc. This is what it would show. But
since it's empty, it's going to show nothing. And let's go ahead and remove the public variable from favorite numbers so that we don't get the duplicate functions at the moment, we'll just get the Retrieve function, we'll show you how to add to this array in just a second. This type of array is what's known as a dynamic array, because the size of the array isn't given at the array initialization. If we were to say, a people array and add a three in these brackets here, that means that this list
, or this array of people could only be three people big, if we don't give it a size, it means it can be any size and the size of the array can grow and shrink as we add and subtract people, if I add three, it can only have a maximum of three in the array ever, we're going to work with a dynamic array, because we're going to want to add a arbitrary number of people to this array. So let's go ahead and create a function that's going to add people who are people array, so we're gonna say function,
add person. And we're going to take string, memory, name as input parameter, and I'll explain that in a minute. And a un 256 underscore favorite number, we're going to make this a public function, or we're going to do is we're going to call a push function that's available on our people object. So we're gonna say people dot push, and we're going to create a new person, a new people object, which is going to take in the favorite number. And the name. Now, this might be a little bit tricky to you
. So let's break this down. People here is capitalized. So we know that since capitalize, it's referring to this struct people and not our variable people, the lowercase people here is referring to this lowercase array. So we're saying our array dot push, or push is the equivalent of adding basically, a new people that grabs favorite number and name. Another way that we could actually do this is we could create a variable of type people and then add it like so. So we could say people, new person
equals people. And then we put those brackets the same way we did before. You say favorite number is going to be this input value, this parameter, and we could say name is going to be this parameter. Now if you hit save, you'll get this error set here, saying data location must be stored in memory, or called data for variable but no one's given. For now, we're just going to add the memory keyword here, and I'll explain what it does in a little bit. And then of course, we need to add the new per
son into our people dot push right here. So this is how we're actually going to push people into our people array. And I'll get to this memory keyword in a bit. Now if we go back to our deploy tab, we delete our last contract. Let's deploy this new one. Right now, if we try to look at the zero with person in our people array, we get nothing but let's go ahead and add a person, we'll call it, Patrick will be the name, and seven will be the favorite number. So we added Patrick, we added seven. Now
if we look at people's zero, we should see the zeroeth person has a name of Patrick, and a favorite number of seven, boom. And that's exactly what we do see, we see a favorite number of seven, and we see a string name Patrick, we tried to add John and do his 16. We hit Add Person, we can see our transaction go through. And now if we go to people at zero, it's still Patrick with a favorite number of seven. But if we look at the people at index one, it's going to be John with a favorite number of
16. And if we look at two, this, of course, should be blank. And we do indeed see nothing actually happens here. Perfect. Now there's actually a couple of different ways to create this new person here, like we showed before, we can use this bracket notation, or what we can do is we can actually just add the parameters in the order that they show. So the first parameter for people is going to be favorite number. So we can just do favorite number, comma, and the second one is going to be name, th
e second one is going to be name. So if we save this, this, this line we just created is the exact same as the last line, we're being a little bit less explicit here. So the other way is generally a little bit better because it's more explicit as to what variables are what or we don't even need to save to this variable here, we could take out this whole line, replace new person with exactly what we just saw, like so now we don't even need the memory keyword. Now, you've probably seen this by now
. But if I go ahead and compile, and I see a little, little red one here, I roll over. And it says something about error, expected semicolon, but got bracket, all these errors mean that your code isn't compiling. It's not working as expected. So now I can go over here and do a little semicolon recompile, and I get a green. Now if I delete this top line, for example, and I compile it, actually get a yellow thing. Yellow stands for warnings, the warning that I get is warning SPX license identifier
, not provided, you should add it. So let's go ahead and add that back. recompile. And the warning goes away. Warnings Don't stop your code from compiling. So if you get warnings, it's okay. But it's usually a good idea to listen to the warnings, because often they'll give really insightful information about how to improve your smart contracts. So to summarize, if it's red, it's broken. If it's yellow, you might want to check it out. But it won't stop you from continuing to code. So one thing th
at you'll notice here is that we have this memory keyword. And you'll notice if you try to delete it from our function here, you try to compile, you actually run into an error data location must be memory or call data for parameter and function. Now there are actually six places you can store data in solidity you have the stack, memory, storage, call data, code and logs. We're not going to go over these right now. But we are going to focus on three of the big ones, or three of the important ones
for this section, which are called data, memory, and storage. So for this section, we're going to talk about call data memory and storage. And this is a little bit advanced. So if you don't totally grasp it the first time, that's totally okay. Please continue. Even if it's not crystal clear what's going on here, call data and memory mean that the variable is only going to exist temporarily. So this name variable only exists temporarily during the transaction that this Add Person function is cal
led storage variables exist, even outside of just the function executing. Even though we didn't specify it up above, our favorite number is automatically cast to be a storage variable. Since it's not explicitly defined in one of these functions. Since we don't need this name variable anymore after this function runs, we can keep it as memory, or we could keep it as called data, you can have a parameter as called data if you don't end up modifying the name. For example, we couldn't reassign name
to equal cat here, if we compile we run into an error. Type literal string cat is not implicitly convertible to expect the type string called data. However, if we have this as memory, and we compile and save it, that error goes away call data is temporary variables that can't be modified. Memory is temporary variables that can be modified. And storage is permanent variables that can be modified. Now even though I just said there's actually six places where we can access and store information, we
cannot say a variable is stack code or logs, we can only say memory storage are called data, you will learn why in a much later section. Now, this is a bit of an oversimplification of this. But that's essentially what's going on. The next question you might have is, well, why do I need to say memory here, but I don't need to say memory here. Well, let's go ahead and put memory here and hit CTRL S or compile. And let's see what happens we get from solidity data location can only be specified for
an array, struct or mapping types. A memory was given arrays structs and mappings are considered special types and solidity. solidity automatically knows where are you in 256 is going to be slowly knows that for this function, a un 256 is going to live just in memory. However, it's not sure what a string is going to be. Strings are actually kind of complicated. Behind the scenes, a string is actually an array of bytes. And since a string is an array, we need to add this memory bit to it because
we need to tell solidity, the data location of arrays structs, or mappings and a string is secretly an array. So that's why we need to tell it it's in memory. You'll notice we can't add the storage keyword here slowly also knows that since this is a function, this name variable isn't actually getting stored anywhere. So it says Hey, you can't have that you need to have it beat memory or called data and those are the only two that it accepts So this is what we want our function to look like here
. So the summary of this is struct mappings and arrays need to be given this memory or called Data keyword when adding them as a parameter to different functions. We'll learn more about storage memory and call data in later sessions. Now, this list is great, but what if we know someone's name, but we don't know their favorite number? Well, what we could do is we could look through the whole array looking for that person. For example, in our contract, we can say, Okay, I'm looking for John. Okay,
let's start with zero. No, okay, that's Patrick. Okay, let's go to one. Okay. That's John. Oh, great. His favorite number 16? Well, this was really easy, because we only had two people. But what if we had hundreds of people in this array? Well, we'd keep have to iterating all the way up to the index that that person was in, it's obviously really inefficient. What's another way to store this information so that it's much easier and quicker to access? Well, another data structure that we can use
is something called a mapping, you can think of a mapping as sort of like a dictionary, it's a set of keys, which each key returning a certain value associated with that key. And we create a mapping variable the exact same way we create all of our other variables. This is going to be a type mapping of string to you and tivity sex, this is going to be our type of visibility keyword is going to be public. And we'll call it name to favorite number. Now we have a dictionary where every single name i
s going to map to a specific number. So let's add some capability to our Add Person function. So we are going to add our people to our array. But let's also add them to our mapping here, what we'll do is we'll say name to favorite number. App key name is going to equal to favorite number. So let's go ahead, compile this. We'll go to our deploy screen, we'll deploy this click, we have a new button named a favorite number. If I type in Patrick, nothing shows up. By typing Patrick, you'll see I get
zero response. By typing John, I also get a zero response. If I type in Becca, I also get a with zero response. When you create a mapping, you initialize everything to its null value, every single possible string on the planet right now is initialized to having a favorite number of zero. So if we want to change that, we'll have to go in and manually add that. So let's go ahead and add a person to our mapping here. So we'll add Patrick. And we'll say my favorite number is seven. And looks like t
hat transaction did go through also add, Becca, and we'll say her favorite number is 13. Let John and we'll say his favorite number is 16. Now, if I look up, Patrick, I'll immediately get back what Patrick's favorite number is, I get seven back. If we look up, John, we immediately get back 16. Back up, we may only get back 13. And we also can see them in our array. Because we kept in this people that push bit zero, we see Patrick's there. At one, we see Becca. And at two, we see John, in our map
ping, we're saying the string name is being mapped to the UN 256 favorite number. And a lot of my variables, I like to make them explicitly named like that. So this is name to favorite number. So now we're in a space where let's say that we really like our simple storage contract. Right now we have a favorite number, a global variable that we can save a favorite number to with our store function, we have a mapping of name to favorite numbers, and we have an array of a new type that we created ca
lled people, we can add to both the array and to the mapping. Using this Add Person function that we've created, we're able to save multiple people's favorite numbers as well as kind of a global favorite number as well. Let's say we really love this contract, and we're ready to send it to a test net to have other people interact with it. Now in future sections, you'll hear me say that you shouldn't do this until you write tests until you do some really simple auditing. But for now, let's go ahea
d and learn how to actually deploy this to a test net or to a real network. Now remember, test nets are run out of the goodness of people's hearts. So if it's a little bit funky, or maybe doesn't work exactly as we show here, that's okay. As long as it works with the JavaScript VM, you'll be all set but it is good practice to learn how to deploy these to a real test net. Let's go ahead and do that. Our contract is here. Simple Storage dot soul. It's compiled, compiling is passing we get this lit
tle green checkmark here we go to the deploy section. Let's go ahead and do Get this. And now we're going to change the environment. So we were working with a JavaScript VM or kind of this fake simulated environment, we want to now move to either injected web three, or web three provider. If you hover over injected web three, there's this really, really small text here. But this basically means we're going to inject our meta mask or our web three wallet into our browser to use similar to what we
did with the faucet, we'll pick our account we want to use. So I'm gonna go ahead and pick account one. And now we actually see our account in the Account section of remix, injected web three means we're using our meta mask or whatever web three wallet, web three provider is, when we a little bit more manually choose an endpoint. And we're not going to go over this right now. But as we get later into the course, you'll understand what this means. So we're picking injected web three, whatever ne
twork are injected web three, or in this case, our wallet is connected to is going to be the network that we deploy to. So for this section, we're going to be deploying to Rinkeby. But again, depending on whatever the recommended test net and the recommended faucet is, that will dictate which test net you should actually deploy to. For us, it's going to be Rigby. To deploy to a test that remember, we're going to need gas, so we're going to need some tested Etherium. Or if you're deploying to a m
ain net main Aetherium, which you shouldn't be come to the top of the GitHub repo to make sure you have the most updated faucet, the other place you can go is link token contracts page in the chain link documentation and scroll down the ranking. And you can see test that link available here, test that eath available here. So this is the other location, you can always look to find the most up to date faucets, and both of them point right back here. So now that we're working with injected web thre
e, we can just go through the exact same steps to deploy to a test net as to deploy to a virtual machine. And remember, if you run out of gas to deploy this, be sure to check back to the faucets to actually deploy this. So we're going to do the same thing, we're gonna go ahead and hit Deploy. But this time Metamask is going to pop up and ask us if we want to actually deploy this, this is the exact same as what we saw with the blockchain example, where we sign transactions, we are signing and sen
ding this transaction, the data of this transaction is this massive, massive data thing here, which represents the contract that we just created, we can see all the payment information for this transaction for deploying this contract, we see it's going to cost around this much Aetherium to deploy. But again, we're on the Rinkeby test network. So this is going to be fake Aetherium. We're gonna go ahead, hit Confirm. And if you pop up a little console, and remix, you'll see that after a slight del
ay, it'll actually say have this green checkmark that it's confirmed that it went actually went through, we can go ahead right click, open a new tab, and view this on ether scan. And after a slight delay, we'll actually be able to see the transaction details here, exactly the same as our transaction details for sending Aetherium we have a hash, we have a status, we have blocked block confirmations, we have timestamp from which is going to be us two, which is going to be the average of the contra
ct that we just created. We didn't send any value with this. So this is going to be zero ether. And then of course, we see the transaction fee, and as well as the gas price. Because again, deploying a contract to the blockchain is modifying the state of the blockchain. So we have to pay gas, and we can see all the different pieces here. As we can see, gas limit and gas usage is much higher than just sending Aetherium, since we are putting a lot of data on chain and adding a lot of computation. S
o this number is much higher than the 21,000 number of just sending Aetherium. Now, if we come back to our remix and scroll down, we're able to see our simple storage contract at this address. If we hit this copy button, and we go to the rink be ether scan, we paste it in the search bar, we will get the contract that we just deployed. And we see this first transaction is going to be the contract creation transaction. So this contract that we just created one transaction, which is contract create
d. So now that we have this contract created, we have all the exact same functions that we saw when working with the JavaScript virtual machine, or the our fake environment, or our super fake environment. Now we can do all the exact same things that we did with the JavaScript VM, but on a real test network. So you'll see if I hit retrieve Metamask doesn't pop up. Because again, this is a blue view function. If we look people at zero, this is also a view function and nothing pops up, named a favo
rite number should be blank. So if I type in Patrick now, absolutely nothing happens, right? I get I get zero returned because mappings initialize every single key with a blank or a null value, which for you 256 is zero. Now, we can go ahead and store a favorite number store When your favorite number is going to modify the blockchain, so our meta mask should pop up for us to confirm the transaction and sign that transaction to modify the blockchain state. So I'm going to store my favorite number
of 16, we'll hit store, meta mask will pop up, and we're going to go ahead and actually confirm this didn't confirm is equivalent to US signing this transaction and sending it to the blockchain to modify the state. So we're gonna go ahead and confirm this, we should be able to view this on ether scan. And again, it might take a little bit for it to actually index or actually start working. So please be patient with these test nets. And again, this is why when building your applications, you wan
t the test net piece to absolutely try to be your last step, because you have to wait a really long time. And it puts a burden on these people running these tests into running it out of the goodness of their heart. So please try to make this the last step of your actual building process. For us learning right here, it's okay. And after a slight delay, once we hit refresh, it looks like it's indexing on ether scan, the ether scan website is still figuring out where the transaction is going to rem
ix, it looks like on the blockchain, this has actually already gone through. So now if we hit retrieve, we do indeed see, our favorite number is 16. Of course, these two are still going to be blank. And it looks like that transaction has gone through and ether scan has indexed. So now let's go ahead and add a person will add Patrick, and my favorite number is going to be 16. We'll go ahead and add person. Again, since these are orange transactions gonna pop up because we're modifying the blockch
ain state, we'll go ahead and hit Confirm. And we're going to be a little bit patient here and wait for this transaction to go through. And we should see this update. And this update. Now if I hit named a favorite number of Patrick, I get 16. And if I hit people of zero, I get favorite number 16. And the name is Patrick. Awesome. So you've actually successfully deployed a contract to an actual test net, and actually seen on ether scan what these transactions look like, you should be incredibly p
roud of yourself, be sure to give yourself a high five pat on the back, send a tweet saying exactly how excited you are. But make sure to celebrate these little wins, celebrating these little wins will give you the motivation to keep going and really excite you for learning each new thing. So huge. Congratulations. If you got this far, you've deployed your first contract to a test net, congratulations. Now if you want to see what it looks like to deploy to a different network, all you need to do
in your Metamask is switch to a different test net. See, if we switch to COVID remix automatically updates and says, ah, injected web three is now the COVID test network. We could switch again maybe to Grilley, we say Ah, the injected web three is now at the Grilley. This is the test net that we'd be deploying to of course, we need actual test net Aetherium to do any deploying, so we wouldn't be able to here. And if we go ahead and hit Deploy right now Metamask pops up. But we get this little r
ed thing saying insufficient funds. Of course, later on, we'll learn how to add new networks like polygon like avalanche like phantom into our Metamask. So we can deploy from any one of them as well. Now, I mentioned this term before, but all this code that we wrote, when we hit this compile button, it compiles it down to the EVM or the Ethereum virtual machine. Don't worry too much about what this means. EVM is a standard of how to deploy smart contracts to Aetherium like blockchains. And any b
lockchain that implements a type of EVM. You can deploy solidity code to some examples of EVM compatible blockchains are going to be avalanche, Phantom, and polygon. Since these are EVM compatible, this means we can write our solidity code, and deploy to these blockchains, which again, I'll show you later on how to add these new networks into your Metamask. And then how to deploy them. Let's do a quick recap of our first smart contract. And then you should actually take a break, maybe get some i
ce cream or coffee because you absolutely deserve it. Congratulations. The first thing you always need to do in your smart contracts is tell solidity, what version of solidity that you're going to be using. And additionally, you want to add an spdx license identifier, then you have to create your contract object and name your contract. The contract in solidity is similar to a class in other programming languages, and everything inside the squiggly brackets is a part of that contract. There are m
any different types in solidity like unsigned integer, 256, Boolean string, bytes, 32, etc. If we want to create a new type, we can create what's called a struct in solidity. You can create arrays or lists in solidity, you can create dictionaries, or what's called mappings in solidity or hash tables, which when you give it a key, it'll spit out the value that that key represents. 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 in pure functions, don't modify by the state of a blockchain, we also can specify different data locations in our functions, called data and memory mean that that data is only temporary and will only exist for the duration of the function. Storage variables are permanent and stay there forever. function parameters can't be stored variables because they're only going to exist for the duration of the function. All the solidity code that we work w
ith, when we hit Compile, it actually compiles down to this Aetherium virtual machine specifications. We'll learn more about those specifications later. And last, but not least, another huge congratulations on your first contract here. Awesome. All right, let's get started on our lesson three, remember, everything is in the GitHub repository. And we can scroll down, hit Lesson three and see all the code here. I'm building up this repo as I film. So underneath this lesson three is going to be a l
ot more information than just the code here, all of our code samples end with dash f f, c, which means dash Free Code Camp. So if you see a GitHub repo that ends with dash F, F, C, know that that repository is associated with this course, I'm going to do a quick high level walkthrough of what we're going to be building in this lesson. So you don't need to code right now just sit back watch and enjoy. In this lesson, we're actually going to expand to having three different contracts. Let's say we
want to be able to deploy simple storage contracts from a contract itself. Yes, contracts can indeed deploy contracts, we are going to create a contract called storage factory dot sole, that's going to be able to deploy and interact with other contracts itself. So what we could do is we could go deploy this to a JavaScript VM, we're going to choose storage factory, and we're gonna go ahead and hit Deploy. In our contract down below, we have a number of different functions. Our top function is t
his function called crate simple storage contract, which we can click and it'll actually create a simple storage contract for us, then we can go ahead and interact with it at an IG zero will save a favorite number of one. Now, if we hit SF get zero, we get one back. And we can see the address of the simple storage contract that we just deployed. Additionally, we're going to learn about a number of solidity features, such as importing inheritance, and so much more. So let's go ahead and jump in.
And remember all the code is available here from the GitHub repository. So be sure to refer back to these contracts if you get lost. So here we are back in remix, and we have our simple storage dot soul. If you skipped over the last section, be sure to go to the full blockchain solidity course, Jas. And scroll down to lesson two, welcome to remix and grab this code. Go to simple storage outsole. And copy paste this code into remix. Because this is where we're going to be starting from, we have t
his simple storage contract, which is great. It allows us to store a favorite number. And it allows us to store favorite numbers across different people in both mappings and arrays. But let's say we want to get even more advanced with this, we actually can have a contract actually deploy other contracts for us. And then go ahead and interact with those contracts from other contracts, contracts interacting with each other is an essential part of working with solidity and working with smart contra
cts. The ability for contracts to seamlessly interact with each other is what's known as composability. smart contracts are composable, because they can easily interact with each other. This is especially awesome when it comes to things like defy where you can have really complex financial products interact with each other incredibly easily, since all their code is available on chain. So we're going to learn how to do that. So let's keep our simple storage contract exactly the way it is, we're g
oing to create a new contract called storage factory. So we're going to hit the New File button and type in storage, factory dot salt. And let's close this off for now. So let's go ahead and get this contract setup from what we learned before. First thing we're going to want to do is the spdx license identifier, which we're going to do MIT. And then the next thing we're always going to need is our solidity version. So we'll do pragma solidity and we could do zero point 8.7. But for this one, let
's do zero point 8.0 And then just add the carrot, meaning any version of 0.8 point something will work. And then let's add our contract name, which is going to be storage factory. Now hit command S or ctrl S or go to the compile tab and hit compile, and boom, we have our regular setup here. Now we want to create a function that can actually deploy our simple storage contract. So we'll create a function called function. create simple storage contract, we'll have it be public, so anybody can call
it will have to deploy a simple storage contract and save it to a global variable. But before we can do it How can our storage factory contract know what our simple storage contract looks like? In order to deploy it, if our storage factory contract is going to deploy simple storage, it's going to need to know code of simple storage. One way we can do this is we can actually go to our simple storage dot soul and copy everything underneath pragma, solidity and down and paste it into our storage f
actory dot soul underneath our pragma, solidity. If we go ahead and compile and save this, it actually works our storage factory, that soul contract actually now has two contracts in it. It has the simple storage contract, and it has the storage factory contract in it, you actually go to the deploy tab and scroll down to deploy while you're on the storage factory dot soul, not the simple storage that's all on storage factory, you can see that you can actually choose which one of these contracts
to deploy, a single file of solidity can hold multiple different contracts. Now that we have our simple storage, that's all in our storage factory, we can actually go ahead and create this function to deploy a simple storage console, we're going to create a global variable the same way that we would create any other global variable, we'll do the type, which is going to be type simple storage contract, we'll give it a visibility of public. And we'll give it a variable name. Type simple storage co
ntract going to be public, the name of the variable is going to be simple storage. Now in our function, create simple storage contract, we're gonna say simple storage equals new, simple storage. This new keyword is how solidity knows Ah, okay, we're going to deploy a new simple storage contract. So we go ahead and compile this, we'll go to the deploy tab, make sure we're on the JavaScript VM, we'll scroll down to the contract. And we'll choose storage factory. And remember, you need to have stor
age factory dot soul selected. In order for that to show up storage factory, we'll go ahead and hit Deploy. And now we see our storage factory contract has two buttons. One is create simple storage, and the other one is going to be a view of our simple storage contract. If we click it right now, it's going to show us that it's currently at address zero, because it gets initialized to being blank. It's saying there is no simple storage contract currently deployed. Now if we pull up our console an
d click create simple storage, we see we created a new function call storage factory dot create simple storage contract. And in doing so we called this function which created and deployed a new simple storage contract, we can now see what address the simple storage contract is out by clicking the simple storage button and we see the address associated with it. So now we know how a contract can actually deploy another contract. But the thing is, having this massive chunk of code above our storage
factory is a little bit redundant, especially since we have our other file called Simple Storage dot soul. And let's say we have a contract that has got a ton of other contracts in it. Always copy pasting all these contracts is going to be a lot of work. So instead, what we can do is use what's called an import. So let's go ahead and delete our contracts simple storage. And now we're just going to type import dot slash simple storage dot soul. This import dot slash simple storage dot Seoul is t
he exact same as our copy pasted version of simple storage. That's all. It takes the path of another file, it takes the path package or GitHub, which we'll get to in a minute of another file and says, Okay, we're going to paste that contract into the top of this contract here, we actually see we go back to compile, we go to deploy, let's delete our old contract, we can actually see storage factory dot soul again, we can deploy it, click the drop down. And once again, we can run those functions e
xactly the same. importing our contracts like this is much nicer than always copy pasting the code. This way, if we want to change something in simple storage, we have one canonical place to go ahead and change it instead of having to change it in multiple different places. Now additionally, you'll notice the pragma, solidity if we have our contracts in two separate files, we actually can have different versions of solidity right now our storage factory has carrot zero point 8.0 Which means that
anything within the 0.8 range of this contract is okay. But for simple storage that sole, it says anything in the zero point 8.8 And above range is okay. So if we were to try to change the compiler version 8.5 And then go ahead and compile, a remix is going to automatically bump it up to a better version that is compatible with both of them, in this case eight point 13. But if we, for example, changed our solidity version of storage factory to zero point 7.0 And then tried to compile them. We a
ctually end up getting an issue parser error source file requires a different compiler version. This is because our storage factory is saying hey, anything in 0.7 means is okay. However, our simple storage is saying anything in the zero point 8.8 And above is okay. So those two versions are not compatible. So what we need to do is we need to make sure our versions of solidity are indeed compatible. So let's change the version back recompile. And now we're looking good again. Now since we have th
is create simple storage contract, every single time we call it right now, it'll just replace whatever is currently in our public simple storage variable. Let's go ahead and update this so that we can actually keep a running list of all of our deployed simple storage contracts. So instead of having this be a single variable, we'll make this a simple storage array or list public simple storage array. Now, whenever we create a new simple storage contract, instead of saving it like this, what we're
going to do is we're going to save it as a memory variable by saying simple storage, simple storage equals new simple storage. And we're going to add this variable to our simple storage array. So the same way we did it before, we're gonna do simple storage array dot push, simple storage. So I should spell storage, right? Let's go ahead and compile this looks good. We'll deploy the storage factory deploy. Like here, we now have simple storage array View button, we'll do create simple storage. No
w we can view the simple storage contract zero. Right now there's nothing at one. But if we create another simple storage contract, we can see the new simple storage contract address at index one. All right, so this is great, we can now keep track of all of our simple storage deployments. But how do we actually interact with them, let's say we wanted to be able to call the store function on all of our simple storage dot souls from our storage factory, you can think of the storage factory as almo
st like a manager of all of our simple storages. That's all let's create a new function that can do exactly that. So we'll create function, and we'll call it S F store, which is going to stand for storage factory store. And it's going to take you in 256, simple storage index, and a UNT 256, underscore simple storage number. There'll be a public auction as well. Now in order for you to interact with any contract, you're always going to need two things. And we're going to refer to this a lot. You'
re always going to need the address of the contract, and the ABI of the contract. The API stands for Application binary interface, the API will tell our code exactly how it can interact with the contract, we'll go deeper into API as we move on. But if you go to your compile tab, you hit compile, and things are actually compiling. You can scroll down, and you can see compilation details. And you can see a whole bunch of information on your different contracts. You can see the name of your contrac
t, which for our simple storage contract is simple storage, you can see a whole bunch of metadata, like the compiler, the language output settings, all this other stuff. You can see the exact bytecode and the opcodes, which we'll talk about much later. But you can also see this API, this API tells you all the different inputs and outputs and everything you could do with this contract. For example, in our simple storage, if we look at the zero with index of our API, we have a function add person.
If we look at one, we see our name to favorite number, we looked at two we can see our people three retrieve for store, it tells us all these different ways we can actually interact with our contract. And the different functions that we can call, we know where addresses are, because we're storing them in this array here, our simple storage array, we can also get the API because we're importing simple storage dot soul when you compile simple storage on soul. As you saw on the compilation details
, whenever you compile it, it comes prepackaged with the ABI, we automatically get the ABI just by importing it like this. In the future, we'll see other ways that we can actually get API's really easily. So to call the store function on one of our contracts, we're first going to need to get that contract object. So what we can do is we can say simple storage variable named simple storage. Variable Name simple storage of type simple storage is going to be equal to a simple storage object. And in
stead of doing new simple storage, like we did last time, we're just going to put the address of this simple storage object in here, which again, we can get from our array. And in this function, we're passing the array index. So we can say simple storage contract at address simple storage array. At index simple Storage index. This bracket notation here is how you access different elements of arrays. So if we want the zeroeth element of our list here, simple storage index would be zero, and we pa
ss it into this bit here, then that'll give us the address of our simple storage contract, which we pass into simple storage here. Since this is an array of simple storage contracts, we can just access that simple storage contract using the index. So we would say, simple store, Edge array at index underscore simple storage index. Now we're saving the contract object at index simple storage index to our simple storage variable. Our array here is keeping track of the addresses for us. And it autom
atically comes with the ABI is here. If this was just an array of addresses of the contract objects, instead, we would have to wrap the address in a simple storage object like this. But we'll get to that much later. So for now, all we have to do is this and we now have a simple storage contract object. Now that we have it, we can call our store function on the simple storage contract. So we'll call simple storage dot store. And we'll store the simple storage number to it. So this is perfect. And
if we were to deploy this right now, though, we wouldn't be able to read the store function. So let's create another function that can read from the simple storage contract from the storage factory. So we'll create a function called S F get, which stands for storage factory get, it'll take a un 256 underscore simple storage index. This will be a public view function, since we're just going to be reading from our simple storage contract. And it's going to return a UNT 256. And we'll say simple s
torage. Simple Storage. Equals when you use this same syntax from up here to get the contract simple storage array at the simple storage index. And then we're going to do return, simple storage.re retrieve to get that number that we just stored up here. And I should spell retrieved correctly, so we get no issues. Perfect. So now we'll compile, we'll deploy JAVA script, we're working on a fake account, we're going to use our storage factory, go ahead and delete all the contracts we have so far. L
et's go ahead and deploy the drop down rate. Right now if we do SF get at zero, we're going to get nothing. Simple Storage address zero is going to be nothing. Let's create a simple storage contract. Now it's simple storage list, we get an address at zero. If we hit SF get right now it didn't zero, we get zero. So let's store a value on this contract here. So the index of that contract is zero. So we're going to pass zero as a symbol storage index. And we're going to save the number seven. So we
'll go ahead and do SF store. And if we did this, right, this is going to store the value seven into this contract. So if we do SF get of zero now, it does indeed return seven. If we do SF get one we're going to get nothing's going to happen. And we're actually going to get this revert error here. So let's create another simple storage contract. Now if we do SF get one, we get zero, because we're gonna get that default value. Let's go ahead on the simple storage contract and index one will store
the number 16 will hit SF store. Now we'll do SF get one and we get 16. Feel free to pause right now and play around with this so that you really understand it. The quick recap is our storage factory contract allows us to create simple storage contracts, it then saves it to our simple storage array, which we can then call different functions on, we can store values from our storage factory contract. And then we can read values from our storage factory contract for any of the simple storage cont
racts that we've created. This is incredibly powerful, we can additionally make these two functions even easier. We can call the Retrieve function directly on this when we call simple storage array. And then we have these brackets and add the simple storage index. This returns a simple storage object. So what we could do is we could actually delete this whole part and just do dot retrieve right here, and then delete this line and say return and just have it be just like this. If you go ahead and
save or hit Compile, you'll get the green checkmark there. We're calling the Retrieve function on whatever this is. And whatever this is, is a simple storage object. So perfect. We can do the same thing up here by deleting this part and just doing dot store, underscore simple store edge number, we save it. And this will work exactly the same. Awesome, we now have a simple storage contract that can store variables in a storage factory contract that can be almost like a manager of these simple st
orage contracts and deploy and interact with them themselves. This is fantastic. Now, let's say that we really liked the simple storage contract, but it doesn't do everything that we want it to do. Maybe we want it so that whenever we actually store value doesn't store the favorite number, it stores the favorite number plus five, for some reason you want a contract that that everyone's favorite number is five numbers bigger than what they think it is. But you really like everything else that thi
s contract has to offer. Let's create this new contract. And we'll call it extra storage. So we'll say extra storage dot soul. And we'll create this new contract, we're going to set it up the exact same way we normally would spdx license identifier, gonna be MIT, we'll give it pragma solidity. And we'll just do zero point 8.0 with the carrot. And we'll say contract, extra storage, like so if you save or compile, you'll get the green checkmark. So what can we do? Well, the first thing we could do
is we could copy paste all this code back into here, and then modify our extra storage contract as we see fit. This seems a little bit redundant. And a lot of work though. So what's another way we can actually get our extra storage contract to be like our simple storage contract? Well, this is where we can do something called inheritance, we can have our extra storage contract, do what's called a child contract of our simple storage contract. And we can have extra storage, inherit all the funct
ionality of simple storage with two lines of code. So first, in order for our extra storage contract to know about simple storage, we once again need to import it. So we'll say import dot slash, simple storage dot soul. And we'll say our contract extra storage is simple storage. And we save or compile. Now our extra storage contract is going to be the exact same as simple storage. And it's going to do what's called inherit all the functionality of simple storage. And we can actually even see tha
t, let's go ahead and make sure this is compiled. And we'll go and deploy this. And now in our deployed contract, we can see we have extra storage deployed with all the functions that simple storage has, if you want a contract to inherit all the functionality of another contract, you can just import it and say your contract is that other contract. Now, we can add additional functions to our extra storage contract. That will include all the functionality of simple storage. Now, let's say that we
inherit simple storage to extra storage. However, one of the functions in simple storage we don't really actually like. So if we go back to our simple storage contract, our store function, all it does is take a favorite number, and then assigns the global favorite number to whatever new number that we give it in our extra storage. We want the store function to do something different. We want it to add five, to any number that we give it. How can we achieve this? Well, we can do something called
overriding the functions. And there are two keywords that we're going to use. Those are virtual, and override. Right now, if I were to try to implement a store function for extra storage, let's see what happens. We'll say function store, you went to the six favorite number. There'll be a public function. And let's say instead of just storing favorite number, we'll say favorite number equals favorite number, plus five. If we try to compile this right now, we'll actually run into two different err
ors. First one is going to say overriding function is missing, override specifier. If the parent contract, which in our case is simple storage has that same function, we need to tell solidity that we're going to override this store function and instead we're going to use this store function. But additionally, we get this other error saying trying to override non virtual function. Did you forget to add virtual in order for a function to be overridable you need to add the virtual keyword to the st
ore function. Now it can be overridable. However, if we save and compile, we still have this issue overriding function is missing override specifier. And then all we need to do is add override to restore function. Now if we save everything compiles correctly, let's go ahead and deploy this. Let's delete our old contracts. JavaScript VM right account. Great we're going to choose extra store Reg, let's go ahead and deploy. And here's our extra storage contract. Right now if we retrieve, we get zer
o. Previously, our store function would store the exact number. However, if I were to store five, it'll store five, plus five. So we should have 10 stored here. Let's go ahead call store looks like that one through, and we'll hit retrieved now. And we do indeed see 10 is in here. So this is how we do inheritance, and we override functions. And that's it. For this section, you've just learned a ton of incredibly powerful solidity for having multiple files. Let's do a quick overview of what we lea
rned, we learned that we can actually deploy contracts from other contracts using the new keyword, we learned that we can actually import other contracts into our contracts and into our code using the Import keyword. And the import keyword is the same as copying pasting that file to the location of the import line, we learned that we can interact with other contracts. As long as we have the ABI and address. We didn't learn too much about the ABI. But we'll learn more later, we learned that if we
want to create a child contract and inherit the functionality of some other contract, we can do something called inheritance. And the way to inherit functionality is using the is keyword and saying our contract is some other contract. However, if we want to change from the functionality of the parent contract, we have to override that function. And additionally, we have to set the function we want to override to virtual now we can have our own store function, do whatever we want it to do. That
is the end of this lesson. Once again, give yourself a huge round of applause a pat on the back for making it this far. And for finishing this section. You're getting more and more advanced facility so quickly, so be sure to celebrate the little wins by getting some ice cream, maybe going for a walk or tweeting about or posting on Reddit. Congratulations, you have completed this section. All right, everybody. Welcome back. We are now headed into Lesson four remix Funmi. And of course, all the co
de can be found on the GitHub repository associated with this course. We're going to be working with two contracts here, one of them is fundament outsole. And then one of them is price converted outsole Funmi dot Sol is going to be a contract that allows people to actually fund a collective good. So people can send Aetherium send Aetherium, or polygon or Avalanche or Phantom, or whatever blockchain native token into this contract, and some owner of the contract can then withdraw those funds and
do whatever they want. After deploying this to a test net, we can see the list of functions this contract has, this will have two red buttons, which are used to notate to payable functions in fund in our fund function. And in our withdrawal function, withdraw allows users to withdraw the funding and fund allows users to send money to the contract, what we can do is we can send some value along with our transaction. When we call this fund function, then what we can do is we can actually fund this
contract with a certain amount of eath, or way by pasting some value into the way value section. And then hitting fund, we will now have sent money into our deployed contract. And we can see a list of the funders and a mapping of those addresses and how much they've actually sent into the contract, we can then withdraw the funds out of the contract. With a special exception with only the person who deployed this contract can actually withdraw the funds back out. Once the funds are withdrawn, th
e amount of all the funds is reset back to zero. Are you excited? Well, you should be. And if you've finished the section, you've completed most of the basics of solidity, and you'll be ready to start making even more powerful smart contracts, we'll be using channeling price feeds to actually set the value of how much these people should be able to fund in USD as opposed to just in terms of ether, we're gonna go over a lot of advanced sections here. And I'll let you know what parts might be a li
ttle bit harder to digest. So you don't have to spend your entire time trying to figure out exactly what's going on. Be sure to use the GitHub repo to your advantage here and the discussions tab to stay connected with other people taking this lesson. Alright, let's jump in. So at this point, in remix, you'll have a couple of contracts here, simple storage, storage, factory extra storage, maybe you refreshed remix, and these have gone away. And in the case, make sure that you just don't have any
of those tabs open, we're going to create a new contract called funding. So let's go ahead and start creating our funding contract. Again, we want it to be able to get funds from users and withdraw funds and set a minimum funding value in USD. This is what we're going to get our contract to do. So first, let's set it up spdx license I tend to fire MIT do pragma solidity do caret zero point 8.8. And we'll do contract bunbee. Awesome. And we'll compile, see if things look good. And they do. Great.
Let's keep going. So before we actually embark on creating all of our functions here, let's just add the different functions that we're going to implement. So we want a function fund for people to actually send money to, we want a function withdraw, or the owner of this contract to actually withdraw the funds that different funders actually give us. And that's pretty much it. These are the two main functions that we want this contract to do, we will be implementing more functions to help facili
tate these two functions. But let's get started by looking at fund. let's comment out withdrawal for now. And let's just start with fun. So we want anybody to be able to call this fun function. So we'll make this public. So as we mentioned, we want to be able to set a minimum font amount in USD. So there's a lot of things to think about here. First thing we probably want to think about is how do we send eath to this contract, whenever we create a transaction on the on any of these EVM blockchain
s, there's this value field that we can set value represents how much Aetherium we're going to be sending with our transactions. For example, when we transferred Aetherium. between our different accounts, we were actually populating this value parameter with different amounts of Aetherium. In fact, every single transaction that we send, will have these fields, it'll have a nonce or the transaction count the account the gas price, the gas limit that we've seen on ether scan a to aka the address t
hat the transaction is sent to a value which is going to be this amount that we're talking about. They'll also have data which is going to be what we send if we make a function call or deploy contract, and then we'll have this v r s components. We're not really going to go over these v r and s because this is that cryptographic magic that's happening when a transaction is signed, but just know that that's it Now, for sending value, we can populate some of these fields, the gas limit, for example
, was 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 call a function and send a value at the same time in remix has a little drop down here for way way Feeny and ether, we're gonna ignore Feeny for now. But of course, we have our way, great and ether. Again, we're one ether is worth this much way. And this much way, the first
thing we need to do in order to make a function payable with Aetherium, or any other native blockchain currency is we need to mark the function as payable. It's this payable keyword that makes our font function red, as opposed to having it normal orange, just like how our wallet can hold funds, contract addresses can hold funds as well, since every time you deploy a contract, they get a contract address, it's nearly the exact same as a wallet address. So both wallets and contracts can hold nativ
e blockchain token like Aetherium. And you'll see that when we deploy this later on in the lesson, that actually will gain a balance of Aetherium. Now that we have it payable, we can access this value attribute by using one of the global keywords in solidity with message dot value to get how much value somebody is sending. You use message dot value in your function. Now let's say we want to set our message add value to a certain value of Aetherium. Let's say we wanted it to be let's say we wante
d people to send at least one whole ether with all the transactions. Or put another way, if they sent Aetherium, they would need to send at least one Aetherium. How would we implement that? Well, we could do something called require, we would say we want to require the message dot value is greater than one e 18. There's a couple of things to unpack here. One, e 18 is equal to one times 10 raised to the 18th, which is also equal to 112345 678-910-1234 5678. This is the value in way of one Aetheri
um this much way is one eath. So if we wanted the message dot value to be at least one eath, or one polygon or whatever ranch etc, we would set it like this require message on value is greater than one. This require keyword is a checker it says hey, is message dot value greater than one. If not, it's going to revert, it's going to do what's called revert with an error message. And we can say didn't send enough, we're gonna try deploying this on a JavaScript VM, deploy Funmi, we'll hit Deploy, lo
ok at Funmi we see this fun button is now red. If we call Funmi right now, and we look at the console, you can see we actually get an error here, call it again, we get an error, we get an error here, we know that the air is going to be this didn't send enough. So what we need to do is we need to send at least one ether with this fun transaction, in order for this require statement to be fulfilled. So back up in the value section, we can change this value to one. So that's gonna be one ether, or
this much way or this much way. Now we can hit fund oh actually needs to be greater than one. So let's send to for example. Now we'll scroll down. And now we'll hit fund. And we see that that actually passes the require statement says if our first section is false, then go ahead and revert with this error. What is reverting? Revert can be a little bit confusing, so I wouldn't let this section hold you back. If it's a little bit confusing. Revert is when it undos any actions that happened before
and send the remaining gas back. So what does that actually look like? Well, let's say for example, we had a un 256. Public number. And in our fund function, we said number equals five. If we were to go ahead and deploy this, let's delete our old contract. deployed this new contract or number right now is zero. But if we were to call our fund function number gets set to five. However, if we call a fund and this require isn't met, this transaction would revert an undue setting number to five. So
let's go ahead and look at our logs here. We'll keep value zero so that our fun function reverts. We'll call fund will see that this transaction failed because this require end up reverting and number is still zero. So then the question becomes, did we actually spend gas Yes, we spent gas to change number to five and then any remaining gas we would get returned by this require for example, if we had a ton of computation here, it On a computation here, we would have need to send a ton of gas with
our fun function. But all the extra gas that we send, after this require gets returned the original user after it gets reverted right here, if reverts are a little bit confusing for you here, don't worry too much about it, we'll go over it in future modules. All you need to know right now is that when you do a require statement, if this first section isn't met, the transaction will be canceled, and any prior work will be undone, and it'll send an error message. Cool. Let's delete this number fo
r now. And we'll delete it from the global scope. There's actually another way to do these reverts, which we'll go over later in this contract. So what we've done so far is great. However, we're checking message dot value in terms of Aetherium, we're looking for one whole Aetherium instead of $50, we want to check that message add value is greater than some number like $50. Let's go ahead and first set the minimum USD value we want people to send along with the fund function, we can do that at t
he top of our contract, we can say you went to 56 public minimum USD equals 50. Now we have some place to check for minimum USD, we're going to update this minimum USD to make it more gas efficient and a little bit. Now that we've set our minimum USD, we want to be able to require the message that value is greater than or let's say greater than or equal to the minimum USD. But minimum USD is in terms of USD and value is in terms of Aetherium. So how do we convert Aetherium to USD, this is where
Oracle's and chainlink are going to come into play. The USD value of Aetherium is something that we've assigned outside of the blockchain to Aetherium, or any other layer one currency or any other native smart contract platform currency. So in order to get this value that is outside the blockchain, we have to use a decentralized Oracle network to get the price of one ether in terms of USD. So before we can continue on here, let's learn a little bit more about the architecture of these decentrali
zed Oracle networks and the different solutions that they have. So that we can create this Funmi contract in the most advanced way possible, 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 Aetherium 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 returned 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. So this is where chainlink and blockchain, Oracle's come into place. A blockchain Oracle is going to be any device that interacts with the often world to provid
e external data or computation to smart contracts. However, the whole story doesn't even in there. If we use a centralized Oracle, we are reintroducing 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, 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 combined on chain and off chain to make incredibly feature rich, powerful applications. chain link is a modular, decentralized Oracle networ
k 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 Oracle's to do this, and then in t
he transaction, this network of nodes will work Turn the data to our smart contracts for us. Now chainlink networks can be completely customized to bring any data or any external computation that you want. However, doing the customization can be a little bit extra work, there are a ton of chainlink 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 channeling data feeds, a
nd that's the one we're actually going to be using for application here. Channeling data feeds currently at the time of recording are powering over $50 billion. In the defy 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 like notes, 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 pricing information to power their defy application, we can see an example. We can see an example at data dot chain dot link. And you can change networks, you can change price feeds, you can change a whole bunch of different information to see some of those popular price feeds. Let's look at eath USD for example. On eath USD, we can see this
whole network of independent chain link node operators that are each getting different answers for the price of eth 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 4.5 deviation threshold or a few hour heartbeat, whichever one 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 Oracle's. 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 deliv
ering 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 your chain
link 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 Avi, with several billion dollars each, we can take a look at an example over at Doc's dot chain dot link work with EVM contracts, we're going to hit EVM chains, scroll down to data feeds.
We'll scroll down to the solidity section. And we can see an example of an entire contract that uses and reads from one of these trending price feeds. We can even open this up and remix and work with it and remix. It looks like this example is reading from a price feed on COVID. 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. Just to show you exactly how this works out. Once we get deeper into the course, w
e'll show you how to actually run tests and work with chain link 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 firsthand how this actually works. So let's go ahead and faucets dot chain dot link slash COVID. We're going to switch to the COVID network, we're going to get some COVID eath. But remember, look at the network flag and use whatever network is in the document
ation. So to get some COVID, we're going to come to the faucet, we're going to turn off test link, we'll just stay with eath I'm not a robot, and then send request. Once our COVID Aetherium has reached our wallet, we can go ahead and close we can take a look in our wallet and see that we do indeed have 0.1 eath on Kelvin. Now let's go back to our remix, we'll compile this contract, go and deploy this on injected web three. And again, the reason we're going to use injected web three instead of Ja
vaScript 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 V three, and we'll hit Deploy and a mass 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 Aetherium 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 Aetherium 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. It's also in the documentation. However, I know that this one has eight decimals. So this is saying the value of Aetherium right now is $3,262. It may of course be different when you g
o ahead and try this. Now there's a number of things that happened in this contract that I'll explain in our Funmi 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 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 addresse
s section of the documentation, choose the network that you want, and then scroll down and look some of the different addresses of the different price feeds. For example, this address will give you the price of one inch token in terms of Aetherium. 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 channeling VRF or channeling verifiable random dysfunction. 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 to wait to get a provably random number by looking outside of the blockchain and Oracle's are perfectly positioned to do exactly that. chainlink verifiable randomness function is a way to get provably a random nu
mber into our smart contract to guarantee fairness and guarantee randomness of applications. Many protocols like pool together x infinity, ether cards, avocado cheese and more use channeling VRF for lotteries, randomizing NF T's for gaming and for more, we're going to do an example of channeling 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 go into Doc's chain link EVM chains, and scroll down
to get a random number. And this will teach you how to get a provably random number into your applications. The next decentralized out of the box feature of chain link is chain like keepers, which is decentralized event driven execution. As we'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 sun. But 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. Channeling keepers are the solution to this channeling 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 acid hits some number, or maybe a liquidity pool is at a certain level, whatever event that you want to code, you absolutely can th
e chain link 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 keepers 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 Doc's touching that link slash Aetherium. Going and go to making compatible contr
acts and feel free to read the documentation. Try it out yourself. The last out of the box 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 making HTTP GET HTTP POST request is an easy way to customize our chain link nodes to be able to do anything. Remember how we talked about making
API calls that blockchain nodes themselves can do that? Well, chain link nodes can do that chain link nodes can make direct requests to any API that you specify. In order to do this, you both have to choose the chain link node and the URL slash data to send the request to this is a little bit trickier than chain link VRF keepers or price feeds because you then have to be responsible for creating the chain link network that gets data from many different chain link nodes and many different data p
roviders. But let's look at an example in remix anyways. For this section, feel free to just watch it since we are working with a test net here. And test nets, as we've seen, can take a little bit of time. As long as you're familiar with what this process looks like. That's good enough. You don't actually have to try it if you don't want to. So we'll open up and remix will read through. It looks like this example is on the COVID network. So we'll go ahead and compile API consumer. We're gonna go
ahead and deploy on the injected web three, we're going to make sure that we're back on the COVID test network. We're going to scroll down. And we're going to change the contract to the API consumer. And we're going to go ahead and hit Deploy, we're going to deploy this contract to the COVID. Test net. And now we can call this function called Request volume data to actually make an API call. Now, like I mentioned before, whenever we request data from a chain link node, we have to pay a little b
it of Oracle gas, or link token, in order to pay some link token, we're going to need to have link token in our API consumer contract. This is what's known as the basic request and receive model to get link token, we go back to our faucet, and this time, we'll select 10 test link for our contract. Let's go ahead and verify that we're human. And we'll hit Send Request. This time, instead of sending us Aetherium. They're sending us 10 test link, which is what's known as an ERC 20 token. Or more ac
curately, in ERC 677 We'll get to understanding that a little bit later, we can see the asset in our Metamask. By importing the token, in order to get the token, we're going to come back to the documentation. And we're going to look up link token contracts like that, we're going to go to the network that we just got the tokens on, which for us was COVID. We're going to copy this address, we're gonna go to Metamask, hit import tokens, paste that address, and hit add custom token, and then import
tokens. And now we can see in our account one, we both have Aetherium and 10. Link, now that we have our link or Oracle gas, we're going to send it to our API consumer, we're going to copy the address of the API consumer, open up our meta mask, we're gonna hit send, paste the address of our contract, switch the asset to link. For now we'll just send 0.2 link. We'll hit next, next. And we'll hit Confirm. And we'll wait for this transaction to go through. I chose 0.2 Link, because in this contract
, there's a fee character, which tells us how much making an API call for this is going to cost. This one is actually 0.1 link, I send 0.2. Just in case, we want to make that API call twice. Everything that's going on in this function will explain in a little bit later section. But for now, I just want to show you what it looks like to do is, once we send the link to our contract, we can first check to see what the volume is volume is zero, we want to get the volume of the last 24 hours of Aethe
rium asset, we're going to be calling this API which has a ton of raw data, including one in specific called volume over the last 24 hours, which can be this number right here. Say we wanted to get this into our contract from this API, we're going to make an HTTP GET call to this API. And what's going to happen is we're going to make the request in one transaction. And in a second transaction, the chain link node is gonna return the value and store it in this volume variable in the global scope.
So let's go ahead and hit request volume data Metamask gonna pop up, we're going to go ahead and hit Confirm. And you'll notice right away volume doesn't update. This is again, because we actually need to wait two transactions, we're sending a transaction for the request. And then in a second transaction, the chain link node is actually going to respond. And after a slight delay, the chain link node has indeed responded with the result of making that API call back to our contract. We'll go over
this process a little bit more in depth in later sections. The reason that I wanted to show you specifically the API calls, is because we're going to show you a real life example of how to use chain link VRF and chain the keepers in a later lesson. Now I know we've already gone over a ton. So let's do a quick review. In order to send Aetherium or whatever native blockchain token with a function need to mark it as payable. If you need something in your contract to happen, and you want the whole
transaction to fail. If that doesn't happen, you can use a require statement. To get the Aetherium or native blockchain token value of a transaction, you can use the global keyword message dot value. chain link is a technology for getting external data and doing external computation in a decentralized context for our smart contracts. Channeling data feeds or price feeds are ways to read pricing information or other pieces of data from the real world that's already aggregated and decentralized fo
r us, channeling VRF is a way to get provably random numbers from the real world into our smart contracts. Channeling keepers are a way to do decentralized event driven computation. We can set some trigger say if this trigger hits do something and we get to define what the trigger is and what to do something is channeling any API's is the ultimate customization of channeling nodes and allows us to connect to anything on the planet. To make this one production ready. We have to do the most work b
ecause it doesn't come already with a decentralized Oracle network, like chaining the keepers and price feeds. We'll learn more about these channeling services as we continue in this course. Now in order for us to figure out if our message dot value is actually greater than the minimum USD that we set, we actually have to convert our message dot value from its layer one slash Aetherium to the USD equivalent. So how are we actually going to do that? Well, first, we're gonna need to get the price
of Aetherium, or Phantom, or Avalanche or whatever layer, one blockchain that we're working with. So let's create a function to get that price to get that conversion rate. So we'll do function, get price, and this is going to be the function that we use to get the price of the room in terms of USD, so we can convert our message dot value to USD. And then we're also going to do a function called Get conversion rate. These are both going to be public functions, so that we can go ahead and call the
m and test them and do whatever we want with them. So in order to get the price, we're going to have to use one of these chain link data feeds to get the pricing information. And we can look right here at this contract to see what using one of these channeling price feeds looks like. What we're actually doing when we're interacting with this channeling price feed is we're actually reading from one of these contracts, there's a contract out there called the aggregator contract that has a function
called latest round data, which returns a whole bunch of data. But namely, this int price. And this in price is what we are interested in. Let's look at our get price function and figure out how do we actually call this since this is an instance of us interacting with a contract outside of our project, we're going to need two things. What are those two things, we're going to need the ABI of the contract, and also the address of the contract. So the address of the contract is going to be easy, w
e can get the address of the contract from the contract address this section of the chain link data feeds. Let's scroll on down to bank B. And we can find the eath USD address on Rigby and we'll create this contract so that it works on Rinkeby. So we're going to grab this address, we're going to copy it. And we're going to move back to our to our code here. And we're going to paste the address here. So great, we have the address. Now we have the address of the other contract that we don't want t
o interact. Now, how do we get the ABI? Well, what we did before was simple storage was we imported the entire contract into our code here. That's something that we could do. But that's actually a lot of code. So what's something that we could do instead, remember, if we're looking at remix, and we look at one of the contracts that we compiled before, the ABI is really just kind of this list of the different functions and interactions you can have with a contract. The ABI itself doesn't actually
need to include any of the logic, it just needs to include, hey, here are the different functions that you can call, for example, in this contract, we can call fund, we have get conversion rate, we have get price, they're not implemented yet, but they will be eventually now there technically is another way to interact with contracts without the API. But for now, we're just going to ignore that. So how can we get the API, there's a concept in solidity called an interface. And let's look at an ex
ample of an interface. If we go to github.com/smart, contract kits, chainlink, we can see a number of different contracts in the chainlink repository, we can go to contracts, src, V 0.8, interfaces, and we'll go to aggregator v3 interface, dot soul. And if we look at the solidity in here, we can see a whole bunch of function declarations, but none of the logic is actually implemented in this. This is what's known as an interface. If we compile this, we'll actually get the ABI of a contract, beca
use it defines all the different ways we can interact with the contract. It doesn't actually say, what these functions do, which is fine, though, because we don't need to know what the functions actually do, those are going to be stored in the contract. So what we can do is we can grab this interface from the code and paste it into our remix. Now hold on, if you're following along, you don't have to copy paste this with me, because I'm going to show you an easier way in just a second. So for now
, feel free to go ahead and just watch. But once we have this interface aggregator v3 interface, we can now use this to make API calls. So now we could say, aggregator v3 interface at this address. And the combination of these two, give us that aggregator v3 contract with whatever code is here. If at this contract address is aggregator v3 interfaces valid, we can do something like dot version. Let's look at this interface. Is there a version function? There sure is. So that means we can call the
version function on this contract. So let's actually go ahead and copy this into a different section. I'm going to create a new function called Get version just to illustrate this. I'm going to be public. It's going to be a view and it's going to return the UN 256 and We're gonna split it up into two steps here. We're gonna say aggregate tour, v3 interface, price feed. So we're creating a variable of type aggregator v3 interface equals aggregator v3 interface at this address. And then we're goi
ng to return price feed that version. Now I'm going to go ahead and deploy this contract to Rigby just to show you what this git version is going to return. But you don't have to follow along here if you don't want because again, we're working with the test net, you can just watch if you'd like for this section, we're going to test a little bit more sparse. Since we're going to be mainly using the test net, since we're going to be working with an actual chain link Oracle network, once you move o
ver to hard hat, and with JavaScript, all this testing locally will be a lot easier and a lot faster, you're more than welcome to go ahead and fiddle and try and test a lot of this stuff as we go along. But just know that it might take a little bit longer to do some of the testing on the test net, let's delete that last funding contract, we're going to deploy this one, we're going to scroll up, we're going to switch to injected web three, we're going to switch from COVID to rink B. And the reaso
n we want to make sure we're on rink beam is because this address is specific to rink B, the contract that we're looking to interact with might not be at this address on every single chain, we want to make sure we're on the rink B chain for this, because of some other contract is there on the different chain, this version function obviously won't exist, and this function could error. So let's go ahead, we're gonna find me, we're going to deploy this to the rink V chain. Again, you don't have to
follow along with me here, you can just watch. And once that contract has been deployed, we now have a view function called Get version. And we can see it's returning the variable for showing us that this is the fourth version of a price feed. So this is a really easy way for us to interact with contracts that exist. Outside of our project, we use one of these interfaces, which can get compiled down to the API, and then combine that ABI with the address to call a function. As we work with these
interfaces more and more, they'll start to make more and more sense. So if it's a little confusing to you right now, don't get discouraged, the more you work with it, the easier it will become. Now, though, now that we know how to call these functions in here, we can start working with this interface. However, as you know, if we have a whole bunch of interfaces, we're gonna have to stick a whole bunch of interfaces at the top of our code, which looks pretty ugly. What's a better way for us to do
this? Well, before we used import, right, we imported from simple storage. That's all for this one, what we could do is we could import from an array gay Tore v3 interface. That's all, we can go ahead and create a new contract with this aggregator v3 interface. Or what we can do is we can import this directly from GitHub. If we go back to the documentation of these chainlink data feeds go to using data feeds, we scroll down, we see at the top, we have this import statement, import at chain link
slash contracts slash SFC visa right interfaces aggregator v3 interface, this, this import is has the same path setup as the GitHub repository for the chain link code, instead of us directly adding all the code right into our remix, what we can do instead is we can import directly from GitHub, or what's called an NPM package. Remix is smart enough to know that at chain link slash contracts, is referring to the NPM package at chain link slash contracts, we'll talk about NPM, a little bit in the
future, it's what's known as a package manager, and can keep versions of different contracts for us to directly import into our code bases at chain link slash contracts is created directly from the chainlink GitHub repository. So remix downloads this code from NPM, which is created from this GitHub. So now we know that if we import at chain link slash contracts, src, V 0.8 interfaces aggregator v3 interface dot soul, this is the same as if we had just stuck this whole contract right at the top o
f our funding contract, which makes our code look a lot nicer. And now we have this aggregator v3 interface that we can work with. Okay, great. So now that we have a minimalistic interface, which will give us the API, how do we actually go ahead and get the price here? Well, documentation has a good example, if you want to play with it and try to reverse engineer it as well. Here's how we're going to do it. In our code. We're going to create an aggregator v3 interface object called price feed an
aggregator v3 variable called price feed, which is going to equal to aggregator v3 interface contract at address this address exactly the same as what we're doing down here. We're assuming a contract at this address is going to have all the functionality of this aggregator v3 interface, which again, means it has this decimals function, this description function version, get round data. And the important one latest round data, which has the latest price at this answer piece, what we can do now i
s we can call that latest round data function on the price feed. So we'll say price feed dot latest round data. Now if we look at the interface, we see that this latest round data actually doesn't return one variable, it returns a whole bunch of different variables. And that's what we're going to return in our contract. So we're going to put these parentheses, and we're going to say, you went at round ID, we can even look right at the documentation to see what else it returns int price, you went
, you went started out, you went timestamp. And then you went ad, answered and round. Now there's a lot of code here. Since this function returns so many different variables, we have to set something up to capture them. However, all we care about is price. We don't care about round Id started at timestamp or answered in round. So what we can do is just remove them and just leave the commas. Now we have int price equals price feed that latest round data. The reason that price is an int 256. And n
ot a un 256 is because some prices or some data feeds could be negative here, so that it's an int 256. So it can stay flexible. Now that we have the price, this is going to be price of eath in terms of USD. And we saw an example of this before, it was around 3000. And it returned this number because solidity doesn't work with decimals for a number of reasons. But we just need to know that there are eight decimal places associated with this price feed. If you want to double check how many decimal
s there are, this contract has a decimal function that you can call as well, that will tell you exactly how many decimals are in this price feed. Now as we know, message dot value is going to have 18 decimal places. Why does it have 18 decimal places? Well, because one ether is equal to 1-234-567-8910 12345678 Is this massive number in way which has 18 zeros, which is equivalent to 1.12345 678-910-1234 5678. So we want these to have the same decimal places, right? Because right now this has eigh
t, this is 18. They're different units right now. So to get them to match up, all we need to do is return price times one, ie 10, or one raised to the 10th, which is equal to 1123456789 10. Message dot value, though, is going to be a UNT 256. And right now, price is an interval at six. So why did we convert this value from n into 56. To a human to 56? Well, we can do what's called typecasting, all we need to do is add you into 56. And wrap this whole thing up between these two parentheses, you c
an't typecast anything. But there are some values like into 56 and you into 56, that can be easily converted between the two. Now of course, since we're not modifying any state with this get price function, we can make this view and say it returns that you went to 36. And if we save and compile, we go ahead and we get that checkmark. Now math can be a little bit tricky. The first couple times you do it in solidity. But the more you do it, the easier it becomes. And in the future, we can always r
eference a function like this to figure out okay, here's the easiest way for me to get this number. Awesome. So now we have a get price function, which is going to return a un 256, which is going to be the price of Aetherium. In terms of USD, all we need to do is convert the message dot value from Aetherium. To terms of dollars, let's create this get conversion rate function. So this one, we're going to take an input parameter of un 256 of eath amount, it's going to be a public view function. An
d it's going to return you went to 56, we're going to pass it some eath amount. And on the other side, we're going to get how much that eath is worth in terms of USD. So we're going to do a u intuity. Six eath price equals get price. So first, we're going to call our get price function that we just created to get the price of Aetherium. Then we're going to do u and 256 eath amount in USD equals eath price times eath amount, and then we're going to divide it by 118. When you're doing multiplicati
on and division math in solidity, you always want to multiply and add first and then go ahead and divide since eath price and eath amount both have 18 additional decimal places if we were to just let them rock without this, they would have an additional 36 zeros tax tacked onto the end. So we need to divide by one EA team. Now when we get to the hard hat sections of this course testing all this math is going to be a lot easier. And if you're really struggling with some of the math bits right now
, I wouldn't let that slow you down. Because once we get to heart, it's going to become a lot easier to actually test this than working on a test net. And this eath amount in terms of USD is the number that we're looking for. So we can just go ahead and return eath amount in USD, CSB returns here, and boom, now we have a good conversion rate function to walk you through the math real quick. Let's say the eath price is going to be $3,000. So it's going to be 3000. But it's going to have an additi
onal 18 zeros tacked on the end, it matches the message dot value way units. And let's say for example, we send one eath or 112345 678-910-1234 5678 eath into this contract, one eath should equal $3,000. So to get the price, we're going to now do the eath price, which is 3000 times the eath amount, which is this one, and then divide by one raised to the 18th. So method out we'll do 3123 1-234-567-8910 12345678 times we'd 1001 2345678 1-234-567-8910 times 112345678 1-234-567-8910. And now we divi
de that by 112345678 1-234-567-8910, which equals 2.9. Mmm, II 21, which the calculator kind of messed up them a little bit, but 2.9, not 2.99, ie 21 means this has 21 decimal places. So it'd be 2.1 234-567-8910 1-234-567-8910 one, or 1-234-567-8910 12345678 2900 I 9.99 and a nine. And this is actually exactly the reason why we don't do decimal math in solidity, our calculator saw that massive number was having a hard time getting it. So it ended up rounding that number to 2.999. And nine, when
we work exclusively with whole numbers in solidity, we don't have a chance of losing that precision. And in solidity, this is going to return exactly $3,000, which is correct one Aetherium at $3,000 per Aetherium is going to be $3,000. And like I said, since we're building this contract, assuming we're going to be working on this test net, we're not going to test this function on the test net, because we're going to have to wait for that transaction to go through. If you want to go ahead and dep
loy this and play around with it yourself, you're more than welcome to Okay, great, now we have a function called Get conversion rate that we can use on our fund function to make sure we've sent enough message dot value in our fund. So what we can do now is all we need to do is to get conversion rate of message dot value needs to be greater than the minimum USD. Of course, right now our minimum USD is just in terms of 50. And we know that conversion rate is going to return it with 18 zeros to re
present the decimal places, our minimum USD amount needs to be upgraded to 10 to 50 times one e 18. Or again, one times 10, raise the 18th, I'm going to deploy this to a test net just to demonstrate it. But again, you don't have to if you don't want to wait for this. So I'm gonna go ahead and deploy this confirm. And now we have this funny contract. If I don't say anything in value, and hit the fun button, we're gonna get this gas estimation error failed. This is kind of a blanket error, basical
ly saying, Hey, you can go ahead and send this transaction if you want, it's highly likely that it's not going to work. And the reason that remix knows that it's probably not going to work is because it can see this require and simulate the transaction and say, Hey, you didn't send enough money with this. However, even if we send some money, like 5000 way, it'll still give us this error. Because that's not enough. Let's do the calculation right now based on what the price of eath is. So we can a
ctually go to data dot chain that link, we look and see approximately what the price is. So it looks like the price of Aetherium right now is about $3,000. And this might be different for you depending on when you do that. So if the price of Aetherium is $3,000, and our minimum is at least 50. We could do 50 divided by 3000 0.016 eath should be approximately enough. So if we go to our Aetherium converter, and we do 0.016, we'll get how much that is in way, let's do 0.02 Just to make sure that we
're going to be over the amount. So we'll paste that in. We'll change this to way. And now if I hit the fun button, instead of us getting that error popping up, it's going to actually go ahead and let us do the fun function and we could confirm it and it wouldn't fail. I'm going to reject it for now just because I don't really feel like waiting for the transaction to go through. But great. We've confirmed that our get conversion rate is one working as intended, awesome, great work. So what's the
next bit of this funding contract that we want to do? Well, when people actually send money to this contract, we want to keep track of all the people who send us money. So let's create some data structures. To keep track. Let's create an array of addresses called funders. And we'll keep adding all the funders who send money to us. So we'll say an address array, or an address list. We'll make it public funders. And anytime somebody sends us money, and this actually does indeed go through, we'll
add that funded server list. So we'll say funders dot push message dot sender, like message dot value. Message dot sender is an always available global keyword message dot value stands for how much Aetherium or how much native blockchain currency is sent. Message dot sender is the address of whoever calls the font function. So if we're on Rigby message dot sender is going to be equal to whatever address is calling that function. Since our address is sending the ether, we're going to add our addr
ess to this funders list. This way we can keep track of all the wonderful donators who are donating to our contract, then maybe we won't even make a mapping of addresses to you and 250 sixes of addresses to how much money each one of these people have actually sent. So we'll do address to you and 256 public address to amount funded. And when somebody funds our contract will say address to amount funded of message dot sender equals message dot value. Now we have a function where people can fund o
ur contract. And we can set a value in terms of USD and we keep track of the different funders who actually fund our contract. This is fantastic. Now I know we've gone over a lot of really intense math and intense stuff here. So so let's do a quick refresher of what we've learned so far. Whenever we work with a contract, we always need the API and the address when compiled an interface gives us that minimalistic API to interact with contracts outside of our project. When you combine these compil
ed interfaces with an address, we can call the functions on that interface on that contract. chain link. data feeds are a decentralized way to get information about the real world. In this case, we're getting the price of Aetherium in terms of USD from a decentralized collective of chain link nodes. When working with math and solidity. Decimals don't work. So we need to keep that in mind when doing any type of math in solidity. And we need to make sure we always have the correct units, so that o
ur math makes sense. Message dot value, and message dot sender, our globally available variables were message dot sender represents the sender of the message or transaction. And message dot value represents the number of ways sent with the message. There's a whole bunch of different special variables and functions that we can access at any time. And these are available in the solidity documentation. Alright, great, we've got a great way that we can actually start funding our contract. But our co
de looks a little bit messy, we've got a couple of different functions for getting the price and working with these prices, is there a way to make this math a lot easier to use, this is where we're going to introduce the concept of a library. So what is a library, I definitely recommend checking out solidity by example.org, as you're going along with this course, as well, they've got some fantastic examples. One of such example is going to be about libraries, libraries are similar to contracts.
But you can't declare any state variables and you can't send ether. We can also use libraries to add more functionality to different values. What do I mean by that? Well, what we can do actually is we can have get conversion rate be a function of a un 256. So we could do something like Messer dot value dot get convert John, conversion rate. And we can add functions as if you went to 36 was an object or a struct or a contract that we actually created. So how do we do this? Well, let's create a ne
w contract in our contracts folder and create a new file. We're going to call it price converter, dot salt. And our price converted outsole is going to be a library that we're going to attach to a un 256. So how do you actually create a library and what is a library? Well, a library is going to be really, really similar to a smart contract. It's gonna start with spdx license identifier. My team, we're gonna give it a pragma, solidity zero point 8.0. And instead of typing contract for the name of
the contract, we're going to do library for the name of the library. We're going to call it price converter. Now libraries can't have any state variables and they also can't send ether and all the functions in a library are going to be in there. kernel. So what we can do is we can go back to fund me dot soul, we can grab get price, get version and get conversion rate, copy them all, delete them from Funmi dot soul and paste them into our library. And of course, since we're using aggregator v3 i
nterface in here, we can also copy the import from Funmi. And since we're not using the aggregate of three interface and our contract anymore, and we're using our price converter, we can paste it into our price converter. Now, if we compile price converted at soul, we see that it actually passes. Now all the functions inside of our library need to be internal. And we're gonna make this library price converter different functions, we can call on you activity six, for example, we're going to be ab
le to do message dot value dot get conversion rate, we're going to directly be able to get the conversion rate of a value of a U and 256 as if that was a function for it the whole time. So first, let's make this internal. Let's make get conversion rate internal. And we'll make good version internal. Now that we have this library price converter back in our Funmi, we can now import this price converter and attach it to you in 256. So we'll do import that slash price converter, dot soul. And in Fu
nmi, we'll do using price converter for UNT 256. Of course, if we compile our Funmi. Now, this line is getting an issue because saying hey, get conversion rate isn't defined. Now in our library, the first variable that gets passed to the function is going to be the object that it's called on itself. So in Funmi dot soul, let's go ahead and comment out this line for now. If we do message dot value dot get conversion rate, this is secretly the same as we did get conversion rate or message dot valu
e in our price converter library, the message dot value is going to be passed as the input parameter to get conversion rate, forget price and get version we don't really care about the number. So we're just going to leave it blank for now. So instead of require get conversion rate of message dot value, we can now do message dot value dot get conversion rate. And compile that you'll see that here we're not passing a variable, even though our get conversion rate function says hey, I'm expecting a
variable. Again, the reason for this is, is this message add value is considered the first parameter for any of these library functions. And that's how it works. If we wanted another variable in here, like you went to 56, something else. Now we would want to pass something else in here 123. And this 123 would get assigned to this something else. But we're going to delete that for now. Okay, great. And in doing that, we've minimized our Funmi contract a lot by moving a lot of that math and price
conversion stuff into our price converter library dot Sol. One of the most common libraries that was used for the longest time was this library called Safe math dot Sol. And you'll probably see it a lot of different places, we're gonna go off on a quick little tangent here and teach you about safe math. So let's close Funmi close price converter. And let's create a new file called Safe math tester. That's all. And let's start with some basic stuff in here. Safe math 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 a 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, we can use any version of solidity before version 0.8 of solidity. So for example, we use pragma, carrot, zero, poin
t 6.0. And we'll create contract safe math tester, dot Sol. Now if I create a you int eight, 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 zero point 6.7 pragma, solidity, the maximum size of a Yewande eight is going to be 255. This is going to be the biggest number that we can fit in the new int eight. And if I were to deploy this to a JavaScript VM or even a test network, safe math tester, let's go ahead to play up.
If I hit big number, we're gonna get 255. Well, what happens if I create a function called ADD? That sets big number equal to big number plus one? Let's save that. Delete that old contract and deploy. All right now big numbers 255 What happens when we add one two? big number. When 255 is the max size a, UNT eight 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, unsigned integers and integ
ers 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 let's say if I were to hit this add button a ton more times and get it back to two and a 55. 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 intuitive six, 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 to under 55. But if we hit Add, it actually fails. And we still get to under 55. In version 0.8, in solidity, they ad
ded 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 plus one in this unchecked bracket, let's delete our old contract will compile will redeploy. We had big numbers to 55. Now we hit add, we hit big number again, it reverted back to zero. So that's a little bit more about safe math, checke
d 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, that it mig
ht make sense for you to use the unchecked keyword. Let's head back over to our Funmi contract, where we are now using the price converter library that we just created. Alright, great. So now we've got a pretty minimalistic contract here for actually doing the funding. And we have all of our math for getting conversion rates done in our library price converter, which we're going to import at the top of Funmi. Cool. So at this point, we've got our fun method. Awesome. And so we can allow anybody
to go ahead and fund this contract and send this contract Aetherium, or any native blockchain currency to this contract. Well, now what do we want to do? Well, once all the funders have gone ahead and funded, we're going to want the project to be able to withdraw the funds out of this contract. So they can actually go ahead and use those funds to buy things for this project. So let's go ahead and create a withdrawal function. So we'll create a function withdraw. And we'll make this public. Since
we're going to be withdrawing all the funds out of this contract, we probably also want to reset our funders array, and our address to amount funded. Since we'll be withdrawing all the funds, those amounts should go back down to zero. So let's go ahead and loop through the funders array and update our mapping object so that each of these funders now has zero, because in just a second, we're going to withdraw all the money from them. So to do this, we're going to use something called a for loop.
So what is a for loop? A for loop is a way to loop through some type of index object or loop through some range of numbers or just do a task a certain amount of times repeating. So for example, let's say we have an array or list. And on that list, we have 1234. If we wanted to get all of the elements in this array, or in this list, okay, 1234. How do we get all the elements in this list? Well, we would use a for loop to loop through each one of these objects. So at zero with index would be one
at the first index would be two, and at the second index would be three, at the last index would be four. So we would loop through the indexes zero through three to get all these elements. Or maybe another example is if this was A, B, C, D, A is at the zero with index B is at the first index sees the second Indy's at the third and we will loop zero through three. To get to each one of these elements, we're gonna do that exact same thing. But with the funders array. So how do we actually do that?
Well, we first start with the for keyword, the for keyword says, Okay, we're about to start a loop. And inside of these parentheses, we define how we want to loop through it. Also backslash star, and star backslash is sort of like brackets for comments. Anything in between these two will be a comment. So in a for loop, first, we give it the starting index, then we give it the ending index, and then we give it the step amount. For example, maybe we want to start with zero, we want to go to 10. A
nd we want to go up by one each time. So we would go 01 234-567-8910. Or maybe we start at zero, we want to end at 10. And we go up by two each time. So we'd go 02468 10. Or maybe we want to go from zero to five, we want to go from two to five, with a step of one, we'd go 2345, etc. So this is what's going to go inside of this four bit here. So for our starting index, and let me even just put this above so that you can reference it. So our starting index is going to be you in to VT six variable,
and we're going to call it funder index. And we're going to start with thunder index being equal to zero. So we're starting with zero here. And we're going to end with the length of our funders array, since we want to loop through all of the funders. So we're going to say, funder index needs to be less than funders dot length. So our ending index is going to be whenever funders index is no longer less than funders dot length. And then finally, we're gonna say funder index equals funder index, p
lus one, which means that every time the code inside of this loop finishes, we're going to increase funder index by one. That's how we go from zero to one to two to three to four to five, etc. Another way you can type funder index equals funder index plus one is you can just do funder index plus plus, this plus plus syntax means funder index equals itself plus one. So let's start looping through our funders array to access the the zero with element or the first element, we're going to say, funde
rs of funder index. So we're saying we want to access the zero with element of our funders object. And this is going to return an address for us to use, we're gonna go ahead and say address under equals funders at the funder index. So now we have this funder address. And we want to use this to reset our mapping. So we're going to say, address to amount funded at at the funder key is now equal to zero. Because remember, in fund we update the amount. Whenever we fund the contract, when we withdraw
the money from the contract, we're going to reset it back to zero. Now let's walk through this funder index starts from zero. So we're going to get the zero with funder, we're going to grab that funder at the zero with index and we're going to reset the address to male funded of that funder to zero, then this for loop is going to update by one, it's going to move from zero to one, it's going to check then if funder index is less than the length, let's say funders has 10 people in it. If funders
has 10 people in it, it'll still be less. So now funder links will be one address funder will equal funders of one now instead of zero, and we'll grab that address, and we'll reset that addresses about funded to zero, then we'll continue to two to three to four all the way up to the length of our funders array. And this is how we can loop through our objects. So saying this middle one is the ending index isn't exactly right, since we're really checking for a boolean to see if this is still true
, but hopefully you get the idea. So we've reset the balances of the mapping. However, we still haven't done two things, we still need to reset the array to make the funders a blank array. And then we also need to actually withdraw the funds. Since when we funded this, we sent message dot value along with calling this fund function. However, we didn't actually withdraw the funds. So to reset the array, we could loop through it and delete objects from this address array. Or we could Just totally
refresh this variable. So instead of looping through the array and deleting objects, we're just going to say funders equals a new address array, we're going to completely reset the array by saying this font is variable now equals a brand new address array with zero objects in it to start, if we were to put a one here, this would be there'll be one element to start in the array, two would be two, three would be three, etc, we're just going to start it as a completely blank new array. So great, we
've gone ahead and reset the array. But how do we actually now with draw 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 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 simpl
est and at surface level makes the most sense to us. So if we want to transfer the funds to whomever is calling this withdrawal function, we would do we would say message dot sender, dot transfer. And then we'd get the balance of our contract here by saying address this, this keyword refers to this whole contract dot balance, and we can get the native blockchain currency or the Aetherium 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 typecast message dot sender from an address type to a payable address type. So message dot sender is of type address. Whereas payable, message that sender is of type, payable address, and in solidity in order to send the native blockchain token like Aetherium, you can only work with payable addresses. To do that, we just wrap it in this payable type caster. So this is the first way that we actually send Aetherium or send tokens from different contracts to each other, we wrap t
he address that we want to send it in, in this payable keyword, we do dot 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 sent Aetherium, from one address to another, it cost about 2100 gas or 2100. Gas, our trans
fer 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 sent 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 air and revert the transaction with send, it won't air, it'll return a boolean of whether or not it was successful. So using send will do payable message that sender that send address this balance. But we don't want to finish our call here. If this w
ere to fail, the contract wouldn't revert the transaction, and we just want to get our money sent. So we want to do Boolean send success equals this whole bit here. And then we want to require success. And if this send fails will throw an error saying sin 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 require statement here. So great. What's the
third way that we can actually send Etherium or native currency wallets 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 Aetherium without even having to Have the API 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 Aetherium, or your
native blockchain currency call is going to look very similar to send, we're going to do payable, message dot sender, dot call. And this is where we will 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 deploym
ent, there's always this message dot value bid, we're going to use this call function as if it's a regular transaction, and we can add stuff like message dot value. So in here, we're going to add these squiggly brackets. And we're going to say, value address this dot 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 bytes 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 we only care about one. And then similar to the centerpiece above, we're going to do require cost access call failed, meaning that we're requiring cost accesses true. Otherwise, we'll revert with an error that says call failed. Now of learning the difference betwe
en 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 learned more about how some of these lower level functions work. And a little bit more about how gasworks solidity by example, does a fantastic job though of saying what the difference is between all three, our transfer has a maximum of 2300 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 d
oesn'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 Aetherium 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 Aetherium or native blockchain currency tokens. And I'm going to delete this part for the video, but I'll keep those comments in the code re
pository associated with this course. And okay, perfect. If we hit compile a fun meat outsole, we do indeed see that it's passing compliation. However, there's a bit of an issue here, right now, anybody can withdraw from this contract. So anybody can fund, which is what we want. But we don't want anyone to be able to withdraw. We only want the person who's collecting the funds to be able to actually withdraw the funds. So how do we set this up so that the withdraw function is only called by the
owner of this contract? Well, to do that, we're going to set up a couple new functions. So when we deploy this contract, we want to automatically set it up so that whomever deploys this contract is going to be the owner of this contract. And then we can do some parameters to set it up so that only the owner of this contract can call the withdrawal function. So how would we do that? Well, maybe we can create a function called like, call me right away. And right after we deploy this contract, we c
all this call me right away function, which will set up us as the owner. Now that's going to take two transactions. And that would be really annoying if we had to do that. So instead, solidity has something called a constructor. And if you're familiar with other programming language, a constructor is exactly the same as other programming languages. constructor is going to be the function that gets called when, immediately whenever or you deploy a contract. So if I were to deploy Funmi, dot Sol,
and I were to say, minimum USD equals to minimum USD would no longer be 50 times one e to the 18th, it would be immediately updated to two. Because constructor is a function that gets immediately called in the same transaction, that we create this contract, this constructor function is going to be incredibly helpful for us, because it allows us to set up the contract the way we want it to be. So for example, if we want the withdrawal function to only be able to be called by the owner of this con
tract, we can have the constructor set up who the owner of the contract is. So let's create a global variable called address, public owner. And then in our constructor, we'll say the owner is going to be equal to the message dot sender. The message that sender of the constructor function is going to be whoever is deploying the contract. So owner is now going to be whoever deployed this contract. And don't worry, we're going to demo all this very soon and show you everything that's going on with
ether scan everything, demoing this all right now might take a little bit of time, because we're using a test net. So if you want to test it all right now, absolutely go for it, but just know, it'll take you a little bit longer to do so. Now that we have the owner setup, we can modify our withdrawal function to make it so that only the owner can actually call this withdrawal function. So at the top of the withdrawal function, maybe we want to add a section, maybe we want to say require message d
ot sender equals the owner, a note about double equals versus equals, you can think of this single equals as a set parameter. So when I say owner, is now set to message dot sender, double equals is how you check to see if these two variables are equivalent. So we're saying is message dot sender, the same as owner. So this is checking to see equivalence. This is setting checking to see equivalence setting. So we're gonna say require message dot sender is equal to owner, otherwise, we're gonna thr
ow an error, saying, sender is not owner. Perfect. Now we have a quick way to make sure the withdrawal function is only called by the owner of this contract. Now, let's say that there's a lot of functions that we have in this contract that are going to be required to be the owner, maybe there's a lot of functions in this contract that need a whole lot of different requires, we don't want to have to copy paste this line to every single one of our functions. So what can we do? Well, this is where
something called modifiers come in. So for now, we're gonna go ahead and delete this line. And below, we're going to create something called a modifier, our modifier is going to be a key word that we can add right in the function declaration. To modify the function with that functionality, we're going to create a modifier and call it only owner. And we're going to paste that line that we just made in withdraw. And underneath that, we're going to put a little underscore, what I can do now is I ca
n take this only owner modifier, and stick it in the function declaration of my withdrawal function. So what's happening with this modifier with only owner in this function declaration, we're saying, hey, for this withdrawal function, before you read all this code inside of it, look down at the only owner modifier and do whatever is in there first, and then do whatever's in the underscore, this underscore represents doing the rest of the code. So now, when we go call the withdraw function, we ac
tually do this require statement first, and then call the rest of the code. If this require statement, we're below the underscore, this would tell our function to go ahead and do all this code first. And then run the require. Because again, we have this only only keyword, we're saying, Great, we've got a function, it's withdraw its public, oh, only odor modifier. Let's look at how that works. Okay, it tells us how to do all the code of the original function first. So let's go ahead and do that.
Okay, now we're done. Now, what do we do? Okay, now we'll run the require, we want to go ahead and put the require here first. So this is how modifiers work, and how we can use them to improve our functionality. All right, awesome. We have all the basic functionality of our contract that we need here. Now we're finally actually going to run everything on a test and see everything happened live before our eyes. Are you ready? Let's do this. So let's go over to the deploy tab. And we're going to s
witch of course to injected web three. Remember But we're using injected web three, because our price converter dot soul is using chainlink Oracle's that actually exist and are actually monitoring the Rinkeby network for us. Now we're going to scroll down to, and we're going to choose the Funmi contract. And we're going to go ahead and deploy. Once again, we want to make sure we're on the Rinkeby test net. And we have a little bit of rinky eath in our wallet, let's go ahead and deploy, confirm.
And we'll wait a little bit. And I'll pull up our log here. And we'll wait a little bit for our contract to get deployed. Alright, great. It looks like our contract has indeed been deployed. If we scroll down, we can see all of our functionality, minimum USD is going to be that $50. But with 18 zeros so that the units are the same as Aetherium, the owner of our contract was set to our address, the instant we deployed this contract, it was deployed by calling our constructor function. So this add
ress 0x 106 x is going to be the same as the address in our meta mask, your address here, of course, is going to be a little bit different than mine, we have our funders array, which, of course is going to be blank, we have our address array, which is also going to be blank. And then we have two functions that we can use to modify the state of the blockchain withdraw is going to be orange, because we're not paying any Aetherium we're actually gaining Aetherium or whatever native blockchain curre
ncy fund is going to be read, because fun is a payable function that we are going to be sending Aetherium to or sending whatever native blockchain currency that you're working with. So let's go ahead and see how this all works. So first, let's go ahead and fund this contract. Again, funding, we got to do a little bit of math, right now, since the price of eath is around $3,000. And we're looking for $50. Minimum, we do 50 divided by 3000. We can do 3000 divided by 50, we can do 50 divided by 300
0. So we know that around 0.02 Aetherium, should be enough for this contract to work. So 0.02 Aetherium is this much way, we can copy that, paste that into here. So when we hit fund, it should actually pass. And we do indeed see meta masks pop up. And we'll go ahead and confirm. Once this transaction goes through, we'll be able to see this contract on ether scan with the funds in it. Now if we don't add way here, if we don't add a value, once again, we had fund will say gas estimation failed bec
ause we're not sending enough here. And in fact, we even see execution reverted didn't send enough, we can absolutely send this transaction however, it's going to fail. Great. So now that our transaction has gone through, if we go on to the rink the ether scan, once we wait a little bit for it to finish indexing here on the Rinkeby ether scan, we can see that transaction actually went through for doing the funding, we can actually see a lot of different details going on with this transaction as
well. And if we scroll down, we once again, you can see all the information about us calling this fun function, gas limit gas, you should the gas fees, gas price, and we can see the input data as well, we can see that we called the fund function down here. We'll learn more about the input data later. If we go to the contract that we deployed, we can now see two transactions, we can see our contract created transaction. And we can also see we called a font method. And if we look at the balance of
our contract, and now has 0.02 ether, which makes sense, since we just sent it 0.02. If we put that 0.02 eath in terms of way back into the value section, and we call font again, after this transaction goes through, we should see this number go from 0.02 to 0.04. Now after we wait a brief delay, we do indeed see the balance has gone up to 0.04, which is exactly what we'd expect. Awesome. So our funding mechanism is working correctly. And if we go down into our array, and our mapping to do addre
ss to array, and we paste our address, we should see the phone number show up. And if we go to funders of zero, we see our address. And if we go to funders of one, we also see our address and we see that and we see this call going through if we go to funders have to in our log over here, we actually see that we get an error an optimization that we could make to our contract in the future is to check to see if an address is already in the funders array and then not add it if it's already there. N
ow let's go ahead and try to call this withdrawal function. But let's try to call it with a different address than the address we originally deployed this contract with. So to do that, scroll all the way to the top of this here. And I'm going to go to my Metamask. And I'm going to switch to a second account and hit connect. Now, our remixes should be updated with the new account that's in here, you'll see that if I switch back to account one, it switches back to account one, so long as they're b
oth connected, you can see which accounts are connected to applications by clicking this connected button and see which ones are connected. If you ever want to disconnect that account, you can click the three little dots and it disconnect the account. And now we can see that this account is not connected. However, count two is connected. Let's go back to account one and Connect account one so that both of them are now connected. But we'll switch to account two, let's switch to account two, becau
se again, account two isn't the owner of this contract. We scroll down to owner, we can see owner's 0x 1066 Something something and account two is 0x 043. Something something awesome. So what do you think will happen when we hit withdraw here? Well, our modifier only owner should kick in. And we should get notified that if we send the transaction, we'll get this error sender is not owner. So let's try it. Ah gas estimation failed, we do get this error. Sender is not owner, which is perfect. This
is exactly what we want, we could absolutely send this transaction if we wanted to. But that would just be a waste of gas because this transaction is going to fail. However, if we switch back to account one, and we hit withdraw, meta mask will pop up, enabling us to confirm and withdraw the ether out of this contract address. Now if we look at this contract address on ether scan, after a brief delay, we'll see the balance go from 0.04 back down to zero. And we'll see our wallet balance go up fr
om what it is back to 0.04 plus what it was. And after a brief delay, you can see our balance is indeed back down to zero in our contract. Now, if we do address to amount for our wallet address that was doing the funding, it's back down to zero. And if we try to check the address of funders at index zero, we get called to funders that fund me errored execution reverted. We've completed all the basics of this section that I wanted to go through. And you should be incredibly proud of yourself for
getting this far, you've just deployed a really advanced smart contract, we're using a library and chainlink contracts to build some of the most powerful applications in the planet, we've learned to use a library for any type we want in our smart contracts. We've learned more about multiplication, and then units of measure in solidity and smart contracts. We've learned about mappings more about arrays what the constructor does, we've learned how to send money we've learned about for loops, we've
learned about the different ways we can actually send money, at least from a low level. And we've learned about modifiers. This section is one of the tougher sections in this course. So if you completed this, you should be incredibly excited. We're going to go through our code now. And we're going to make a number of tweaks. Now this section, we are going to do a little bit more advanced solidity here. So if you get a little bit lost, don't sweat it too much. And feel free to try some of this s
tuff in the future on your own. We're going to modify this contract to make it a little bit more professional. It's not going to be end to end 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 o
f the constructor. If we have variables that only get set one time, we can actually use some tools in solidity to make them more gas efficient. For now let's compile our Funmi 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 in the money stuff isn't going to work. Because again, we don't have a chain link network on our JavaScript VM. So those aren't going to work so well. But for what we'r
e gonna do right now, we don't really care so much. Here's what we do care about. You do care about how much gas this costs to actually send. We do care about how much gas is costs to create right now creating this contract costs about 859,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 the bid, 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 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 cons
tant keyword, this minimum USD no longer takes up a storage spot, and is much easier to read too. So now 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, let's compare it to how much it was before. Well, we saved almost 19,000 gas, that's almost as much gas as a cost to send Aetherium. Typically, constant variables have a different naming convention. Typically
, you'll want to do them all caps like Min imaam. Underscore, who is the CIO 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 and compile this and redeploy. In our Funmi contract, even though this is a view function, remember, view functions do have gas costs when when called by contract as a constant variable, we
can see the execution cost of this variable 21,415 gas. So let's put a little note rather Nathan. If we remove the constant variable, we delete this contract. And we redeploy, like Funmi. And we hit minimum ust 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 that much of a difference. But on more expensive chains like Aetherium, this is going
to make a big difference. For example, on Aetherium, we can actually see current gas prices on Aetherium. Here, we can see the current gas price of Aetherium is about 141 way, so we'll go to our converter, way to way we'll copy the way price times this will get the gas price of calling our minimum USD, which is this number here, which if we put back in our Aetherium uniconverter, we can see cost this much gas. And if we times that by the approximate current price of Aetherium, which is around $
3,000. Calling minimum use D as a constant is going to cost $9 on the inside is at a nonconstant is going to cost almost an entire dollar more, 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 slip the 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 abo
ut gas optimizations right now. Now another variable we only set one time is going to be our owner variable. Owner equals message dot 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 immutable 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 that sender, there's only going to be a message dot sender when we're inside of a function. So inside here, we might say I owner equals message dot 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 deploy up, we can see how much gas we can see how much gas calling I owner is going to be by with immutable notice, we get 21,508, 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. If we scroll down to I owner, screw up the logs, we go down to the call, scroll down, we see the execution cost was much more. So we'll do the backslash, a seven here, ye
s, 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 bytecode 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 low level stuff that comes to these contracts. But for now, just know that these exi
st. And they're nice gas savers, if you're only setting your variables once. Alright, great. So we've just made our contract a little bit more gas efficient, little gas efficiency improvements are going to be concept I sprinkled 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 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 charact
ers in this errorlog needs to get stored individually, this string may not seem very big, but it's a lot bigger than the alternative with what we can do. As of zero, point 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 a 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 air. So for example, wi
th our require down here, and with actually with all of our requires, well 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 error not owner scroll down into our only owner, instead of doing a require we'll do an if statement, we'll say if message dot sender is not owner, then we're going to go a
head and revert with a non 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 in solidity. So you'll want to get used to writing in 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 t
han required, you can use something like this, we could update all of our requires here for these customers. 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 required us without the conditional beforehand. So you can actually go ahead 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 the c
ontract that takes Aetherium 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 with our fund function get triggered? No, it wouldn't get triggered, we wouldn't keep track of that funder, we wouldn't have that person's information updated in this contract. So if late
r on we want to give rewards or something we wouldn't know about those funders. And this wouldn't be great because 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 Metamask. 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 con
tract, ether without calling the fun function? Right now, if we were to send this Funmi contract, ie 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 nu
mber 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 received 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, dot soul. And in here, we're going to add our basic pieces, SPX license identifier, MIT pragma, solidity zero, point 8.7. And we'll do contract fallback example, like so, feel free to pause the video to catch up to this point, let's recreate 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 Aetherium or make a transaction to this contract. Now, as long as there's no data associated with that transaction, this receive function will get triggered. What we can do in here now is we can say result equals one. So let's go ahead and test this out on the JavaScript virtual machine, we compile this, so we're gonna g
o ahead and compile this. And we'll go deploy it on the Java 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 zero. But what if we were to send this contract some Aetherium? Well receive would go ahead and be triggered here, we can actually send this contract some material directly by working with this low level interactions. But here, don't worry about wh
at 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 called Data blank, it'll be the same as if we were in Metamask. And just hitting send in the 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 exa
mple, 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 fall back example, dot receive, it looks like it called our received 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 this value be zero, does receive get triggered 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 Aetherium to this contract. Let's hit transact. It looks like that
went through, do you think result is going to be one or zero? You thought one you were correct or 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 Funmi. For example, when we call one of these functions, we're actually just populating this call data bit with certain data that points to one of these functions up here. If we send a transaction and we add da
ta 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 I had some call data to this transaction, do you think receive will be triggered this time? If we hit transact and remix we actually get a pop up 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. Hmm, I don't see any function that matches the 0x 00. 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 can work even when data
is sent along with transaction. So our fallback will look something like this callback, external payable. result equals to 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 Funmi. Our constructor, for example, is a another type of special function. There's no function keyword. solidity knows that this constructor is immediately calle
d 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. Like here, we hit result, we do indeed, see, it's set to zero. Now, if I add this 0x 00, and I send this, and I hit transact, this is equivalent to calling our contract here without a valid function. So our contract goes, Huh, I don't recognize what you're trying to tell me here, I'm going to refer you to our fallback.
And now if we hit result, we see that it's been updated to two. If we take this away, solidity will go, Hmm, it looks like you're trying to send some Aetherium, or call this contract without specifying what you want to do. Well, I have a receipt function. So I'm just gonna 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 to no data, updates to one slowly by example, that org has a wonderful l
ittle 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 air out. So this is a lot of really fantastic information here. How can we apply this to our fund mi contract here, or what we can do now in
our Funmi is we can add these fallback and receive functions, just in case somebody actually sends us contract money instead of calling the fund function correctly. So what we can do is let's add a receive function. So if somebody accidentally sends it money, we can still process the transaction will 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 will have fallback external payable. We'll ju
st have it automatically call fund. Now, if somebody accidentally sends us money without calling our fund function, it'll still automatically route them over to the fund function. This means to 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, Amman rink B and my Metamask. Let's switch over to injected web three. And we'll scroll down we'll choose our Funmi contract.
And we'll go ahead and deploy this Metamask pops up, I'm gonna go ahead and confirm the transaction. And we see our Funmi contract here right now we can see the owner 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 the copy the address, and then go to rink the 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 contra
ct creation. We saw what happened before when we hit the fun function, our contract was updated with a new balance, and that funder was added to our an 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 the font. So let's copy this address. We'll go to our meta mask. We'll hit send, paste the address in here with 0.02 eath. Again, because
this should be more than the minimum amount in USD, we'll hit next. I'll go ahead and confirm this. After a slight delay, if we did this right, we should see the transaction having called the fund function here, now that our transaction has gone through After a brief delay in waiting for ethers can 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 i
nstead 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 zero with 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 fun function up here. So awesome work, we were able to add a receive function to help people who accidentally ca
ll the wrong function or accidentally send this contract money, instead of correctly calling the fun function. Now, if they had directly called the fun function, it would have cost them a little bit less gas, but at least this time, they're gonna get credit and add it to our funders array for having sent our funding contract money. 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 c
ode editor now, where we can get even more advanced with our solidity on our setups. 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 gotten 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 itams events, try catch function selectors, abi encoding
, hashing, and then you will slash and then you will slash 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 it 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 t
o 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 times 118. 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 constant variable,
and we compiled, a compiler would give us an error saying, Can't write to a mutable here. Or if we tried to change a constant variable. Our compiler would say, Hey, you can't assign 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
will trigger the 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 Awesome, you've done fantastically to get this far. And for this section before we get started actually moving over to Hardhead. And moving over to JavaScript and understanding why we need to do that. Let's understand a little bit about getting help and running into problems. So let's say we have our Funmi contract here that we just worked on. A
nd we run into an error. Let's say for example, we forgot the payable keyword, right, and we go ahead and compile this compile fund, we did so. And we scroll down. And we see obviously, we have two errors here, right, we're getting some errors, and we scroll down. And we see type error message dot value and call value can only be used and payable public functions, make the function payable or using an internal function to avoid this error. And then it goes ahead and gives the line that's airing.
Now this error is pretty clear, this error code is pretty clear. It's saying Hey, make the function payable, or using an internal function to avoid this error, right? This should be pretty easy to to add payable, and then recompile and be good to go. And this is actually a good example of what to do when you run into errors. When you run into errors. The first thing you want to do is you want to try to figure out exactly what's going on yourself based off of what the error says. This one's pret
ty straightforward, but some of them can be a little bit more obscure step one when trying to get unblocked trying to tinker and figure out errors yourself, right? Because maybe you go okay, I'll make this payable, right? And you go to save. And then it gives a different error saying, hey, you know, payable doesn't go here. You resave you recompile it goes, Hey, we're still missing that payable thing. First step is always going to be trying to tinker and figure it out yourself. For this course,
I want you to limit tinkering, slash triaging to 20 minutes, if you take more than 20 minutes to tinker and triage, then move on to the next step. But I also want you to take at least 15 minutes yourself or be 100% Sure, you exhausted all options, you're completely out of ideas. So typically try to tinker try some stuff for 15 minutes. And if you're under 15 minutes, and you're saying, Hey, I'm 100% Certain I've tried everything that I can think of, then you can move on to the next step. So step
one, when you run into errors is always going to be tinker and try to pinpoint exactly what's going on. Try to pinpoint exactly what's going wrong. Step two, let's say you tinkered and you tried payable all over the place, and you couldn't figure out what this error was and how to debug this here. Step two is always going to be Google the exact error and see if you can learn from that. So zoom out a little bit, I'll roll my mouse over this, grab this, copy it, or quotes around it, and do exactl
y that, in Google search that exact error and take some time going through Google going through Stack Overflow going through Stack Exchange eath, and look to see if somebody has asked this question already. And it looks like down here looks like somebody has type error missed a value and call though can only be used on PayPal public functions. And if we scroll down, we see that somebody ran into exactly this. And they went ahead and solved it. They go, I realized my mistake, I needed to add the
PayPal keyword to my own implementation. And they go ahead in this question, they've added the payable. And hopefully this would give you the insight to say, Ah, okay, great. I do need to come back here and add payable. Let's say this StackOverflow question didn't show up. Right? This forum wasn't here. What do we do next? So step one, tinker. Step two, Google the exact error, I'm going to do a step 2.5 That only is for this class, go to our GitHub, repo discussions, and or updates for this cour
se, specifically, go to this GitHub repo, full blockchain solidity course, Jas, it'll look a little bit different when you all get to it. But come to this repo, and look in this chronological update section to see if there's an update on that section that you're doing. Obviously, since I'm recording right now, there's no update. And if you don't get anything, feel free to jump into the discussion section. And ask a question in here, right, there's going to be a community of people looking to hel
p each other out and looking to make this a lot of fun. And the reason I say 2.5 is because in the real world, you're not going to have our GitHub repo, when working on stuff outside of this course, you're not going to have this GitHub repo. So instead, in the real world, I'm still going to give you the keys, I'm going to give you what it takes to still unblock yourself on anything. Okay. So number three is going to be asked a question on a forum, like stack, exchange eath and Stack Overflow. St
ack Overflow is a question and answering tech forum like this, right? You can ask tech questions, and then you can answer them as well. And as you can see, when you search for these issues, they'll show up so Stack Overflow is more for general Role programming questions and Stack Exchange Aetherium or Stack Exchange eath Aetherium Stack Exchange, this is for more Aetherium or EVM based question and all the solidity code that we're gonna be working with, whether it's polygon, whether it's avalanc
he, whether it's whatever, those questions are going to be valid here, and you can ask here. So what you'd want to do is you'd want to sign up or log in, and ask and format your questions on these forms, you'll want to sign up for GitHub, you want to sign up for Stack Exchange, you'll want to sign up for Stack Overflow, so you can participate in these forums. 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, becaus
e 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 powerup. 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 gonna do, we're gonna go ahead and sign up GitHub, enter your email and we hit Create Account, th
ey're going to send us an email. So we're going to come back to our email, and we got our launch code here, paste it in. And so a little bit of information. We're going to choose the free version. and fantastic. We've now created a GitHub profile. Now back over in the smart contract kid full blockchain solidity course, Jas, I'm going to create a new discussion, a new thread, and I want you all to comment on to make sure you understand how to format and how to ask questions. Okay, general thread
for practicing. Question formatting. Oops. And so let's go back here. So first, I'm going to format this question poorly, two ways, and then we're gonna format it really, really well. So the first way we're going to format it poorly, is by not giving enough information. So what we're going to do is I'm gonna just copy this issue we're going to do is we'll just say like, Hey, I'm having trouble with remix and an error. Can someone help me? Why is this not a well formatted question? If this is my
question, there's not nearly enough information here, I, as a helper, have no idea what this person's asking. So let's do something else. What I'm going to do is I'm going to copy this entire contract all the fun, read outsole, paste it in here, and go, Hi, I'm having issues here. Can someone help? I'm gonna head start discussion here want to hit start discussion, it formats this all weird. And once again, there's not really enough information here. I don't know what the issue is. But at least w
ith this one, we have some code, we have some way to actually debug. So this is a little bit better. But it's still not that good. Let's go ahead and edit this. To make this even better. We hit three dots, we can hit edit, what we can do is we can use something called Markdown syntax, and highly recommend learning a little bit of markdown, it's basically some syntax help make discussions on GitHub. And also, questions on Stack Overflow and Stack Exchange a lot easier. So we're going to format th
is code by adding these three backticks at the start, and then also at the end of our code. And then additionally, next, the first three backticks, we're going to type so lid did T which tells the format or to to use solidity to format this code here. Now if we update discussion, we notice we get some nice highlighting here. So this becomes much, much easier to read. Right? This is way easier to read now than than it was before. However, it's still not specific enough. We've given a ton of code
here, and we haven't given the specific answer. So this is gonna be really hard for somebody to answer. So let's make this more specific. So let's edit this question again. And let's specify, so we see here, our issue is specifically on this function. We're going to copy this function and we're going to delete everything else in here. And now we have just this code inside of here. Now we're going to make this really specific. We're going to say, on this function, I'm running into an error. And t
hen what we're going to do is we're going to come back here, we're going to roll the over this. We're going to copy this we could have pull our code if we want but we're going to format this error like this. And then we're gonna say Can someone tell me What's going on? Update? Now this is a much, much easier question to debug. Right? We have some minimalistic code, we have the error that we're getting. And we have Can someone tell me what's going on? Obviously, the answer to this would be to add
payable to this. And that's what somebody would say, hey, like, you need to add payable to this, I want you all to practice doing some formatting, go ahead and add a comment on this with your own formatted question. So that you understand how to actually do the formatting. And this markdown format. It's this format here, that's gonna be the exact same for asking questions on Stack Overflow, or Stack Exchange for this course, go ahead and practice if you want to create more new discussions, feel
free to create new discussions. If you want to use Stack Overflow or Stack Exchange eath actually highly recommend you Stack Overflow or Stack Exchange eath as well, because those are gonna get indexed a lot better than GitHub here. However, feel free to ask questions, obviously, in this GitHub as well. Now that I've given you kind of the basics rundown, we're going to watch a video that I made that goes even deeper into why and how to format all these questions and what to use. So let's go ahe
ad and watch that. Every developer has run into this. Something breaks or maybe you don't know something, but you don't have time to let these stop you. There are a series of steps that one should take to maximize one's chances of solving any coding problem, but you'd be surprised at how few developers currently use the superpower effectively, our first one we'll spend the least time on, because it's just tinker and experiment. When you run into an issue. Keep trying different things you think m
ight work, maybe try doing print statements throughout the file, learn some debugging tips, but don't be so cocky that you only do this first step. And this shouldn't just be random running around. This should be trying to pinpoint exactly what's going wrong in your code, so that you can either ask an effective question, or figure it out yourself. So pinpoint exactly what's going wrong, because you'll need it for the next steps. Anyways, next, check the documentation. Not all tools have good doc
umentation. But taking some time to explore documentation can be a quick way to find your answer, you'll want to learn how to search a webpage with Command F or Control F. That way, you can look for specific keywords on a page, or hopefully they have a good search bar that works well. Sometimes documentation can be really dense. So maybe you'll move to the next step, which is doing a web search. At the end of the day, good software engineers are secretly just professional Googlers. And this is o
ne of their most powerful tools, being able to search the web for somebody else who has already run into the problem that you've just run into, and then solved it. Most search engines like Google have tools you can use to get even more specific about what you're looking for. Often for specific errors, the best thing to do is actually just copy the exact error and paste it in the search bar with quotes or use the Asterix in spots, your error might be too specific. Most of the results you'll get w
ill be from forums and q&a sites, which leads us to our next step, asking questions in these forums and q&a sites. Just make sure that before you ask a question, you've done some ample Googling around yourself beforehand. This way you don't waste yours and anybody else's time. And by asking questions that you swear you will promise me that at some point, you will go back and help other people learn as well got it good. Before even asking your question though, we should learn where is going to be
the best place to ask. This is why I've categorized for different types of forums and QA sites, feel free to pause to read them over. And here's some specific examples of each one of these index code base forms like Stack Overflow, index repositories like GitHub issues, index technology, specific forums, like our slash eat dev or unindexed discussion platforms like chainlink discord, one of the key differentiators in these categories is the index keyword. We typically want to ask questions on f
orums that web crawlers have gone through and stuck them in their database or index them this way. And three weeks when we look back at the code that we wrote, we can just Google what was going on when we forget what it does. And this will help out other developers who run into the same problem, which in turn, they might go ahead and help you out later. Ideally, most of your questions should be asked on one of these index forms for this reason for their searchability and discoverability. However
, at some questions are a better fit for DMS, Twitter or discord that aren't index and we made a little chart here to figure out where's the best place to post your questions, feel free to pause the video take a look or read our blog and the descriptions with the picture as well to take another look at it. And of course, before actually posting that in one of these forums, be sure to read their rules as they might state that some kind of questions are specifically for Ben. But basically the brea
kdown looks like this. Theoretical big picture or opinionated questions can go great on general q&a forums like Quora or specific technical forums like specific subreddits or discord forums, specific coding questions can go on these forums as well, but will often get more eyes on coding forums like Stack Overflow or Stack Exchange communities often the question of Oh, should I post this on stack URL? flow or maybe a Stack Exchange community is incredibly blurry. And sometimes it doesn't really m
atter which one you post on. Now, if you run into a bug or an issue with a technology you're really familiar with, and you think it shouldn't be breaking, this is your chance to pop an issue into their open source code repository and potentially improve the tool. They don't have an open source code repository, you throw that closed source piece of shit into the garbage, but just kidding closed source Tech has its place in our lives, too. Additionally, if you're following a tutorial, and they hav
e a Git repo associated with it, like all of my videos that do, that's gonna be the best place to leave your issues. So as much as I hate to say it, putting your issues onto my GitHub repositories is going to be much more effective for us answering your questions than posting it in the YouTube comments. Now finally, Discord, element, email, text message or any other these unindexed chats are still good places to ask questions, but please try to use them as a last resort. And if they do end up an
swering one of your questions, maybe go back and add that question and answer to one of the other forums that we were talking about this way it will be indexed next time you or somebody else, Google's it now these quicker chat forums are places more for the community to congregate and have quick conversations with each other. They're places to theory craft, talk about new things coming out new ideas, events, and other things that shouldn't be indexed by web crawlers. They're also great places to
meet and network with people that you might be able to bounce ideas off directly as you get to know each other, which leads into our last section. But before we do that, Oh, do you hear that? Oh, that's the video inside another video alarm ringing. When you ask a question in one of these forums, the better you format your questions, the better chance you'll have of getting an answered. Now there's no bad questions out there. But there are poorly formatted questions. So let's teach you how to al
ways ask questions as format as best as possible to give you the highest chance of making sure they get answered. Number one, before asking your question, make sure you followed all the steps in the parent video. And you've done some research on this already and make sure the question hasn't already been asked. Number two, make a title that summarizes the specifics of the question three introduced the problem before you write any code, add minimalistic, reproducible code minimalistic code means
it's not just a copy paste your entire file. If you're having problems on one line, maybe just post that one line reproducible code means that others should be able to run to the exact same error that you're running into, or at least post the steps for them to do it. This doesn't mean that you should put I was following along Patrick's video and on our five I ran into this problem, just watch his video and you'll get there. As flattering as this is it's not reasonable that everyone is going to h
ave watched my videos, even though they should you want to give the technical steps to reach the error that you've reached. For those of you watching my Free Code Camp video, you're kind of exempt from this, but you can only say, Hey, I was on our Five on this part of your video inside of our discussions tab of the GitHub repo associated with this course. So you can do that. But only in that GitHub repo associated with this course, learning markdown to format your code, especially using these th
ree backticks and labeling of the language. This is a critical piece of formatting your code and will drastically improve on the number of people who answer your questions. Any errors or code should be formatted with this three backticks syntax. And finally, often people who care about certain technologies, monitor specific tags and monitor specific questions being asked about the technologies that they like. And then finally, again, be sure to read the forum's guides before posting different fo
rums have different rules about what they want and what they don't want. So being familiar will increase your chances of getting an answer. All right. So now back to the main video. Now a note about Stack Overflow, in particular, Stack Overflow can be a little aggressive, which is why sometimes posting on specific community forums might be better for your specific technology questions. If you post on Stack Overflow, and you get a ton of down votes on your questions. Don't let that bother you. Ju
st take it as a learning opportunity to learn about what Stack Overflow likes and doesn't like and just keep going but do not let that discourage you. Okay, well, now that we know where things should go, where questions should go and how to actually format them. Let's practice let's look at some sample questions that you might have. And we'll figure out where we want to put them. So the first one, where does this one go? Feel free to pause and guess yourself. So a question like this is going to
be great for a Reddit or a discord? Probably more a discord. Now, this is definitely something that you can search for. Right? So you probably could search for this, find an answer and go from there. But maybe you want to ask a buddy or maybe you want to ask a very specific community like our slash eat Dev. Now, of course, if you see this question, you obviously want to recommend Patrick Collins his YouTube channel. Now how about this question. Notice its formatting right? The title is nice and
big. They have a technical command that is formatted properly. They have Git commit which is formatted properly, where would this go like this would definitely do very well on a Stack Overflow or an index code based forum to very clearly try had to do something technical. The problem is laid out very clearly. And they've given the command that they're looking to do. Now, how about this one, something like this could go on either StackOverflow. But it's probably more likely going to go on a GitHu
b issue for this brownie package. A big difference between code forums and and Git repos like GitHub is that when you make an issue on a GitHub repository, especially when you think there's a problem, you do want to be as in depth as possible. So oftentimes, when making an issue on these repos, they'll even ask, what version are you using? Can you post all your code? Can you post all your files and just be much, much more explicit? So how about something like this. So this is going to be really
good for the GitHub repo associated with this tutorial, it looks like this person is asking about a very specific tutorial. So posting this, there is going to be best. Now if your question is on a tutorial that doesn't have a GitHub repo, well, they probably should. But then maybe this is better in the comment section. Now, again, this is where this all becomes a little bit more art than science, because maybe the specific error that they're running into is a generic error that a ton of people r
un into, and maybe it is better on StackOverflow. Or maybe there's an issue with the package. So maybe it is better on GitHub. Or maybe the solution to this is opinionated. And finally, what about this? Yep, this is going to be much better for a discord or a DM with your buddy. And away, it's our last step on blocking you from any question is going to be join and strengthen the community of your tool. Now at the start, it's going to be hard for you to give back since you're not going to be very
knowledgeable on these tools. But as you get better at these technologies, you'll want to try to answer some of these new questions that do come in. The reason is because this will give you a chance to actually learn more about the tools that you like, it'll strengthen the community of your favorite tools, meaning if you help answer questions on tool, it'll actually encourage other people to use the tool because there's a strong following there. And likely, they might actually help you sometime
in the future, you helping people will make you look like a good person. And then you'll also feel like a good person. Additionally, in many forums like Reddit, oftentimes, mods will actually look at how often you post versus how often you help others and comments on others people posts and some mods may actually start blocking your posts for abusing the forums and not giving back to the community and only trying to take knowledge you in the community will be more successful if you join in and h
elp others and not just try to extract things from other people. Additionally, by engaging with the community, I can't tell you how many people I've met and I've learned and been able to brainstorm with. And then the final step is going to be iterate through these steps. Maybe you get to the end of these and you say, Oh, I'm still blocked, but you'll likely be much, much more knowledgeable. So you want to go back and try these steps again. Now this is where this whole process is a little bit mor
e art than science. Because some questions might not have been discovered yet. Only very few people know not enough people understand the importance of the questions, or maybe people don't understand your question. And this is why it's important to go back and iterate on these steps. Now that you have the basic building blocks of this incredible superpower, I encourage all of you to go out there and try this and then let me know how it went. Alright, awesome. So now that we know more about how t
o get unblocked, we can move on. The reason it's so important to learn how to get unblocked is because blockchain and web three is more than just everybody on their own. It is a very collaborative space. So as you get better, and as you learn more a massive way to test how much you've learned and give back to the community is to going to Stack Overflow and going to stack exchange them and trying to answer some questions yourself. So I highly recommend you all go to Stack Overflow, and then you g
o to the GitHub repo associated with the scores, you try to answer some discussions, try to answer some issues and help other people out because it's going to help you become a much better software engineer. The other reason I want to do that part is because when we install some of the tools that I'm about to show you, sometimes the installation process is the hardest piece there. Once you get past the install process, it generally becomes much, much easier. But this can often be the hardest par
t of the course is just installing some of these tools that we're going to give you. And that's what we're going to learn about right now. So we have been working so far with remix, remix IDE, or integrated development environment. As we've seen, it's this wonderful place where we can try out code we can try solidity out, we can compile we can deploy, we can pretty much do everything that we need to do. It's web based. It can do testing, debugging, deploying local JavaScript VM, it's very quick
and easy to create and test our smart contracts. However, it does have some limitations. It can really only deal with smart contract, it can't really integrate with other parts of projects. It has limited support for tests or custom deployments. And you need an internet connection to even work with remix and it can be tricky to do a lot more advanced functionality. So it's a phenomenal tool and absolutely if you're looking to do something very quickly, I absolutely recommend everybody just go to
remix to go ahead and try something out how are now we're going to move over to a more professional smart contract developer setup. And this is with hard hat. This is known as a smart contract developer framework similar to brownie or foundry or, and likes, there's a number of these frameworks. And the reason that we're going to do hard hat is because hard hat is JavaScript based. It's a JavaScript based development environment. It's got JavaScript based compilation, environment, deploying, tes
ting, debugging. Now, for those of you who love TypeScript, we will also have TypeScript editions of every single one of our code examples for you. So if you love JavaScript, we got you, if you love TypeScript, we also got you we're not always going to walk through us doing the TypeScript. But we will sometimes, and all of the code for the TypeScript will be available in the GitHub repo. Now, before we can actually learn hard hat, we have to learn another package first. So we're going to learn h
ow to do everything with ethers. Jas, which is a JavaScript based library for working with smart contracts. And it's also what powers the next tool that we're going to be working with, which is hard hat under the hood of hard hat. There's a lot of ethers Jas. So it's important for us to learn ethers Jas so that we can understand what hard hat is actually doing. 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 edi
tors on the planet. And if you've already got it set up, feel free to go ahead and skip this part. If you already have a professional coding setup with no GS and VS code, and Git and everything, feel free to use the timestamps in the GitHub repository. To skip over this setup section. You'll often hear people refer to this as VS code, or Visual Studio code or just Visual Studio. However, it's important to note 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, make sure you're on Visual Studio code. Now, if you choose so and you're a total Harto, 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 actually set it up whatever way that you feel comfortable. And of course, in our lesson six here, we have a link to installation and setup. And I'm going to be adding more links as we go about here. And once again, all the code that we're going to be working with is in this GitHub repository down here where it says code. Now we're gonna go through three different installation processes and pick the one that's most appropriate for you. The first one is going to be for M
ac 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 Git pod installation. Now, I highly, highly recommend that you try to get everything working locally without using Git pod. However, if for whatever reason, you can't get those installation pieces to work, we will have Git pod instructions for all of the repos th
at 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 goi
ng 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. Once you have Visual Studio code installed, the next thing that we're going to want to install is going to be node j s. And again, we have links to all of these in the GitHub repo associated with this course, you can just go ahead and click download for Mac OS or download for Linux, I recommend u
sing the LTS version. lts stands for long term support, which means that they will be supporting this version for a long time. So go ahead and download Node js. I've already downloaded this, so I'm not gonna go ahead and redownload this now one of the awesome things about Visual Studio code is it has this thing called terminals, which are command line prompts that allow us to run scripts, basically, it's where we're going to be running all of our code where 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 Z ca or some other type of shell type that you have doesn't really matter because on Mac and Linux it's going to be Linux based we can now test our no Jess installation has been done correctly by running Node dash dash version, and you should see something that looks like this. The exact version of node that you have doesn't really matter here. But ideally you're at least on Node vers
ion 14 or higher. And if something like this doesn't show up, remember to go ahead and start looking at Stack Overflow looking on the GitHub repo in the discussions tab, looking on the updated section, etc. 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 Etherium, and the GitHub repo to move past any issues you run into. Now, if you're on Mac or Linux, you can actually hit Ctrl bac
k 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. Because 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 no jazz is known as a JavaScript runtime. And it's a tool that we're going to use to help run JavaScript code in our Visual Studio Code slot exactly JavaScript. And the difference between no Jas and JavaScript can be
a little bit confusing, but don't let that stop you for now. Next, we're actually going to go ahead and install 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 macOS, if you just type git on the command line, it should go ahead and prompt you to install it. So we're back in our command line, and we just type git, it should prompt you to go ahead and stall it. And if you do get dash d
ash version, you should get something that looks like this. You can also use a Mac OS get installer by clicking this link here and running through the installation process. Alright, now that you have no JS yet in Visual Studio code installed, we can continue on to the next section. Awesome. If you're not planning on using Windows or get pod, feel free to skip the next two sections. I'm running this on Windows 11. However, it should work on most editions of Windows. So the first thing that we're
going to want to install is Visual Studio Code, which looks something like this, it should auto detect it. And we're gonna go ahead and download this for windows in a walk through all the installation process. Go ahead and create a desktop item, we'll add this just in case we want to open with code. And we'll go ahead and install. And then we'll go ahead and finish. Once you've installed Visual Studio code, you'll see something that looks a little like this, it'll go ahead and give you this get
started with VS Code section where you can choose some themes, and you can choose kind of the way it looks feel free to customize it the way that you want. If you want to learn a little bit more about Visual Studio code, I highly recommend you walk through this section to learn more about the shortcuts and making your development experience more efficient. When you're done, you can just go ahead and close the tabs at the top. And it'll look a little something like this. Once we have Visual Studi
o code installed. The next thing that we're going to want to install is node j s. And of course, we have a link to installing this in the GitHub repository associated with this course, what we're going to do is we're going to go ahead and come to node j s.org. To download this for Windows node. JS is a JavaScript runtime environment, it's not exactly JavaScript. And the distinction can be a little bit confusing, but just know it's going to help us run our JavaScript code for our development envi
ronment. Let's go ahead and download the LTS or the long term support edition of no GS. We'll go ahead and we'll run through the setup wizard. And we'll go ahead and make sure that this is clicked just in case we ever want to use some different tools with our setup. And then we'll go ahead and click Install, you'll get a pop up asking if you really want to install this on your device. And we'll go ahead and hit yes. And then we'll hit finish, you might get a pop up that looks like this, go ahead
and click any button to go ahead and install the tools, go ahead and press any key again. And you'll likely get a Windows PowerShell screen pop up asking you to go ahead and install a whole bunch of different projects and files. If you chose not to install this, that's totally okay. But in the future, this will be really helpful since we are going to use a lot of tools that this package installs anyways, this might take some time to install. So go ahead and be patient. And if it gets stuck, it
might just be waiting for you to go ahead and hit enter. So go ahead and hit Enter for any prompts. But yes, please be patient with this, it can be a little bit slow to go ahead and install everything. Once you have all that installed, you can come back to Visual Studio code. And we're going to go ahead and open up a terminal. To do that we hit terminal and we hit new terminal terminal is going to be our command line prompt where we're going to basically run all of our scripts to work with our c
ode. And if you run Node dash dash version, you should see something that looks like this to know that you've installed Node js correctly. Now this command line is known as Windows PowerShell. If you want to work with Windows PowerShell, you absolutely can. In fact, if you want to be a total Harto, and write all your code through Windows PowerShell, you can absolutely do that as well. However, we're actually not going to be working with PowerShell We're going to be using a tool that makes our Wi
ndows environments more like Linux. The reason that we're doing this is Linux is the standard for most development environments. And having everybody work on a very similar setup will make the rest of this course a lot easier for everyone to interact with each other, no matter what coding environment, they're working on. WsL stands for Windows subsystem for Linux, and allows Linux programs to run natively on our Windows environments. To get this setup, we're gonna go ahead, go to the WsL install
. And we'll have a link for this as well in our GitHub repository. So what we're going to do, you must be running a Windows 10, version 2004 or higher, or Windows 11. If you're using an older version of Windows, you can absolutely continue with PowerShell. But you might run into some issues where all the commands don't work exactly the same. So I highly recommend working on a newer version of Windows. To install this back in your Visual Studio Code, PowerShell, or just the PowerShell app, or run
ning WsL dash dash install. Now if you get this error, the requested operation requires elevation, it means that we have to run our Visual Studio code or our PowerShell application as administrator. We close out our Visual Studio code. And right click it and say, Run as Administrator, we get a little pop up saying Do you want to allow this app to make changes to your device, we'll go ahead and click Yes. And then we'll reopen the terminal. And then we can run WsL space dash dash install. And we'
ll go ahead and install WsL. This may take a little bit so please be patient. Once it's completed, you'll see something that looks like this, we're going to be working with Ubuntu. And we have a list of different commands to change your Linux distribution. If you choose to do so. And you'll see the request set operation is successful changes will not be effective until the system is rebooted. So you'll want to go ahead and restart your computer. There's also a troubleshooting guide in the GitHub
repository. If you run into issues after you restart your computer, you'll be prompted for a name for your new system and a password. This can be different from your Windows name and password, and then just follow through with all the prompts. And then once you're done, you'll be dropped into a Ubuntu shell, and you can run Linux commands. Now you'll have a Ubuntu instance, on your machine. And you'll be able to run Linux commands in your terminal. Now that we have WsL set up correctly, we're g
oing to head back over to Visual Studio code. Once we have WsL, we'll want to go ahead and install an extension. So in our Visual Studio code, we'll go to Extensions, and we'll look up remote development you can install the whole thing or just remote WsL we're gonna install the whole thing you can follow along to get started with remote WsL if you like, or you can just follow along with me right now. Right now if I go to the terminal and hit new terminal, I'm still gonna get PowerShell we actual
ly want this to be our Linux shell. So there are a couple ways to open Visual Studio code up in our Linux environment. One way is you're gonna hit Ctrl, Shift P and type WsL. And then click remote WsL new WsL window, and you'll get a new window that looks like this, you can also click the bottom left and choose New WsL window. Now if we go to our terminal and hit new terminal, we'll be dropped into a bash shell and we can run Linux commands in here. Awesome. Another way we can open up Visual Stu
dio code with WsL on is we can go into our your boon to application, we can make a folder by typing MK dir folder, we'll CD or change directory into folder and type code period. We'll go ahead and trust the authors in here. And this will open up Visual Studio code already connected to the folder that we're in. And we can create files in this folder like hi dot txt, and those will get created inside the folder in our WsL. Now that we're inside our WsL environment, you'll notice that node dash das
h version doesn't work anymore. That's because we installed it on our regular Windows machine and not on our WsL or Linux environment. The reason we installed it on a Windows environment first is that just in case you wanted to go ahead and use PowerShell or user Windows environment to run everything you still can just remember if you use the Windows environment and PowerShell all the commands that we use might not work for you. So we're gonna go ahead and install Node js on our Linux environmen
t. Now, all the commands that we're going to write are going to be in the GitHub repo associated with this course. We're going to do a curl command to the nvm repository, which stands for node version manager. And we're going to pipe the install script into bash. And this will go ahead and install and VM. After running that, go ahead and trash the terminal, and then reopen it. And then we can type MBM dash dash version to see if it actually installed correctly. Once we've installed nvm, we can g
o ahead and install no GS using nvm. Just type npm install, and we'll do 16 point 14.2 Is that same long term support version we installed on our Windows machine. Once we have it installed, we can type in Node dash S version. And now we have no JS installed. Now I know there was a lot here, but if you made it this far, this is fantastic. You've done a great job to push through to this point and get everything set up so you can code in the best environment there is. So if you've made it this far,
huge congratulations. Now the next thing that we're going to install is Git. And now we're not going to use Git for this lesson. However, we will definitely be using it in the future. See if gets installed type git dash dash version, sometimes Linux will automatically come with Git installed and you'll see something output like this. If you don't have Git, we can just look up the get install. Which again, link to this is in the description. And you'll actually run the installing on Linux. Now a
gain, now if you want to use PowerShell, and you want to do everything with Windows, you can absolutely follow the installing on Windows instructions here instead, when you're working in WsL, you'll want to use the Linux commands instead of the windows commands even though you're on a Windows because WsL makes it so that you're basically running in a Linux environment. 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 Linux even though you're running on 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 Ubuntu. 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 five. The lesson that we're
on right now, ethers, jazz, 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 get 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 th
at you can 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 good pop. 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 promise that for this
course, you're not going to be using a meta mask 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 get pot 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 get pod button, you'll get a welcome to get pods showing up. We're gonna go ahead and continue with GitHub. Since you've signed up for GitHub here, you want to go ahead and authorize g
et pod. 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 git pod here, that's how you know that you're running off of Git pod. If you see this pop up, 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 Git pod 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 sam
e 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 Git pod, 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 are running locally with Visual Studio code. To open up the terminal, you can hit this little bar at the top left, go to terminal, new terminal, or use CTRL tilde exact same as Mac OS and Linux keyboard shortcuts to create a new folder, we can change directory, CD, dot.mk, dir, new folder, MK dir makes make directory called N
ew Folder. And then we're going to change our directory into a 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 GitHub, 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. All right, this is fantastic. At this point, you should be set up with Visual Studio Code no Jas and get. And I'm going to be working ou
t of a folder called Hard Hat Free Code Camp at this point, you should have node, dash dash version, get dash dash version. And if you're using Windows, this should say WsL or your boon to 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. Oftentimes, 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 tha
t 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 Ctrl 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 to a couple of enters here, and we're down here, if I hit the trashcan, 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 I hit the trashcan, and then pull the terminal back up, you'll see it actually refreshes mine a special command that prints stuff out. trashing your terminal is basically deleting whatever's running in it, and the x is just hiding it. And as hitting Ctrl tilde 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 trashcan, and then we
pull it back up. Alright, so now we're gonna start working with ethers. And we're going to start learning to code, our transactions and our contract deployments and everything programmatically at a relatively low level. And we're gonna learn how to deploy and interact with the contracts using the ethers JS package. Now to get started, I'm going to recommend you create a folder where you're going to put all of your projects in it, I'm going to create a new directory called H H. hyphen, FCC, whic
h stands for hard hat Free Code Camp. And once we run that command, we can cd into hh FCC. And this is where we'll create all of our projects for this course moving forward, so that we have them all in one place. Now to get started, whenever you create a new project, you always want to create a new folder. So to create a new folder, we're going to do MK dir, and we're going to call this ethers, simple storage, like that. And now, if you type ls, you'll see that there is one folder named ethers,
simple storage. ls is how you list all the contents of your folder. You might have a lot of other folders in here, I only have the one since I created this new folder for this. Now what you can do, you can type code, ethers simple. And then if you hit tab, it should autocomplete for you. And if you enter, Visual Studio code should open up a new Visual Studio code for you. That is inside of either simple storage if you open up your terminal now, your home directory for this workspace is going to
be through simple storage as this is what pops up. If that doesn't work for you, we can also do is you can hit File, Open folder and then open the folder that you just created or that you want to open this again we'll open up VS code. And if we open up our terminal we see we're inside of ether simple storage. This is so powerful because as we create files we'll be able to See those files in our Explorer here, this button here stands for the Explorer. If we click it, we can see the different file
s in here. And I'm going to go ahead and actually delete this file dot txt, because we're not actually going to use that. Now it's this part of the course, where we're actually going to start jumping into some JavaScript. Since this course is in JavaScript course, if you're unfamiliar with JavaScript, it might be a little bit tricky. If you want to come into this with a better understanding of JavaScript and Node js, there is a Free Code Camp YouTube video teaching No, Jas for beginners. And a l
ink to this will be in the GitHub repo associated with this course. There's also a JavaScript Free Code Camp video that I'm also going to put in the description for this course, keep in mind that JavaScript and Node js are slightly different. And we are going to go over some of the differences as we code along here. But for the most part, learning one means you've learned the majority of the other. So if you want to pause and go through these videos, before continuing here, please feel free to d
o so you don't have to, you can absolutely continue on with the course as is. And if you get confused or stuck on some JavaScript piece, feel free to pause, Google it and come back. But just to reiterate, you can check out the JavaScript programming full course. And also the Node js full course, as those are both going to help you. Like I was saying before, Node js is a JavaScript runtime. So it's not exactly JavaScript. But we're going to write our code in JavaScript. And if that's confusing, j
ust don't worry about it right now. And as we go through this course, I'll show you where the differences are. But basically, you can think of no Jas and JavaScript kind of being the same thing. The big thing about Node js is it allows us to write JavaScript code in the back end, as opposed to running JavaScript on the front end, JavaScript is made to be a browser run language, like running inside of, you know, Chrome, brave Firefox, etc. No, Jas allows it to become a a scripting language, a bac
k end language, which is why the syntax between the front end JavaScript and the back end JavaScript or the no JS JavaScript are going to be a little bit different. Additionally, as we go along in this code, if you're familiar with TypeScript, all of our code is going to come with a TypeScript edition. TypeScript is what's known as a statically typed version of JavaScript. And it'll be it'll be this one. It'll be TypeScript, not TypeScript edition. I'll go ahead and fix that and remove this one
to make it clear. TypeScript is a type safe version of JavaScript, which is that's confusing, don't worry too much about that. But we are going to do all of our programming in JavaScript. And then if the code is different enough, I'll show you how to do it in TypeScript as well. However, for most of them, we're not going to show you the TypeScript editions, because it's going to be really similar. But you can always refer back to the GitHub repository to see all the code for the TypeScript. Now,
if you're new to this space, I actually do recommend you go ahead and start with JavaScript and learn how to do TypeScript later on. TypeScript actually catches bugs early on, making it a lot easier to code your projects in the long run. However, it does take a lot of extra typing. And it can be a little bit frustrating learning how types work for beginners, JavaScript is a little bit more loose as a language and lets us kind of do whatever we want, but it can cause a headache later on. So if y
ou do run into some issues, and you do run into some bugs, it might be a good idea to try TypeScript on for size, and see how that fares. Well. Let's go ahead and begin working on our local development environment and getting set up to do everything in ethers Jas and in JavaScript. Oops. And I actually went and renamed this folder to ether symbol storage dash, FCC. Reason I added this dash FCC is all the GitHub repositories associated with this course, all the GitHub repos that have this dash FC
C to know that it is part of this hard hat JavaScript course. Awesome. Let's jump in. Let's start working with solidity and our smart contracts locally in Visual Studio code, as you can probably tell by the name of this folder. And of course, if you looked at the code, this project is going to be our simple storage project, but developed locally using ethers. So the first thing that we want to do is want to get in that smart contract code. So what we can do is make sure we have the Explorer sele
cted, we can go ahead and right click and select new file and do simple storage. So just close this for now. And we can copy paste our simple storage code from our last section into VS code. If you closed remix or you forgot where it is, you can just go to the ethers simple storage FCC repo, it's simple storage dot Sol, and we can just copy all the code in here and then come back over select Symbol storage that Saul and paste it in. Now an important note about Visual Studio code is that when you
see this little white.up here, it means that this file isn't saved to save your Git file. To save, and it'll go away like that. Or what you can do is you can hit command S or Ctrl S, depending on if you're on a Windows, Mac, or Linux. Now you'll see here that this code is a little bit hard to read the simple storage dot salt, it doesn't have the syntax highlighting that we saw in remix. So we want to go ahead and add a Visual Studio Code extension to give this syntax highlighting. So what we ca
n do is come over to this bar over here looks like this. And if you don't see it on the left hand bar, you should click these three dots, and it should be in here. But we'll go ahead and click Extensions. And what we're going to do is we're going to look up, solidity plus hard hat. And we're going to install this solidity plus hard hat extension. For VS code. Now that we have this installed, if we go back over to our simple storage dot sole, you'll see that all the highlighting is back in. And n
ow it's much easier to read. Right? So this is good. We have our code in here we have our syntax highlighting. Now let's add an auto format or or default format or right now our code is pretty good with the way that it's formatted. But what if we, we accidentally do some stuff like this or like this, or maybe even like this, we add a ton of new lines, etc, our code can start to look pretty gross. And even though the code itself is fine, and it'll run the exact same way, with all this extra white
space, it doesn't look very good, right. And due to that, it can be a little bit hard to read. What we want to do, then, we want to open up our settings and adjust our vias code so that it auto formats whenever we save, so whenever we save, so that whenever it goes from the little white dot here to no white dot, this whole thing gets automatically formatted to some looks really nice. Okay. So what we can do is we can open up our command palette to open up our command palette, you can hit View co
mmand palette, and we'll get a little pop up that looks like this. Another way to open up your command palette is you're gonna hit Command, Shift P, or Ctrl, Shift P, depending on your Mac, or Linux or Windows. And what we want to do is we want to type in settings, and we're going to open Settings JSON, we don't want to open the default settings JSON. We don't want to touch these. But we want to open our JSON settings. You'll also notice there are user settings and workspace settings. These are
pieces that we can adjust as well. But we're going to just go right into the JSON settings. So So I already have some stuff in here, but yours might be blank. Or you might have some stuff in here as well. So what we're going to do is if you have stuff in here already, we're going to add a comma, then we're going to do quotes, solidity. Close the brackets, we're gonna do a little colon and something like this. This means that we're going to apply some settings to our Visual Studio Code. Whenever
we're working with solidity, one of the things we're going to add in here is going to be an editor, Doc's default, for matter. And you might even get a pop up that tells you some different things that we can use for a default format or our default format, or is going to be Nanak, foundation, dot hard hat, hyphens solidity. This will mean that any time we go to format our code, it'll use the hard hat solidity plug in, as its default format, or the hard hat solidity plugin comes with some formatti
ng, and a lot of other really useful tools for us writing our code. So now that we have this part in, the next thing we're going to do is add format on Save. If we haven't already, we could add it in here in our JSON, but I'm going to add it not in the JSON file, I'm going to add it in the overall file. So if we open that command palette back up, and we type in settings, open user settings, this is another really good place where we can look in add settings with the UI. So these two do essential
ly the same thing. It's just that this one has dials and a little bit more context versus settings that JSON just says Okay, give me the raw code for it. This tells us a little bit more. So you can use either one. But we're going to look for format, on save. And you're going to want this checked if you haven't already. This means that every time we save VS code is going to try to format our code for us. So now that we have this checked, we have settings dot JSON added in. And remember, we want t
o save this. Remember, if you see this white dot, that means not saved. So you're gonna want to save it and close it out. Let me close this out too. If we come back in here and we add a bunch of random new spaces or whatever, you want to make it look a little bit ugly, and then we save it. It should automatically reformat to look much nicer, right. So if we do something like this, we'd save it reformats it to look much nicer this one make them more readable for you, and more readable for anybody
else who looks at your code. And it's just really nice. And this line of code for your settings dot JSON is located in the full blockchain study course.js. So you can also just copy paste it, we are going to end up overriding that default format or with another format are called prettier pretty soon. But it's great to have a default format or so that if you don't feel like adding the prettier code sometime in the future, you can just rely on your default formatter. Awesome. While we're doing fo
rmatting, let's also add a default format or for our JavaScript code. And just to test it out, let's go ahead and create our new file, we'll call it deploy dot Jas. And in here, we can do something like function Hi, console dot log, hi, and then just add and then just make it look kind of gross, maybe something like this. If you hit save, and it does some auto formatting, that's great, you can actually turn that off by going back to your command palette, and saying, Save without formatting. And
that way it will be saved and not formatted. The way we can add some other formatting here is we're gonna install another extension, this one is going to be called prettier. So we can just look up prettier and extensions here. And you'll want to install this prettier code formatter. So we're gonna go ahead and install this. And great, now it's installed prettier is a form is a code format, or that works for many languages like Python, JavaScript, and even solidity. And pretty soon we're going to
use prettier for both JavaScript and solidity. But for now, we're just going to use prettier for JavaScript, we can enable this by opening back up our command palette, we'll go to preferences, open Settings. And the same way we added a solidity section, we're going to add a JavaScript section. So we're going to add a comma here, some quotes, brackets, we're going to type in JavaScript, close that colon brackets. And we're going to do the same thing at the door dot default, or matter. Net we're
going to do and then in here, we're going to do e s BENP, that prettier, hyphen VS code. And this will make prettier the default editor for JavaScript. Now, like I said, pretty soon, we're going to have prettier override both of these for solidity and JavaScript. And we're going to give prettier some parameters so that no matter who uses your code, they will always have the exact same formatting. But now that we have prettier in here as the default editor, if we come back to deploy dot j s, and
we hit save, it should format to look a little something like this. Now, we go ahead and we do something like this. If we go ahead and do something like this, it'll reformat to look like look like that. And then additionally, if you want to go back to the command palette, open user settings, not in JSON mode, and we go to default format, or you can actually even select the default format or for all languages, if you want to use prettier for all formatters. Feel free to go ahead. Alright, great,
got our JavaScript format, or in as well, let's start writing some JavaScript code. Awesome. So now that we have our code in here, it's time for us to learn how to actually deploy our contract using JavaScript. This is going to teach us a lot about transactions and what's going on under the hood, and even what's going on under the hood in remix, and remix, we usually just hit a compile button, and then hit a Deploy button. And that's really it. In JavaScript, we're actually going to create our o
wn functions that are going to help us do both of those. And as I mentioned, this is the part of the course we're going to start working with JavaScript, and optionally, TypeScript if you like. Like I said, all of these sections come with a TypeScript edition as well. So let's set up our deployed out js script to actually deploy our simple storage dot soul. So how can we get started here? Well, let's first learn how to run a script using JavaScript and Node J S. So if you want to do a print line
, or just print something out to your terminal, we can do something called a console dot log. And if I do console dot log, hi, I hit Save. And I open up my terminal. I can now run Node deploy.js. And it'll print out high node is how we say hey, we want to run this JavaScript code using Node js. Other languages you might be familiar with, sometimes we'll do Python, you know, deployed up py, or Java, C deploy dot Java, you know, etc. But with JavaScript, since the front end and back end JavaScript
are different. We run code on the back end with node. And with JavaScript, you can do a lot of things that you'd see in something like solidity with a little bit looser have a structure. If I wanted to create some variable, I could say let variable equals five, this kind of similar into solidity like you and 256, variable equals five. But in JavaScript, we use let or var or const. And then I can print this out, I can do console dot log variable. And I had saved JavaScript is optional on whether
or not you actually want to have semicolons. Here, I think prettier, defaults to putting semicolons. And we'll get rid of those in the near future in your terminal. Once you start typing the name of a file, if you hit tab, it could autocomplete the rest of the file name for you node deploy hit Tab, it'll autocomplete and if we hit enter, now, we get Hi, and then we get five. Since this prints out Hi, and then it prints out five. JavaScript automatically starts with whatever code you have at the
top of the file. So it does console dot log first and variable. And then this one as well. However, a good practice is to actually wrap everything you want to do in a main function, and then run that main function. But what we could do is up at the top here, we'd say function, mean, add parentheses and some brackets, a closing bracket at the bottom, and hit save for its auto format. Right now, if we run this, nothing will happen, because we've wrapped all of our code in a main function. So if I
run it now node deployed to Jess, nothing happens, because I need something to call the main function. So if I then take this, this main function down here, and I call main, our jobs from code is actually going to say, ah, the first line of the script is actually this main function here. So now if I do node deploy dot j, s, it'll run high and five, which is what we want. Now, this is going to be the setup for most of our scripts moving forward, including the scripts that we write, when we get t
o hard hat, however, there is going to be one major difference. Instead of regular functions, we're actually going to use something called async functions. And we're going to do something called asynchronous programming to do this. Now, if what I say next is really confusing for you don't let it slow you down, feel free to go ahead and watch that JavaScript course to learn more about this. But I'll also let you know, hey, this is an async function. Here's what we need to be aware of when working
with it, okay. But I do want to give you a quick bit background on asynchronous programming. So far, the programming that we've done has been synchronous. And solidity is an example of a programming language, that synchronous, Synchronous means it just goes one line after another. If our code looks like this, this is synchronous write, our main function is the first thing that actually gets called. Then we do console dot log, that variable equals five, and then console dot log. Again, this is s
ynchronous programming in JavaScript, all of our solidity is synchronously programmed. There will be some exceptions to this when working with oracles. But for now, everything is synchronous. JavaScript can be asynchronous, meaning that we can actually have code running at the same time. A good example I like to use to understand the difference is with cooking. In synchronous programming, for cooking, you might put popcorn in microwave, wait for popcorn to finish. And then, and then maybe you'll
pour drinks for everyone. And now this is synchronous programming. Now, it might be a little bit weird for you just to put the popcorn in the microwave, and then just stare at it, waiting for it to finish. And then pour the drinks, you typically can pour the drinks while your popcorn is in the microwave. And this is where asynchronous programming comes in. If setting up for this movie night, we're asynchronous, what you would do is you'd put popcorn in the microwave. And while the popcorn is in
the microwave, or drinks for everyone, and then you'd wait for popcorn finish, since there's nothing left for you to do, but it doesn't make sense for you to wait for the popcorn to finish to pour your drinks, you can just go ahead and pour the drinks right away and then wait for the popcorn to finish. So asynchronous programming is way for us to do stuff without waiting around for things to finish. And this is really advantageous in JavaScript by default allows us to do this asynchronous progr
amming, however, sometimes we do want to wait for our popcorn to finish. For example, if instead of just pouring drinks, maybe the next thing instead of pouring drinks was placed salt on popcorn. Of course, if we want to play salt on our popcorn, we do have to wait for the popcorn to get out of the microwave. So even though placing popcorn in the microwave has this wait time we need to be able to tell our code I want you to actually wait for it or No, you're good. You can go on and do another ta
sk. So that's kind of the difference here. And I'll leave some links in the GitHub repo associated with this course to understand this a little bit better functions that have functions that come with this waiting period return something called a problem. This, if put popcorn in the microwave was a function in JavaScript, it would be a promise based function. A promise can be either pending, fulfilled, or rejected. And this is how we know if our popcorn is done. If our popcorn was a method, putti
ng popcorn in the microwave, were a function in JavaScript, when we're waiting for the popcorn to finish, it's in a pending state. When it's when the popcorn is finished, it would be fulfilled. And if we aborted halfway through, and we stopped waiting, it would be rejected. So putting the popcorn in the microwave returns a promise. With this promise, we have to tell our code, hey, we want you to wait for the popcorn to finish or you can go ahead and you can just keep doing stuff. So let's put th
is all together with some JavaScript syntax here. Let's say again, we're going to be setting up this movie night. And we need to cook popcorn, pour drinks for everybody. And then we need to start a movie. So let's write some pseudocode to pretend what this code would look like if this was actually a function. So we create some function called setup, Movie Night. And in here, we would say okay, what's the first thing we need to do? Okay, we need to cook popcorn. So let's say we have some cook pop
corn function. So we'll say, okay, cook popcorn, then the next thing we're gonna have to do is we're gonna have to pour drinks, or drink. So we'll call some pour drinks function. Now here's the thing, we only want to start the movie once our popcorn has been cooked. And once our drinks have been poured, so if either one of these returned a promise, so if either one of these returns a promise, like cook popcorn, for example, we would need to tell our code here to actually wait for the popcorn to
finish because cook popcorn is going to be a function where we could say let status equals cook popcorn. And while the popcorn is being cooked, the status is going to be ending. Once the popcorn gets cooked, it'll be fulfilled. If the popcorn breaks, the microwave explodes, the status would be rejected. But we don't want the status to be in a pending situation. Before we move on, we only want to start our movie once these two functions have completed. And let's say both of these return these pro
mises things. So we need to tell our code, hey, you have to wait. Or you have to wait for cook popcorn and for poor drinks to finish. So what we can do now without getting too deep into the weeds on how all this works, one of the easiest things that we can do and you'll see us use this syntax quite often is we'll turn this function into an async function. When our functions are async, we get access to a keyword called await the await keyword tells any promise based function to wait for that prom
ise to be fulfilled or rejected. So we say okay, we want to await for our popcorn to cook. And then we want to await to pour drinks. And then we can just go ahead and start the movie. And we only start the movie here once these two have been completed. And this is why throughout all of our code, you'll see this await keyword used a lot. But it can only be used in async functions. So basically, whenever you see this await keyword just now Ah, okay, the function that's being called is promise base
d. And we don't want to move on to the next step until that function has completed. So that's a little bit more about promises and asynchronous programming. Hopefully, that's clear. If not, like I said, there's some links in the description to learn more about asynchronous programming. The reason I wanted to go through this is because most of the functions that we're going to be working with are going to be asynchronous. For example, when we deploy a contract, what do we have to do? Well, we hav
e to wait for it to be deployed. If we don't use synchronous programming, and we just leave our function main like this, what would happen is we would write some code like contract dot deploy, and we wouldn't wait for it to finish. Obviously, if we don't wait for it to finish, and we try to run some code on a contract that hasn't finished deploying it, it's not going to work. So we want to do this, we want to have our main function be an async function, so that we can we can wait for our contrac
ts to deploy, we can wait for things to happen, we can wait for our popcorn to finish, we can have the flexibility to tell our code to either wait for our popcorn to finish or continue on. So now that we have our main function as an async function, we're going to add some code to our main function down here. And the code that's added here is some syntax for working with asynchronous functions. And if this part is confusing, I'm just going to say for now, absolute, don't worry about this. If you
want to try to understand that later. That's fine. But for those who are following along, we're just going to add an add then catch air air you can follow along typing this yourself or you can just copy paste it into your code. Basically what this allows us to do is we have our main function, that's an asynchronous function. So when we call the main function, this is some other syntax for waiting for it to basically finish and then printing any errors it gets. And that's why we do this but Again
, if this big lump of code, if you're like what is going on with this big clump of code, honestly, for now, just copy paste it. So great. We have our asynchronous function main, we have some code. And then we have this lump of code, which basically just calls our main asynchronous function. Okay, great. I'm gonna delete all this for now. But you can still find that common in the GitHub repo associated with this course. Awesome. Okay, so now that we have our real basic setup, let's go ahead and s
tart coding. And if this set apart is confusing, and the async await stuff is confusing, don't worry too much about it. It'll make more sense as we progress. All of our code basically is going to be inside of this async function main, which is going to be our main script for deploying our simple storage dot soul store deploy script is going to replicate exactly what goes on in remix, in remix, what was the first thing that we always did? Well, the first thing that we would do is actually compile
all of our code. So we're going to want to compile our code in our JavaScript project as well. In order for us to compile our simple storage contract, we're going to use a tool called Silk Jas, and JavaScript actually has a way to install projects directly into our setups and into our folders. If we scroll down this silk Jas is exactly what we're looking for. Because it has a way to compile a contract that imports other contracts via relative paths, you can see a section in this readme and most
documentation will have something like this, if it's JavaScript compatible. For Node js usage, it says to use the latest stable version of the solidity compiler via Node js, you can install it via NPM npm install. So NPM is what's known as a package manager. And we actually installed NPM just by installing no Jess, right, if we do no dash dash version, you should also be able to do NPM dash dash version. Another tool that it comes with is something called core pack. And you can type core pack d
ash dash version, now we can install with NPM using npm install silk, however, I like the yarn package manager a little bit better. So we're actually going to install the yarn package manager instead to do all of our package management. If you go to the installation page, the newer way to install yarn is just by running core pack enable. And the older way is to install with NPM. If you go ahead and run core pack enable after that finishes, you should be able to run yarn dash dash version. Altern
atively, you can just run NPM i dash g core pack, and then you can run core pack enable. The last option you have is you can run NPM i dash g yarn. This will install yarn globally for your system. But this is considered the outdated way to install yarn. And ideally you run core pack enable. But in any case, after you run those, if you run yarn dash dash version, you should get something that looks like this. Now that we have yarn, we can actually use yarn to install all of our projects, instead
of NPM. Back in silk Jas where it says npm install soak, we can do the yarn equivalents of NPM install sock, which is going to be yarn, add sock, this will actually go ahead and install solc to our project. If we open up our folders, you'll actually see that this added a couple of different folders, it first added a package dot JSON package dot JSON is a file that tells us a lot about our project and the dependencies that it works with. For example, we've installed the soap package of 0.8 point
13. Our yarn dot lock tells us the exact version of all the different packages of our project. For example, the reason this is so important too, is solc has a ton of dependencies as well. So yarn dot lock tells us exactly what version of solc and all the different dependencies of solchen. Any other project that we add. This is autogenerated file, don't edit the file directly. The final bit is we got this node modules folder. This node modules folder is going to be where all the installed code th
at we just downloaded is, for example, if we look at node modules, we can see there's a sock folder. And inside this sock folder is all the code associated with this soap package that we just installed. And since we're working with zero point 8.7 of slowly, we actually want to install that specific version. So we're going to do yarn add solc at zero point 8.7 Dash fixed and you'll see in our package dot JSON you can now see zero point 8.7 Dash fixed in our dependencies section for sulk. Normally
you can just add your salt version like yarn add zero point 8.7 But there was an issue with zero point 8.7 So we had to do zero point 8.7 Dash fixed. You can find the different releases and the different versions if you go to sulk Jas releases and then to tags Alright, great. Now that we have sold, we have the ability to actually compile our contracts, we could either compile them in our code and have it automatically run whenever we hit Deploy, or, or we could compile them separately. If you w
ant to go back after this section is an example in the sculpt Jas repository that shows you how to actually compile silk right in your code. We are actually going to compile them separately using a soap Jas command. The yarn command is both used to install dependencies and it can be used to run scripts. If you go to sulk Jas and you scroll down, it says in order to use the command line, you actually need to install it globally. If you want to install this globally using yarn Global Add solc at z
ero point 8.7 Dash fixed you can absolutely go ahead. However, since we're inside of this folder here, which has the yarn dot lock the package json and the node modules yarn will be smart enough to know i You're looking for the soak in this folder. So we can actually go ahead and compile our contract using yarn and solc Jess if you want to see all the different commands soak Jas allows we can just run yarn. So Jas dash dash help, and you'll see it'll spit out a list of all the different options
that soft Jas has. You can also run yarn, so Jas dash dash version to just make sure that we're on the correct version, which is indeed zero point 8.7. Now to actually compile our simple storage at soul, let's run the compliation command we will run yarn, so J S, dash dash bin since we want the binary dash dash ABI since we also want the ABI dash dash include path node modules. Since we want to include any contracts or files in our node modules, we aren't using any for this project, but in the f
uture, you will need to include this dash dash include path node modules do dash dash base path of period, this period means that the base path is going to be this folder dash O period, which means we're going to output the compiled binary and ABI to this folder. And then finally, simple storage dot soul. Since this is the contract that we want to compile, auto completed it from simple storage to simple storage. So by typing simple, and then hitting Tab, but let's go ahead and hit enter, you'll
see it's running this command to compile this contract. And you'll see two files get output. One called Simple Storage soul underscore simple storage that API in simple storage Sol underscore simple storage dot bin, the ABI is obviously the ABI of this contract, which will need in the future. And then the bin is going to be the binary, or the really low level of this code back and remix. If you compile simple storage, that soul, you can actually look at compliation details, like the ABI which we
just got, or the bytecode, which if you look at this object 60806 That's the same as the binary here 60806. Alright, great. So now we've compiled our contracts here. Now, obviously, now if you hit up on your keyboard, you can actually cycle through your most recent terminal commands. And if you hit up enough, we can see this command that we just ran typing this out or hitting up a whole bunch every single time, it's going to be really annoying to do anytime we want to recompile. So what we can
do is we can add a script section in our package dot JSON to shorten some yarn scripts for us. So what we'll do is back in our package, dot JSON, a lot of comma, and we'll add a section called scripts, add the colon and the brackets. And in here, we'll say anytime we say compile, we will run this long command. So I'd compile we'll put some quotes. And we'll paste that in there. So now instead of typing that whole thing out, as long as we're in the same folder that our package json is in, we can
run yarn compile. And this will run that whole script for us without us having to type the whole thing out scripts are a really useful way to make it easier for us to run long commands. All right, great. Now we have our code compiled, this is going to be equivalent to US hitting this compile button for us to actually go ahead and deploy. So now we have our simple storage. That's all compiled, let's learn how we can actually deploy this thing. Remember, in remix, we actually deployed it to one of
two different places, we deployed it to either a JavaScript VM, or with our injected web three, with our Metamask. Let's learn first ad, do the JavaScript VM. And then we'll learn how to use the injected web three, or a meta mask or some connection to an actual test net. So in order to deploy this to a JavaScript virtual invite I'm in or kind of a fake blockchain, we're gonna need to get a fake blockchain. Now in the future, we're going to be using the Hardhead runtime environment as our JavaSc
ript virtual machine or aka our fake blockchain. But for this section, I want us to use a tool called ganache. There's a link to this in the GitHub repository. Ganache is similar to a virtual machine in remix. It's a fake blockchain that we can run locally to actually test, deploy and run code. It's also a nice way to see things that are going on in a blockchain. Let's go ahead and spin up the ganache application after you install it, the ganache application will look a little something like thi
s. And to spin up a fake blockchain really quickly, you can just go ahead and click Quickstart. This will spin up a fake blockchain that's running locally on your computer right here, which is fantastic. It comes with a whole bunch of fake accounts exactly like how remix comes with a ton of fake accounts with 100 ether each ganache comes with a bunch of fake accounts with 100 ether each. They also come with the private keys that we can use in our applications to actually take control of these fa
ke accounts. Remember, don't use these private keys on a public blockchain. They're for development purposes only because a lot of people know these private keys in our code. One of the first things that we're going to need to do is actually connect to our blockchain remix does this a little bit behind the scenes, if we're choosing JavaScript virtual machine remix chooses its own fake blockchain that it runs. If we choose injected web three, as we know, meta mask pops up, and it connects to our
meta mask, this connection that remix does, is actually doing something really interesting. It's not just connecting to our meta mask by some magical powers. It's actually connecting to our meta mask, which has a connection to the blockchain behind the scenes. If you open up your meta mask, and you go down to you select the networks and you select ad networks, you'll get popped up into a UI that looks like this. If we go back and hit select networks over here, we can actually see information abo
ut these different networks. One of the main things that we can see is that all these networks have something called an RPC URL. RPC stands for remote procedure call. And then URL is uniform resource locator. This RPC URL stands for a connection to a blockchain node that somebody is running this this URL connects us to make API calls and to interact with a blockchain node. Blockchain nodes run with software, and some of them expose an API call. If you look at the NGO Aetherium website, there act
ually are instructions for you to run your own blockchain node for a real blockchain like Aetherium. Most of these have flags like dash HTTP dot ADR to expose these RPC endpoints. So if you ever want to run your own node, your own real blockchain node, instead of using meta masks or any other the providers that we're going to go through, you can use go Aetherium, or whatever blockchain you're working with software to run your own notes. But it's this RPC URL that allows us to connect to Rinkeby,
if on Rinkeby ropsten, if we're on ropsten main net if we're on Main net, etc. And it's going to be the way that we're going to connect to our ganache blockchain that we're running inside of this application. So if you look at the top of your ganache here, there's a section called the RPC server. And this is the endpoint of our ganache node right now. So what we can do is we can copy this and go back to our VS code, and paste it in here to see if we can connect instead of HTTP. With these capit
als, we're gonna have a B lowercase instead of the uppercase, because the lowercase is more correct, and it looks nicer. But now we have the endpoint. Hypothetically, with just this, we can start making calls and API calls to this endpoint, go to this JSON RPC specification. Again, link will be in the GitHub repo, we can actually see different calls we can make directly to our node to get different information. eath get blocked by hash eath get blocked by number. And all of these wonderful piece
s in here. Making these API calls directly is is a little bit annoying to do ourselves. If you want to do it yourself, you absolutely can using an API endpoint like Axios or fetch. However, we're going to use a rapper to interact with our node and do things like deploy and interact and other such things with our blockchain node. This is finally where ethers comes into play. Ethers js is one of the most popular JavaScript based tooling kits, that allows us to interact with different blockchains a
nd has all these rappers that make all these API calls and do all these things with Aetherium, and polygon and avalanche and any EVM compatible chain. The other incredibly popular package that does the same thing is going to be web three.js. And you've probably heard about this and you'll probably see it a little bit more throughout this course and throughout your web three journey. The reason that we're using ethers is that ethers is the main tool that powers the hard hat environment and I real
ly enjoy it myself. And remember, if you ever get lost with any of this, you can always come back to their documentation to install it. As you can see here, you can just run npm install ethers, we're just going to do yarn, add ethers. And now you should see in your package json, we now have ethers added in here. Awesome. Now back in our code, we're going to import ethers into our deployed.js script so that we can use all the wonderful tools that comes with so we'll say const ethers equals requir
e ethers. For those of you doing the TypeScript edition of this course, this will be import instead of require now that we have ethers in here, we can create our provider object in our main function. The reason we we pull ethers outside of the main function is because we do want to pull our package into our script. Before we call main, we want to make sure all of this is done first. So you'll see this is kind of the the normal setup of our scripts. At the top, we import any dependencies or exter
nal packages, we'll have our main function, and then we'll call our main function at the bottom. const is a keyword similar to let the const keyword makes it so that ethers can't be changed. So we can't change this. Our ethers variable, anytime we use const require is a function for us to import the ethers package. Now remix does all this behind the scenes. But the way we're going to do it in our code here is we're going to say const provider equals new ethers dot providers dot JSON RPC provider
. And then we're going to pass this string as our provider. So we're saying hey, we're going to connect to this URL right here. Awesome. So this is the way that our script is going to connect to our blockchain, our local blockchain. Now let's get an actual wallet here. With a private key and a balance and everything, we can see all of our wallets and private keys in our ganache here. So the way to get this set up is we can say const. Wallet equals new ethers dot wallet. And this wallet function
takes in a couple of input parameters, like a private key, and a provider, the private key will go to Kenosha and just choose one of these private keys. And we're going to paste this right into our code. And then we're gonna do comma provider and save that. Now pasting your private key directly into your code is a huge nono. And we're going to learn how to avoid this in the future. It's okay right now, since we're just using one of the ganache private keys, and you have no risk of having any mon
ey associated with this account. These two lines alone give us everything that we need to interact with smart contract, they give us our connection to the blockchain, and they give us a wallet with a private key so we can sign different transactions. If you remember back to our blockchain basics section. This is the private key that we're using to sign all of our transactions to encrypt our transactions. Now that we have a provider and a wallet, let's go ahead and grab our contract objects from
these two files here. In order to deploy our contract, we're gonna need the ABI and we're going to need the binary compiled code of the contract. So we're going to need to read from these two files to read from these two files, we're going to need to use a package called Fs. So back at the top, we're gonna do const Fs equals require Fs extra I autosave, all the time, you'll see like, I'll do something and then my white dot will go away a lot. It's because my fingers have a habit of pretty much a
nytime I stop typing I save so so please remember to save early and often, this Fs extra should come directly with your node project. But if not, you can always add it with yarn, add Fs extra, and you should see it in our package dot JSON. Now we can get the ABI and the binary, we can say const, abi equals Fs dot read file sync, which means we're going to synchronously read from this file, we could do it asynchronously. But we want to wait for this file to get done. So we're gonna say read file
sync. And depending on your VS code, if you scroll over, you might even get some information about this function popup like this, which can be really helpful, we can see that we need the path for the file we want to read. And then any options as well path the file that we want to read the at the ABI located at dot slash simple storage, underscore soul underscore simple storage dot AVI and then we're going to do a comma of U T, F eight is UTF. Eight is the encoding that we do for this file here.
Don't worry too much about what that means for now. So we need the ABI. And we also need the binary, which is in this second file. Simple Storage underscore soul underscore simple storage dot bin. So we're gonna say const binary equals Fs dot read file sync. We're gonna give it the path Hear, which is going to be dot slash, simple storage soul, simple storage dot bin, and then the encoding option, which again is going to be, and it should look like this. Now that we have the binary, we have the
ABI, we can create something called a contract factory, which is not to be confused with the factory pattern in ethers. A contract factory is just an object that you can use to deploy contracts. So we're gonna say const, contract factory equals new ethers dot contract, factory. And we're going to pass it, the API binary. And the wallet, we pass the ABI so that our code knows how to interact with the contract the binary, obviously, because this is the main compiled code in our wallet so that we h
ave a private key we can use to sign deploying this contract, then I usually like to write a little console dot log, saying something like deploying these wait. And we can actually deploy this contract with ethers by doing const. Contract equals await, contract factory dot deploy. Now, this is the first time we've seen this await keyword and you can only use the await keyword inside of an async function. The reason we want this await keyword we're telling our code to stop here, wait for contract
to deploy. And this await keyword means that this will resolve the promise contract in this contract factory dot deploy with the await here returns a contract object. So now I could do something like console dot log contract. Let's see what happens when we run this code node deploy dot j s, we scroll up, we see deploying, please wait. And then we see this massive object that gets printed out. This is the contract object that we just deployed. And in fact, if we go over to our ganache, we can se
e that the address that we're used for our wallet has a little bit less balance and has a transaction count of one. If we were working with truffle, we'd be able to see the contracts here we're working with hard hat, so you won't be able to see the contracts in here. But if you go to transactions, we can indeed see the transaction that we just created. This is similar to ether scan. But for our local blockchain, we can see the sender address, the creation address, the value, gas price, all this
stuff associated with this contract. You can also see the different blocks. Since we've only made one transaction only one block has been mined. And this is awesome. We have all this other stuff associated with it. Great job. You just deployed a contract to your own local blockchain with ethers. Jas. This is fantastic, Awesome work. Now let me show you what happens if we don't use the await keyword here. We're not telling our code to stop. We're saying hey, deploy this contract and then just kee
p going. So we never actually checked to see if this deploy function finished. So let's see what happens when we run this instead. Instead of that big contract object, we get this promise in its pending state because our code actually finished before our contract could finish deploying. So we see promise pending here instead, this is why the await keyword is so important. We're saying hey, wait for this to finish the await keyword also resolves a promise. So it'll wait for the promise to exit it
's pending state. And then it'll return whatever the pending promise returns. So contract factory to deploy returns a promise that returns a contract. In fact, if we go to the ethers documentation, we look up deploy. And here we can see contract factory methods contract factory dot deploy. If we look at the definition of the function, it says contract factory dot deploy takes a whole bunch of arguments and some overrides this arrow is saying this is what it returns, it returns a promise that res
olves to a contract. And that's why we need this await keyword because contract factory to deploy by itself just returns a promise. But if we do await contract factory dot deploy, we're saying it returns a promise that resolves to a contract. And we're waiting for it to finish deploying to resolve to a contract object. So that's gonna be a major difference here. Awesome work. So that's gonna be why this await keyword is so important. And again, you can only do that in asynchronous functions. So
you need this async keyword at the top of your function names. Awesome work. So we've deployed a contract to our ganache. Shane, this is fantastic. Let's play with this a little bit more. So what else can we do? Remember how in remix and in Metamask, we could add a whole bunch of stuff. We could add a gas limit, we could add some value when we were doing our trends. that we could press the transact button. We know that when we're working with Metamask, and we want to send some money between our
accounts, we can actually choose our gas price, our priority fee, all this other stuff, we can actually do all that in ethers as well. So if we wanted to await contract factory to deploy, but with a certain gas price, we can add these overrides in this deploy function here. Another really neat trick that your Visual Studio code might have is if you click Command or Control, depending on your setup, you can actually click into a function and see where it's defined and see everything about this fu
nction. So if I command clicked, I could see that I'm now in Node modules ethers project contract source of Ts, all this stuff. And I can see exactly the function definition of this deploy function on the contract factory object, which shows us the same code as what we saw in the documentation. We see we have a deploy function, it takes some arguments, and then it returns this little semicolon means it returns a promise that resolves to a contract, which is really nice. These are in here are act
ually a list of overrides that we can specify with some brackets. So what we can do is we can put some brackets in our deploy function here and specify certain things like for example, we can specify the gas price to being some number. And now if we were to run this, we would deploy this contract with a gas price of this, we could add a gas limit, we can add a whole bunch of different overrides in our deploy function here. Well, what else can we do? Well, we can wait for a certain number of bloc
ks for our contract finish with so we've deployed the contract. But maybe we want to wait one block to make sure it actually gets attached to the chain. So we can say const. Deployment received equals await, contract dot deploy transaction dot Wait, and specify the number of confirmations that we want to actually wait. So we'll wait one block confirmation to make sure that this happened. And then we can do console dot log, this deployment receipt option. So if we run the code now, we can see all
this information about our transaction, and we can see exactly what our transaction looks like, we can see there's two is no because we're creating a contract from is going to be this ganache address that we got the private key for, we see the contract address that we created transaction index, we can see gas use gas use log bloom block hash transaction, and we can see all this information about our transaction, something I want you to take note of is the deployment receipt and the deployment t
ransaction, I want you to separate these two because it's going to make your life a lot easier. So we're going to do quick console dot log, here is the deployment transaction. And then we'll do console dot log contract, dot deploy transaction. And then I'm going to copy this whole line by just typing Command C or Ctrl. C right there. And then here is the deployment. Here is the transaction receipt. And then this deployment is receipt is the transaction receipt. So I'm just going to rename this t
o transaction receipt. To make it a little bit clearer, which ones which, and we'll run this one more time. You only get a transaction receipt, when you wait for a block confirmation. Otherwise, you're gonna get the contract object, which has the deploy transaction with it, this distinction will be more important later on. But I wanted you to know what the difference between the two transaction receipt is what you get when you wait for a block confirmation, the deployment transaction or the tran
saction response, transaction response is what you get just when you create your transaction. So transaction receipts transactional response, they're different receipt is what you get when you wait for a transaction to finish. And then response is just what you initially get. Make sense? Okay, great. We're gonna go ahead and delete those. But those lines will be in the code associated with the GitHub. Now you saw when we actually printed out those receipts, we got all this stuff in here, because
deploying a contract is actually just sending a transaction, as we've said before, so if we want to see what's really going on under the hood, we can actually create a transaction ourselves and create a contract ourselves just by specifying the transaction information. So how will we do that? Let's deploy this contract again, but only purely using transaction data. So we'll do a console dot log. Let's deploy with only transaction data. And this is going to be the way you can actually deploy or
send transactions purely with transaction data you can send any transaction this gives you unlimited flux. ability with the transactions you want to send, what we can do is we can say const, or let TX which is going to stand for our transaction equals, and we can just add all of our transaction information in here. So the first thing that we're going to need is our nuts, or the number that we only use once we go back to our transaction count, we're on four transactions here. So we'll use the non
ce five, because that's going to be a nonce that we haven't used before. Every time you send a transaction, it comes with one of those nonces. Right, so the nonce is a bit of a over overused term, we saw it back in our blockchain basics that we use the nonce to solve that hard problem. nonces are also used in wallets and in signers, to send transactions and they use a different nones for every transaction. So nonce, when we're talking about wallets talks about a number associated with a unique t
ransaction. nonce, when we're talking about blockchain mining is a value used to solve that hard problem, they both mean the same thing. They both mean a number only used once. But they're different in these different contexts. So we're going to use this number only use once this unique number for a transaction to send this, so we're going to say nonce is going to be five, we're going to pick a gas price of, of this right here, we're just going to use the gas price of ganache like that, we're go
ing to pick a gas limit of some big number, we'll use 1123456, we'll just use that we're gonna say two is going to be no, right, exactly like what we saw in our receipts and responses down here. Since we're creating a contract value is going to be zero. Since we're creating a contract, we don't want to send an ether polygon or avalanche. And then data is going to be that massive binary object in our binary bit. So in the binary section, we're gonna copy this massive binary piece, and we're going
to put some quotes in here, we're gonna do 0x, and paste that in here. So this massive, massive data piece is the binary that we're sending. Whenever you send a transaction, you have this this data object that you can fill this stuff, we're filling our data object with the binary with the code that tells the theory that tells our blockchain to deploy our smart contract that's going to look exactly like this. And then finally, we want to add the chain ID. As we've seen before with Metamask, if w
e go back over to our networks, each one of these EVM chains has a different chain ID Etherium. Main net is one ropsten is three Rinke, B is four COVID is 42, etc. And other EVM chains like avalanche like polygon, are going to have their unique chain IDs as well, or ganache, we can see the network ID appear is 1337 in some people, so we can just paste that in here. Some people have run into some issues where the chain ID and the network ID are different. And the chain ID is actually 31337. So if
you have a problem with this, try 31337 instead, but it should be 1337. Now this is a transaction with all this information propagated, which is awesome. However, this transaction isn't signed. So nobody's sending this transaction right now this is just the transaction details of what somebody wants to do, we actually need to sign this transaction, and then send it to our blockchain. Cons sign, TX response equals await, wallet dot sign transaction, and we can pass that TX object. And then we'll
do a console dot log of the sign TX response in JavaScript. Same as solidity. If you type two backslashes, before some code, it won't run that code. So I'm gonna go ahead and comment out the three lines above. And the way that I'm doing it is by highlighting the sections and hitting Command backslash, or you might hit Ctrl backslash, but this is a keyboard shortcut you can use to quickly comment out entire sections. And the reason I'm doing this is because I want to show you what happens when w
e just run scientex response wallet that signed transaction back in nosh, we see that we have four blocks in here. Let me ask if we do this sign transaction and we get the signed transaction response, will we propagate another block? Well, let's find out run no deploy.js, we get this massive thing here. But if we go back to ganache refresh, we actually don't see another transaction sent. That's because we're only signing a transaction here, we're not actually sending it. So the signed transactio
n response. This big number here represents a signed transaction but not a cent transaction, which is different. You can actually send one of these transactions by changing this line a little bit. So instead of scientex response, we'll change this to send TX response equals await wallet dot send transaction TX then once We send the transaction here, we can do a wait, send transaction response, that Wait, one, we're gonna wait one block confirmation to make sure this transaction actually goes thr
ough. And we can run node.js. And it looks like it's done. But if we actually scroll up, we actually got an error here. So there's this huge, massive thing here. And if we scroll up, we'll eventually see TX reject error, the TX doesn't have the correct nuts, which just for some practice, let's go ahead, type this into Google and see what we get. We actually get a web three Jas from four years ago, trying to call leaf picked, blah, blah, blah, blah, blah, blah, blah, blah. It looks like this is a
meta mask issue that they ran into. And they said, you have to reset your account in meta mask, which we could do. But let's make this a little bit more specific. Let's say ethers. JS looks like we don't get it looks like as of right now, from this recording, we don't get a Stack Exchange eath or a Stack Overflow question for this trolley, because this is pretty straightforward. We don't have the correct nonce for our transaction. But this would be a good time to actually make this a question o
n Stack Overflow or Stack Exchange Aetherium so that it shows up first. So we actually don't get the correct nuts, we're going to want to make this a nonce of four you can see here account has a nonce of four TX has a nonce of five. So we actually would want this to be four. Now an easier way to always get the correct nonce here is going to be actually just calling the transaction count from the wallet. So back in the ethers documentation, there's actually some good samples here on how to assign
ing a message and then how to actually send these messages. So we can do a weight wallet dot get transaction count to get the nuts. So back in our code, we could do const nuns equals await, oops, copy pasted, await wallet dot get transaction count. And then we can just place the nonce right here. Now, let's try running this again. And it looks like this one did indeed go through. We can verify on ganache here. We do indeed see we're currently on block five now and we have one extra transaction.
Now we could go ahead and just run this again. And we'll never have to worry about actually updating this nonce ourselves. Since we're just calling wallet dot get transaction count to keep updating it current block is six and the our additional transaction has indeed gone through awesome. I showed you how to actually sign the transaction. But we didn't sign the transaction for our central injection. Well, why not? If you command click or control click, or you go to the documentation for ethers,
we can see the code for send transaction. So first, it does some check provider stuff. There's some stuff to populate the transaction. But we can actually see that before it sends the transaction even in ethers, it signs the transaction first, and then calls this dot provider dot send transaction. So if you just call send transaction with the transaction details like we did here, it's the same as signing it first and then sending it with the provider. Okay, great. So we've learned how to send a
transaction using pure JavaScript and using pure ethers. One of the main takeaways from this is that every time we change the blockchain, every time we change state, every time we use gas, we're sending a transaction that looks pretty much exactly like this, the data is going to be the differentiator, the data for us here was data saying to create a new contract, when we make transactions, like adding people or storing the data that we're going to be passing in our transaction is going to be dat
a associated with calling these functions. And when we actually call functions in ethers, or in Hardhead. We're not going to do this kind of raw const, TX, and list out all the stuff like here and list out the raw data, right? Because that's really, really hard ethers and hard hat are going to make this process a lot easier. So for now, let's go ahead, comment out this whole section, which again, if we copy this whole thing, and then hit Command, slash, or control slash, or whatever the shortcut
is on your environment, that'll actually comment this out. Let's go ahead and uncomment this section so that we deploy our contract using kind of the ether is much easier to read way than this weird TX stuff. Oh, cool. So we've changed our script back to deploy our contracts like this. Now that we've actually deployed our contract, we can learn how to interact with our contract through code as well, the same way that we click these buttons in remix, we're going to code it out for ourselves here
. So if we look at symbol storage, we have a button for add person for store. And then we have these view functions as well. The easiest one is going to be the Retrieve function, which grabs our favorite number, retrieve returns favorite number. So we can call that in ethers by doing const. current favorite number equals await. contract.we retrieve. The contract object that we have is what's returned from our contract factory as long as we've awaited it the contract object is going to come with
all the functionality described in our API. That's why we had to pass the API to our contract factory. If we look inside our API piece here, we can see it has a ton of information on the different functions that we can call and the types that it has and the return types and everything like that. For example, if I look up retrieve, I can see down here, we have retrieve, we can see that the name of this function is going to be retrieved. And the outputs are going to be a un 256, of type Nuun 256.
Now, this is a little bit difficult to read because it's not formatted. Since we call this dot API, it's going to be a little bit hard to read. But we could change it the dot JSON. And then you'll see it's highlighted a little bit, I can even do format document with prettier. And you'll see it actually formats to be a lot easier to read now and go back to retrieve. And we can see, this block of code here defines what the Retrieve function can and can't do. I'm going to change it back to abi. And
it looks like my formatting has stayed, which is great. This is much easier to read than it was before. As I said, the ABI or the application binary interface is incredibly important for working with our contracts. If we give our code just this huge bytecode thing, it's gonna be really hard for any processor to decompile this or understand what exactly what the functions are that are going on here. There are decompiler options out there, like ether VM, that IO slash decompile. That can decompil
e some bytecode into the solidity. But it can be really tricky to get it exactly right. So it's much easier just to have the ABI to say, hey, this lump of code, this lump of numbers and garbled nonsense is this. When we deploy this bytecode to the blockchain, and we call functions on it, the code will automatically allow those functions to get called if they do exist. But in order for our code to know that they exist, it's much easier just to give it the API. So we can get our current favorite n
umber like this. Let's go ahead and console dot log, the current favorite number. Now that we've edited this code, we're going to let me zoom out a little bit. Now that we've edited this code, we're going to connect organ nosh instance, we're going to connect a wallet with a private key that we got from the top of our ganache here, we're gonna grab the ABI and the binary of our contracts, and connect them to a new contract factory object, which is connected to that wallet. So that wallet will be
the one to actually deploy the contract, we'll deploy the contract with const contract equals await contract factory dot deploy, we will wait one block for that transaction to finish. And in fact, we're not going to use transaction receipt. So for now, we're just going to delete that part. We're not going to do any of this here. So I'm going to delete it for now. However, I'll leave this section commented out in the GitHub repo. And then we're going to call contract retrieve which should return
our current favorite number. Since this is a view function, this contract call won't cost us any gas. If we look at simple storage, that soul we can see retrieve is a view function. And remember view and pure functions, if called outside of a contract function call don't cost any gas, we're just reading up the blockchain, we're not changing any variables on chain, we're not changing the state of the blockchain. So this won't cost any gas. So let's go ahead and run this. Perfect, we get deployin
g, please wait. And then we get this big number response. So what's this big number response here? Big number is a library that comes with the ethers application that helps us work with numbers. If you actually scroll down, they even have a section saying why can I just use numbers, you'd expect current favorite number to just be zero, but it returns this weird hex thing that says his big number true this weird, big number thing. So solidity can't use decimal places, and JavaScript has a hard ti
me with decimal places. And this is kind of the more specific rationale for why not to use numbers, what you'll see a lot of the time instead of numbers is you'll see strings like zero, you'll see JavaScript use strings like this, or big numbers. Now, if I were to try to pass a number like this in JavaScript, this number would be too big for JavaScript to understand. So we want to use big numbers or strings when working with ethers. Now we can make this more readable by adding.to string at the e
nd and printing out the string version of this big number. Now, if I rerun this code, we can see we get zero, which makes sense again, because our favorite number gets initialized to the zero value, if not specified, and we haven't called store yet. So awesome. So that is, that's working perfectly. So this is what our current favorite number is. Let's make this console dot log a little bit more syntactical. We're going to use something called string interpolation. So we can interpolate our strin
g here with variables. Typically in JavaScript when working with strings, use double quotes. However, if you want to mix variables with actual strings, you can use backticks instead. So we're going to use some that backticks here, and we're gonna say current favorite number to call in here. And to tell JavaScript that this is a variable that we want to read, we put a little dollar sign and a bracket around it, like this. Now, if we run this code again, it's saying deploying, please wait, and we
get current favorite number is zero, because JavaScript goes, Okay, this is a string, ah, dollar sign, curly brace looks like this is going to be some variable or some JavaScript that you want me to interpret and close it off, and then backtick. Cool. So our current favorite number is going to be zero. Great. So let's update on the contract the number by calling the store function. So we'll say const, transaction response equals await, contract dot store, and we'll add seven. Now since seven is
a small number, you can just pass it like seven. But passing it like seven in a string also works. Again, this is because if we want to pass some crazy massive number, JavaScript would get confused. So it's usually best practice to pass variables to contract functions as strings, even though that might be a little bit confusing ethers is smart enough to know that this seventh string is actually seven the number then we can do const. Transaction received equals await transaction response that Wai
t, one. So we'll wait one block here. This is similar to us doing contract dot deploy transaction dot Wait, the syntax here is a little bit different than what we saw up here. Because this is using a contract factory. And this is calling a function on a contract. So when we call the function on the contract, we get a transaction response. When we wait for the transaction response to finish, we get the transaction receipt. Now I can do const, updated, favorite number two equals await on track dot
retrieve. And then console dot log updated. favorite number is, and we'll do a little string interpolation, updated, favorite number like that? Now let's go ahead and run this. So in this process, what are we doing, we're deploying the contract, we're getting the initial value, we're going to update our contract by calling store which is going to cost gas. So this is a transaction, we're going to get the transaction response, then we're gonna get the transaction receipt, we're not going to do a
nything with the transaction receipt, I want to ingrain in you all that these two are different transaction response and transaction receipt, and you'll see why in the future. And then we'll get the updated favorite number, and then we're just going to print it out. So let's do this. Boom, and perfect. Deploying, please wait, current favorite number is zero, updated favorite number is seven. And if we go to our ganache instance, we go to transactions, we can see, we now have a contract call at t
he top, we have the sender, the contract address, the gas price, all this stuff, and we see our transaction data right here. So this transaction data is what gets sent in that data slot of our transaction object. Ethers is just doing that on the back end for us so that we don't have to make that big transaction object there. All right, awesome. You've successfully deployed a contract to your own local ganache instance, or your own JavaScript virtual machine. This is great. Now let's clean this u
p a little bit. Because if we look up here, we have both our connection to the blockchain and our private key stored directly in our code, we were to push this code up to a GitHub or some other code repository, if you will, will be able to see our code. If we look into ploy dot j s of my code, ah, there's something else in here, we don't actually see the private key or the RPC URL in here. So what's going on? Remember, if you give out your private key, whoever has your private key owns your fund
s. So even though this is a fake, private key that doesn't have any real money in it, we still don't want to have to hard code our private keys into our code, just in case we accidentally share code with somebody. So what can we do? Well, one of the most popular methods is actually creating something called a dot EMV file or an environment variable. And if you're familiar with environment variables, you can actually set them right in your terminal, but we're gonna set them in our dot env. So wha
t you want to do is you're gonna want to create a dot env file. And this is going to be a file where you store its sensitive information. And this is going to be a file, we're never going to share this with anybody. This dot env file will stick variables of our choosing into the environment of our code. So for example, if I pull up my terminal here, and I do echo cat, this is going to reflect what the cat environment variable is for us. Right now there is no cat environment variable. However, if
I do export, cat equals dog, and now I do echo dollar sign cat, I get dog output. This is what an environment variable is, it's a variable in our terminal or in our scripting environment, since I don't want to have to type export, private key equals blah, blah, blah, every time, what we're going to do instead is we're going to stick them into this dot env file. So when this dot env, we can put private key equals. And we can grab this private key from our script, and paste it in like this. And a
note, some tools look for the 0x, at the beginning of the private key ethers, and hard hat is smart enough that either one works, but if you run into some issues, just know that sometimes you might have to put your 0x at the front of this. Great. So now we have a private key in an environment variable. What do we do now? Well, in our deploy.js, we want to grab this environment variable and stick it into our script here, so that our script can then stick it into our environment. So we're going t
o add a tool called dot env. To make this easier, so we're gonna do yarn, add dot env. And if we look at the dot env package, can read more about it and read about how to add it with NPM. Again, we're just using yarn add. But then we can just call this require dot E and V dot config. And this will pull in all our environment variables. So we can just do require dot EMV config, we should see this on our package that JSON, we do. Excellent. Now that we pulled it in, we actually get access to our p
rivate key environment variable, you can access environment variables in JavaScript, are using process dot EMV. So instead of putting our private key here, we're gonna delete that whole thing and substitute it with process dot EMV, that private key, and we'll save and it'll reformat for us to make sure this is actually working, we can just hit up after we save up, up up up up a bunch and go back to no deploy to Jas. And we see we get the exact same setup. And if we scroll back, you can see a tra
nsaction has indeed gone through. If you want to double check that this is actually printing out your private key, we could do console dot log, press study and via private key we run, we see that that is indeed the private key coming from our environment variable here. Awesome. Now our RPC URL here is isn't really something that we need to secure however, maybe we're going to use a certain API key or maybe a certain endpoint that only we want to have access to. And we don't want anybody else to
be using our RPC endpoint. So we're going to add this to our dot env file as well. So in our dot env. When I copy this here, I'm gonna say RPC URL equals, and I paste that in there, just like that. And we're gonna delete here. And we're gonna do the exact same thing, say process dot e NV dot RPC URL. And now we're going to run this again. And I'm going to take out that console dot log. And we should get the exact same response because all we did was swap out our RPC URL with our environment vari
able, which is going to be exactly what it was before. So we go ahead and run this, and we get the exact same response. And if we go to ganache, we see that we do indeed get a transaction here, which is perfect. Awesome. So we've learned how to add environment variables to our dot env file. So that so that just in case, we want to share our code, or we push our code up to GitHub, which we'll do in later sections, we don't accidentally expose our private keys or our RPC URLs. Now all the code tha
t we have in our project here, if we push it up to GitHub, or share it with somebody else, all this code will get pushed up, including our dot env file. However, if you look at my code samples here for this course, we don't see a dot env file in here. So how is that possible? Well, what we want to do whenever we have a project is create a dot Git ignore file. And in here, we want to put in v. And we also want to put in Node modules. This means that when working with Git and working with version
control, which we're going to do a little bit later, we won't push our dot env file up to GitHub. And we also won't push up known modules. So if we go back to my example here, we don't see, we don't see a dot env file, but we do see a dot env dot example, just to show you what one would look like. So it doesn't really matter that I have them in here. Now, if you're really paranoid, there's something else you can actually do when running your scripts and running your commands. Let's say you didn'
t want to put your private key into a dot env file because you were nervous that you would accidentally push it up or something. What you can do is you can add your private key in your RPC URL as environment variables right in the command line. So before you run Node deploy, that's as well you can do, you can say RPC URL equals, paste your RPC around. And then you can say private key. equals and then paste your private key and then do node deploy.js. Setting these right before we run our script
is the exact same as if we had set them into dot env. Here If we hit run, we see the exact same output, which means that our RPC URL and our private key went through successfully. This way for key management is fine. But our rights doing this, it's going to be much better. But it still makes me a little bit nervous in our development environments with our fake private keys, having our code in the dot env file like this is, is okay, right? Because we don't really care if this key gets hacked, lik
e nobody's using it. But when we move to a more professional setup, this can be a little bit scary. So how can we make this even more secure? Well, what we can do is actually we can encrypt our private key and store our encrypted key locally. That way, if for some reason somebody does get into our account, our private key isn't just sitting around in plain text, it's encrypted. And you'll need to know a password that only you know to get into it. So how do we add that? Well, first, we're going t
o create a new file called encrypt key.js. And this is some code that we're going to use to actually encrypt a key. And we'll store that locally instead of our private key in plain text. This will make us even more secure so that we don't have our private key just hanging around in plain text here. So let's go ahead and build the script to encrypt our private key. So we're going to use the exact same setup as we did for our deploy script. We're going to do an async function main. And then down h
ere, I'm just gonna go ahead and copy from deployed J S. We're gonna use this exact same setup, and paste it. Okay, great. We're gonna be using ethers J, s, and r dot E and V again. So we're going to add these in const ethers equals require ethers const, FS equals require Fs extra. And then require dot env. Config. Alright, so right now, in our dot env, we do have this private key. And again, if you don't want to have the private key in their way you can just do is you can do private key equals
and then you know, node, whatever script you want to run. So we're going to set this script up to run our encrypt key one time. And then we can remove our private key from anywhere in our workspace so that it's no longer in plain text anywhere. So what we want to do is we want to say const wallet, and we're gonna create a new wallet, but a little bit differently. We're gonna say equals new ethers dot wallet, process dot E and V dot private key. So we do need our private key to stick in here. But
then once we create this wallet, we're gonna say const. Encrypted JSON key equals await ethers dot encrypt, this encrypt function is going to return an encrypted JSON key that we can store locally and that we can only decrypt it with the password. And it takes two parameters. It takes a private key password and a private key. So in our dot EMV, just for right, now we're going to create a private key password. And I'm going to say it's password. But obviously, this is a terrible password. And yo
u should never use password as your password. But for now, we're just going to leave it as password since I'm encrypting this big key anyways. So we're going to encrypt it by passing the password process study and v dot private key password. And we're also going to pass the private key, it's going to be ethers, it's going to be wallet dot encrypt. We're also going to pass it process dot EMV dot private key. Now let's go ahead and run this right now. And then we'll console dot log out this encryp
ted JSON key and see what happens when we run this. So to run this, we're going to do node, encrypt key.js. And hit enter. And we'll see what happens when we console log it out this JSON object here is what our key looks like, encrypted. So it's got the address this ID version, all this other stuff. And all this other stuff is the encrypted version of this key. If somebody gets into our account and they see this, they'll have to know the password to decrypt this private key, they'll need to know
the password to decrypt this JSON object back into a private key. So what we're going to do, now that we've encrypted it, we're going to save it. So we'll do Fs dot write, file sync, we're going to pass it to dot slash dot encrypted key dot JSON, comma encrypted JSON key. So we're saving it to a new file called dot encrypted key dot JSON. And we're passing it this encrypted key that we just made. So if we open up our file explorer, and we run this command, you'll see we get a new file called do
t encrypted key dot JSON. And it's this encrypted key here, which is awesome. So now what we want to do in our dot Git ignore is add dot encrypted key dot JSON, so that we don't accidentally push this up to GitHub. And now we have an encrypted key and we can go to our private key and delete this from our dot env file. We can also delete our private key password from our WMV file so that the password isn't just hanging around in plain text. Now that We have an encrypted key. Back in our deploy sc
ript, we can change the way that we actually get a wallet. So at the top, we're getting our wallet just by passing in the private key like this, we're not going to do that, we're going to use our encrypted key that we just created. So we're going to do is we're going to say const encrypted JSON equals Fs dot read file sync. That slash dot encrypted key dot JSON, comma UTF eight, this Fs dot read file sync is just going to read from our encrypted key dot JSON into this encrypted JSON variable her
e. Next, we're going to create a wallet from this encrypted key. We're gonna say let wallet equals new ethers dot wallet, dot from encrypted JSON sync. And all these commands that we're working with ethers, we can of course, find them in the documentation from encrypted JSON sync takes the encrypted JSON and a password and returns a Wallet Object. So we're going to pass it that encrypted JSON that we just read. And then we're going to pass it password which we're going to do process dot EMP dot
private key password. And then finally, the reason I use let here is because now we have to connect this wallet back to our provider. If you look here, we're not connecting our wallet with a provider. When we make our transactions with our contract factory, we need to make sure the wallet knows about the provider here. So we can just say wallet equals await wallet dot connect provider. Now, if we run our deploy dot j s with our private key password as an environment variable, it should still dep
loy. So we can do private key password equals password, which yes, we know is terrible. But that's what we're using for now node deploy dot j s, we should get the same output we've been seeing this whole time and we do we're able to no longer have our private key in our dot env file not in plaintext anymore, it's in this encrypted key. So that just in case somebody hacks our computer, they still won't be able to send in new transactions unless they know the password. This is awesome. One more th
ing to know, if you type history, if somebody got into your computer, a hacker could actually see private key password equals password in your bash history. If you run history, dash c, you actually will clear your history. Now if I type history, I can just see that the most recent command I wrote was history, this is really just some of the bare minimum for encryption and keeping your key safe. And it might seem ridiculous that somebody might be able to hack your computer and read your encrypted
private keys and everything. But as your projects get bigger and bigger, it is really important to know about private key security and private key safety and, and for this course really just giving you the bare minimum here and showing you how to encrypt keys and how to be a little bit safer here. Now for the rest of this course, we are going to be just using this syntax with our private key in a dot env file. The reason why we're doing like this for the rest of the course is it is a little bit
easier, I'm really hoping Hardhead add some additional features to make private key encryption much safer and also easier to use in the future. And they probably will. And the other reason that we're okay to do this here is because you've solemnly sworn that you're not going to use an account that has any real money in it for the duration of this course, you're only going to use private keys that have tests on Aetherium or are fake private keys like this one that we got from ganache. In fact ju
st to really hone this in in the smart contract kit slash full blocked in solidity course, Jas GitHub repo in the discussions tab, you go to announcements, I've created one called the dot end pledge. Because recently I've seen too many people follow a tutorial that doesn't tell them about the security risks of doing this. And I've made this dot EMV pledge, I would love everyone to jump on and read. And if you agree, at the bottom, leave a comment saying I will be safe, I will be safe, make sure
you read and you understand what's going on in here. And I'm not doing this to scare you. Because again, at the end of the day, if you use a Metamask that only has tests that funds for the duration of this course, you will never have to be worried because of your key gets compromised. It's just test it. So who cares? This is if you're using a meta mask or you're working with a meta mask that has real funds. So I'm going to read up the pledge because it is really important. You understand this wh
en you're working with real funds. And if you're like, Hey, I'm not working with real funds, I don't care, great move past this, whatever. But when you do work with real funds, when you do decide, hey, I actually want to deploy this to a real network. Now I need real money to do that. Come back to this pledge. Scroll the bottom say I will be safe and make sure you read and you understand this. Okay, so the pledge is, I solemnly swear that I will never place a private key or secret phrase or pneu
monic in a dot env file that is associated with any real funds. Basically, you basically never have your private key or your pneumonic phrase, in plain text, anywhere. You'll all only place private keys in a web file that only have tested e FF link or other cryptocurrencies. Because again, if your private key has only test net funds, then that's great. I don't care, we are aware that if we forget a dot Git ignore, and we push our key phrase to GitHub, even for a split second, or even show our ke
y slash phrase on the internet, wherever it may be for a split second, it should be considered compromised. And you should remove all funds immediately. So even if you deploy your private key to a website, and then immediately delete your website and think, Oh, nobody probably got to it, you should consider that private key compromised, and you should remove all your funds. And again, this is just for real funds. If your private key was only tested, funds gets compromised. Well, who cares? I do
that all the time, you've been seeing me do that all the time, because it only has tested funds in it. If at the end of this course, you want to steal all of my tests that funds I mean, have a blast, it would be annoying to me at worst. If I'm unsure if my account has real funds in it, I will assume it has real funds in it. So if you don't know if it has real funds, assume it has real funds, and you will not use it for developing purposes. And then finally, I am aware that even if I hit Add Acco
unt on my meta mask or other eath wallet, I will get a new private key, but it will share the same secret phrase slash pneumonic of all the other accounts generated in the meta mask or other eath Wallet. So if I'm in my meta mask here, and I hit Create account, I will get a new private key with the new account. However, all of these accounts that I've created with this Create Account button have the exact same pneumonic phrase or secret phrase. If I import an account with a private key, it's goi
ng to have a different pneumonic phrase. But all of the ones that I generate inside the wallet are all going to have the same phrase. Okay, great. Hopefully that'll make sense. I have some pledge additions here. For this course, I will only use funds associated with a brand new never before use meta mask or other eath wallet. Again, this is not to scare you, if you just work with a brand new meta mask, you don't have to worry about any of this and just refer back to this when you start looking a
t real money and real private keys. I'm aware that my account associated with my private key is the same on test nets that it is on Main nets. So like I was showing you, my private key on Rinkeby is going to be the same as my private key I'm on a main net, if I must use a private key associated with real funds in the future, until I am 100% sure what I am doing, I will always either use one of the encrypted methods that Patrick showed you some better encryption stuff that I didn't show or use th
e command line way to pass private keys and then delete the command line history right after. If I'm never actually deploying anything to make that myself or work with a private key with real funds. I do not need to be concerned. Take a look at this. Read this internalize it, it should make you confident. Now again, I'm not saying this to scare you. I'm saying this to instill confidence in you that these are some of the things that we want to think about. Okay, great. In here, I will be safe. Bo
om, I will be safe. And if you want to copy paste this on Twitter, put this in a huge tweet thread. Go for it. The more people who know about this, the more people who understand the security risks of their WMV files and their private keys, the better. So thank you for listening to this. I know I definitely belabor the point, but it is really important. Let's continue with the course. Alright, so we're just about done here. However, there's one or two more things we want to do just to clean this
all up right now when we're auto saving reason, the VS code plugin for us to auto format. However, in the future, if anybody else comes across our repository, they might not have the Vyas code auto format or on. So we want to give users a way to format their code. So it matches the styles that we use. So we have prettier the extension installed. We can also add prettier as a Node js module that can tell other users who don't have a Vyas code exactly how to format both their JavaScript and the s
olidity. There is a prettier plugin solidity located here, there will be a link to it in our GitHub repo. And if we scroll down, we can see how to install with npm install dash dash save Dev, which again, we're just going to use yarn, so we're going to do yarn, add prettier, and then prettier plugin solidity. So we're installing both prettier, and the solidity plugin for prettier. And if we check our package, JSON, we can see that these two have been added. And what we can do now is we can creat
e a new file called dot prettier, R C. And in this file, we can define some little curly braces. And here, we can define what we want for both our solidity and for a JavaScript, so for example, our simple storage has a tab width of 412344 spaces. Maybe we want to change that. We want tab width to be two. So we would save it here and come back to simple storage To save it here, and it would get auto formatted to r dot prettier RC. So in our settings here, we have the default editor for solidity,
our hard hat, solidity plugin, and the default for meta for JavaScript being the prettier vs. Code one, when we add prettier RC in here, this file will take precedent over the default configuration, so long as we have downloaded the module in our node modules, which we can see it right here. And we have this dot prettier rc file. I'm going to keep the tab with form. So we're going to update it to that one thing that we currently do have that I do not like is these semicolons at the end, so we're
going to do semi boss, and I'm going to save this, come back to deploy it save and you'll see the semicolon automatically goes away. I'm also going to add use tabs false, since I want to use spaces or spacing, and then single quote, false. This way, we'll always use a double quote, instead of a single quote, in JavaScript, you can actually use the single quote or double quote, to define strings, but we're going to make it so that no matter what quote you use, it'll always be double quote. And t
hen for all your open source repos, and for all your projects that you make, you want to make a readme.md readme files are generally where people put instructions or information about your project or anything like that. This way, whenever anybody comes across your project, they'll know what it's about your readme dot MDs, our Markdown syntax again, remember how when we made that trial discussion, we use some interesting tips to format our solidity in our code here. Well, that formatting process
is the exact same for.md files for markdown. They're both going to use markdown. In fact, if we hit Ctrl, Shift V, you'll enter preview mode for the markdown you'll see pound sign here in my preview of the hard hat. This ethers simple storage FCC is huge. And it looks like a heading at the top. So Command Shift V to view your.md files or or MIP Ctrl, Shift V for Windows and Linux users. The last thing that we're going to do is we're going to deploy this to a test net and interact with this on a
test net, we're going to use the Rinkeby test net. But be sure to use whatever recommended test net the GitHub repository for this coerce recommends. Now looking at our code, you might already have a good idea of how to actually make this slight change. Based off of our last section, we know that all we need is an RPC URL and a private key and we can begin making transactions on a blockchain. So we're probably going to need a rink B RPC URL, and a rinky private key. Where can we find both of tho
se, if you want to do everything on your own, and in full decentralized context, we could run a rink B version of geth, we could run it locally, and then just connect to our guest node, we're not going to be showing how to do this here. However, this is 100%, something that you could do. Instead, we're gonna use a third party RPC URL in the GitHub repo associated with this course. Go to Lesson five, we can scroll down to get a link for alchemy. Alchemy has a node as a service and allows us to co
nnect to any blockchain that they have support for two alternates might be quick node, Morales, or infura. These all have node as a service options. But we're going to work with Alchemy, because it's the one that I liked the best, we can go ahead and get started for free or login or create a new account, I'm going to go ahead and sign up with our hard hat Free Code Camp user. And we're going to select the Ethereum blockchain ecosystem. Let's go ahead and create our first app. This is going to be
we'll call it Free Code Camp. RT hat. Our app name will be ethers, simple storage, FCC, and the network is where we're going to choose rink B. But you can see in here, we can actually choose more than just rink B, we can choose really Kovan, rink B, ropsten. And layer twos like arbitrage and optimism, we're going to be using rink B. So let's go ahead and create this app. We're going to choose the free plan and hit Continue. We're going to skip adding payments. If you want to tweet your referral
code, feel free to tweet your referral code. We're going to skip for now. And we're going to keep it at capped capacity. Since we don't have a we don't have a key in here. And then how did you hear about us go ahead and give me that shout out at Patrick and Free Code Camp and then hit Let's go. Now we get to the alchemy dashboard, where we can see a ton of information about our node and different ways to connect to the nodes and and stuff like that. This is going to be really similar to to this
RPC server endpoint of ganache, except it's going to be a connection, except it's going to be a connection to a real test net or real main net. What we can do now is we can select our our app that we just made. And we can hit View key. And we can see here we get an API key Key, we add an HTTP endpoint and we also get a WebSocket. We're only concerned with the HTTP endpoint. This is going to be our RPC URL that connects to rink B. So what we can do now is we can copy this and come over to our Vi
sual Studio code. And in our dot env, we can substitute these out for their actual tests and values. So for RPC URL, we're going to delete this and replace it with our Rigby RPC row. And now how do we get a private key for an actual test set that has actual rank be on it? Well, here is where we can use our meta masks. So back in your browser, go over to your meta mask, select the three dots, go to Account Details, export private key. And this is where you can export your private key, type in you
r password and boom, you now have your private key for your account on meta mask. Now remember, please, please, please don't continue with a meta mask that has actual money in it. A quick way to check is by going to your networks tab and seeing if on any of the main nets or the networks with actual money in it, you see any money, I don't have any money in this. So I know I'm good to go. If you have tests that money, that's fine, because that's fake money anyways. And again, most browsers have a
profile mechanism where you can create a new profile for you to use. But here now that I've copied my private key, we can come back to our Visual Studio code, paste the key in here. And now I have a private key that has actual rink be in it. Awesome. And remember, if you ever get low, just come over to faucets dot chain dot link slash Rigby get some tests eath I'm not a robot will send the request. Now that we have our private key in our rink being here, we can now try to run this on an actual t
est. Net, we look at our code, we see we're grabbing an RPC URL, which is going to be from r dot end, we're grabbing a private key which is going to be from our daughter Yun V, which points to our rink D Metamask. And our rink B blockchain. So let's just add a console dot log under our contract deployment so that we know what address it's at. So we'll do console dot log, we'll do some string interpolation, contract, address, contract dot address. All right, great. Now let's go ahead and run this
. So we'll do node deploy dot J. S deploying Please wait, you'll notice this takes a lot longer. Because we're deploying to a test net instead of our own fake local blockchain, test nets and real networks often will take a little bit longer because they need to wait for the blocks to propagate the transaction to go through, etc. But after a brief delay, we will indeed see that we get a contract address here. And we have a current favorite number. And it's being a little slow again, because we're
waiting for our next transaction to go through to update the number and boom, looks like we've successfully updated it. Now something that's important to know if ever you run command, and you want to kill it, you can do Ctrl C, and that will stop it. So any command in the terminal that you want to just abort Ctrl. C is your Get Out of Jail Free card and that will kill it. That'll stop it wherever it is. So we'll use Ctrl C a lot in the future. So now let's grab this contract address and go over
to Frank V ether scan and paste it in, we can see our two transactions here, we can see we have a contract creation. And we can also see we call a store function. This is awesome. We've successfully deployed a contract to the wrinkly chain using our own code. Congratulations, this is massive. Now on ether scan, we actually can verify and publish our contract code. What is verifying and publishing your code? Well, right now, our code looks like a huge gerbil of bytecode. And anybody looking at o
ur contract directly on chain will just see this huge jumble of bytecode, we can use a decompiler to try to decompile the bytecode into what it looks like in solidity. But this can often take a long time and, and a lot of processing power. So instead, we can just make it much easier by verifying and publishing the code ourself, you go ahead and hit verify and publish. We can scroll down and we can add compiler information to compile this on ether scan and other block explorers. This is a single
file compiler version is zero point 8.7. And it's open source is licensed is MIT. Let's go ahead and continue. And we're going to copy paste our solidity code into this large section. Paste. We don't have any constructor arguments so we can skip this section. We don't have any libraries or any other miscellaneous settings. So we'll select I'm not a robot and we'll hit verify and publish. You might have to wait a few minutes, but awesome. Our contract was successfully compiled. Now if we go back
to contract source code, we can see all the code in here. And if we grab our contract address, place it into place into the search now, and we go to contract, we get a little green checkmark. And we can see, anybody can now read our source code. Additionally, those buttons that we saw and remix for reading from our contract, and writing to our contract, are in this read contract and this write contract. If we read the contract, and we retrieve the most recent number, we do indeed see that we hav
e seven here because we recently stored seven. Awesome, quick note, this might already be verified for you, since ether scan might get smart enough to notice that a lot of people are deploying the same bytecode it's already verified for you just go ahead and walk through these steps anyways. Now the code verification we just did was pretty simple and straightforward, because our code was pretty simple and straightforward. Using larger and more complex code can make the verification process a lit
tle bit harder. Additionally, we don't always want to have to click buttons on ether scan. To verify our code, we want to do it programmatically. So in later sections, we'll learn how to verify all of our code directly through our code editor, you can imagine the process is this easy for deploying to any EVM chain in our alchemy, we could easily create a new app and change our network. And you could see how easy it would be to just switch out this RPC URL and your private key to work on a differ
ent chain. This process is also the same for harmony Phantom, avalanche, etc. And if we wanted to switch chains, we would just switch the RPC URL and switch the private key, and everything else would stay exactly the same. Now, Alchemy also shows us and can teach us a lot about transactions and about things that are going on behind the scenes, including a concept called the mempool. To help us understand a little bit more about those transactions that we just sent, and how to work with Alchemy.
To see more about our transactions, we have Albert from the alchemy team to give us a little demonstration. Hello, Albert here from alchemy, I'm that guy in tech on Twitter, feel free to follow if you want to engage and ask any questions about this section of the video. But super excited to join Patrick here to explain a little bit of what goes on behind the scenes when you are using alchemy to submit a transaction. And we have a ton of tools to actually provide a window of visibility into what'
s going on so that you can actually debug in case there are usage errors on your website, or there are pending transactions that are stuck. Whatever it is, we provide that window into the data that you control. Remember that all the transactions that you submit are recorded on the blockchain. They're not controlled by alchemy, they're not controlled by any other service provider. We are just a window, we're just the plumbing the piping to be useful to you. So let me show you exactly what that me
ans. Right now I have a bunch of applications in my dashboard. You can see here that there are different projects that I've used over time. This one is the most recently active, and it is the one that I have currently set up to connect to my meta mask. So actually use a custom RPC provider here. And let me make my face a little smaller. And you can see here, I've misspelled Rinkeby. But this right now, my my network is actually connected to the Rinkeby test network via alchemy. So this is actual
ly this application. So if I click into here in the dashboard, you can see here, a bunch of really interesting statistics, this is the first thing that you'll probably use. If you're trying to understand more about your application, you'll go here and you can see how many compute units per second your application is currently using. And this is kind of great for specifically alchemy usage, understanding. But then this is also really useful to see like, what's the median response time, and so 33
milliseconds is pretty good. If that starts to increase, then you might want to figure out, you know, what's going on here, success rate, it has been kind of low. So that is a clue for me to click on this tab to view recent invalid requests. And that I can actually see oh, there's a bunch of failed transactions where the transaction has already been sent or the nonce is too low, or whatever it is, I can actually use this tab to debug. So that success rate is pretty useful. Throughput that's been
limited. So if you are sending too many requests or your website is getting spammed, you might start getting some requests blocked. So that's what's useful to view their concurrent requests over here, success rate in the past 24 hours versus the past one hour, the total number of requests in the last 24 hours. And this is different than compute units, because each request can have a different level of computing cost. And computing cost as measured by compute units. Total requests is just the ac
tual number of absolute requests. And then of course, the number of invalid request. Cool. So one thing I do want to show you that's interesting is when I do submit a transaction, and I actually have one right here, I want to send so let's transfer between my accounts, and I'm just gonna send it to tiny amount of Rinkeby eath. But I'm going to purposefully edit my gas fees to be super, super low so that the node will actually not muck send the transaction to be mined, or there are no miners that
will actually pick it up. So you can see here I've divided the the priority fee and the max fee by a ton. So it's super low. And it might confirm that in the MME Max UI, you'll see that the transaction has been pending for a bit. And we'll go over to this mempool tab. This is another really useful visualization. And what the mempool is, is a kind of a holding ground, I like to think of it as the waiting room of a restaurant, where if you're a transaction, and you're waiting to get mined, the me
mpool is kind of like the waiting room where you're waiting to get seated. So there are different statuses for your each of your transactions, the ones that you always want to see are the mines transactions, because that says that your transaction is successful. And it's now part of the blockchain. Now, the mempool, every node has its own, you know, holding ground. So I can actually show you this quick visualization. Remember, blockchains are run by a network of nodes. And each node or each comp
uter that's running the theorem, software maintains a copy of the blockchain. And as a developer, you have to use these nodes to make requests to the blockchain. Now you can use alchemy, you can use another RPC provider, you can spin up your own node if you want to. But regardless, you need to use a node to communicate with the chain. Now each node beyond having a copy of the entire blockchain state, it also has a local memory of transaction. And that's called mempool. So if there are pending tr
ansactions that are waiting to be mined, you can consider them as being in the mempool. Now that's what we're looking at right here. If we click on the app that I am currently using for my Metamask RPC, then you can see here that there are, this is not the right one, this one is the right one for wrinkling. For all the transactions here, you can see some more drop in placed somewhere mind and there's one that's pending, and this pending, one actually matches up with the one that is pending, here
, it's being sent to 0x, C, BB. And if we click on this transaction hash, you get all the information that you need to debug. So you can see here that it's from my current address, 0x, five F, and then it's two 0x, C, BB. And here's the value that I'm trying to send. Here's the gas fee that I've attached to this transaction. And you'll notice that that is super low, even for the Rinkeby test network. So knowing this, and seeing, wow, this transaction has been pending for one minute and 46 second
s, it was sent at this time, I should probably fix that. And so over here, you can actually use the metamath RPC, meta meta mask API. And speeded up. And then I'm just going to use the auto high speed up to update the gas fees. And then if we go back to our dashboard back to our application, you can see that there are some new recent invalid requests. And this is because we've resubmitted a transaction, and then in their recent requests we have, let's refresh that real quick. You can see that we
are sending a raw transaction, this one's already known. And there's another one before, but it that's resulting in a get transaction receipt that is successful. And then if we go back to the mempool, you can see boom, no more pending transactions only dropped and replaced and mined. So this transaction nonce number five is now successful, and you're on your way to developing and maintaining the rest of your application. So yeah, thanks hope that was useful. Let me know if you have any question
s. Now, other than the TypeScript portion, which I'll do at the end, you've successfully completed this section. And wow, you've learned a ton. Let's do a quick review of everything that we've learned. Well, first, we've learned how to create new projects with Node js, we've learned what the node keyword does and how we can use the node keyword. To run JavaScript in our local development environment, we learned that we can add different dependencies of external packages into our local package us
ing yarn or NPM. And we can see those dependencies added in package dot JSON, we know that they've been installed because they get installed into the node modules folder, we can also create a script section where we can minimize long commands that we need to run into a single keyword, like compile for example, we can just run yarn compile. To compile all of our code, we learned the basic setup of our JavaScript scripts, we import our packages at the top, we have some main executor function at th
e bottom. And then we have our main function in the middle, we use the async keyword so that our function can use asynchronous programming, and we get access to the await keyword, which basically means Hey, wait for this promise to finish doing its thing. We're able to connect to any blockchain we want using an RPC URL, and then we're able to connect our provider to a wallet or a private key in ethers by doing something like this. Speaking of So we've learned about the ethers package, which is a
tool that makes our life a lot easier to interact with the blockchain in JavaScript, if we decide to, we've also learned we can encrypt our private keys so that even if our computers get hacked, our private keys aren't lying around in plaintext. And we've learned how to run scripts from our encrypted keys. We've learned how to get the ABI or the application binary interface, and the binary of our code to deploy to a blockchain, we've learned how to deploy our contracts to a blockchain programma
tically. And then we've learned how to interact with our contracts programmatically as well. Additionally, we've learned how to add a default editor in our settings dot JSON of our VS code. But we've also learned how to override those settings by adding prettier using a dot prettier rc file this way, we can auto format our code to make it look a lot nicer and much easier to read. Finally, we learned how to deploy one of these contracts to a real test net or a real network. And then we finally le
arned the manual way to verify our contract source code. Like I said, we're going to learn a lot of shortcuts. And a lot of ways to make this all a little bit easier in coming sections. Oh, you have done a phenomenally to reach this section, give yourself a pat on the back, take a break, go for a lap, and feel really proud about yourself that you made it this far, we've got a lot more to go. But you have come a phenomenally long way. Congratulations. Or take that five to 10 minute break and come
back when you're ready. Now the one thing left I want to show you all is the TypeScript addition to this. However, if you're not interested in the TypeScript edition, which you don't have to be, then you're done, there's only a couple of changes we need to make to make this TypeScript compatible. First, of course, we're going to change our deploy.ts and encrypt key, we're going to change our deploy and our encrypt key from dot j s two.ts. And then we're also going to swap these requires out for
imports. So we're going to import ethers from ethers, we're going to import star as Fs from Fs extra. And then we're going to import dot TMP slash config. And then we're just going to copy these, and we're gonna come over and paste them into here, deleting or commenting out the requires, okay, great. Now, if we try to run Node deploy.ts, we're going to get cannot use input statement outside of a module. In JavaScript, if we'd want to use an import statement outside of a module, we'd come in her
e and do some like type module like that. But in TypeScript, we actually don't even need that. All we need to do is run this in TypeScript note. So to add TypeScript, we're going to do yarn, add TypeScript. And we're also going to add TS node. TS node is the TypeScript edition of node. So now that we've added that we can try a TS node deploy.ts. And we're still going to run into an error. And if you scroll up, we're gonna get a couple errors here. We're gonna say, could not find a declaration fi
le for Module Fs extra, we need to add the TypeScript version of them. So we're gonna do yarn at types slash Fs extra. That, and if we run it again, it still shouldn't work. But for a different reason. Yes, we're gonna get something like this type. Undefined is not assignable to type bytes. Like the reason we get this is because process dot EMV private key in TypeScript technically, is type string, or undefined. So we need to tell Typescript and and the Wallet Objects. And the Encrypt function i
s looking for a type string, not string or undefined. So we just need to tell TypeScript that this will not be undefined. So we can just put a bang here. And everywhere that we use process, study and be, oops, I got to do that on deploy, as well. Bang, looks good. Now that we've added everything in here, we run TS node deploy.ts, we're gonna see the exact same output as we saw with just using regular node. And as long as our private key password is in our dot env file. If we run TS node and cryp
t key.ts, we're gonna get the exact same setup as before. And we're gonna get a new encrypted key dot JSON. And that's all you need to do to make this TypeScript compatible. And you should give yourself a huge round of applause for getting this far and learning what's going on underneath hardhat. The next tool that we're going to learn and learning all about these transactions and how to interact with these blockchains this is absolutely massive, so huge. Congratulations. Alright, so now that we
've learned about ethers js and how to do some more raw JavaScript coding, we're now going to move into hardhat. We saw with our ether symbol storage that deploying a contract can take a lot of code. And there's a number of things we didn't even do in here. Like we didn't save where this contract was deployed. So we'd have to go remember where it was deployed every time. Instead of having it just added programmatically. We didn't write any tests here, and we'd have to build our own testing infra
structure. Maybe we want to make this a cross chain application. And we want more than just one private key and RPC URL, you can absolutely work with your smart contracts in JavaScript purely through ethers and small scripts like this. But we want a more robust framework for doing all this. And that's where hard hat comes into play. Hardhead is easily one of the most, if not the most popular smart contract development framework out there. It's used by massive several billion dollar protocols lik
e Ave uniswap, sushi swap, and more. In fact, I recently did a poll on Twitter. And even though a lot of my content has been more brownie and Pythonic, Hardhead was well and beyond the most popular framework, and Hardhead has quickly become one of the most advanced frameworks out there. Hardhead is a development environment, which allows for JavaScript based development, kind of like what we saw with ethers, it gives us even more tools to integrate our code with common things that we want to do.
It's incredibly extensible, and it has really nice debugging features as well. And it's just an overall fantastic tool. So let's go ahead and let's jump in. If you want to follow along with the code, come over to the GitHub repo and scroll down. Lesson Six heart had simple storage, and all the code is located here. And a quick note for the future ever, you want to just download all the code from one of these repositories, the way you can do that is by doing a git clone, what you do is you come
to the folder that you want to put this code in, and you run git clone. And then you grab the URL that you want to clone, paste it in. Now, you can CD into your new folder here that has everything downloaded directly from GitHub, but only do that as a backup or to just download the code yourself. But for now, just follow along with me. Right, so let's do this. Let's create our next project using hard hat. The project that we're going to be making is called Hard Hat, simple storage dash FCC or Fr
ee Code Camp. This is going to be us working again with that simple storage contract. But in hard hat, we're going to show you a ton of the fantastic tools that we can use to make our coding life way easier. So I'm in a brand new VS code, and we're going to create a new folder for us to run all this. Now what you can do to create a brand new folder is you once again you can do MK dir, hard hat, simple storage of CC. Now we can cd into hard hat simple storage of CD, and type code, period. And thi
s will open up a new Visual Studio code inside of that folder. Now if we open up our terminal, you'll see that we are indeed inside that folder. Now if that doesn't work for you, you can still of course to File, Open folder and select the folder you'd like to open. And you'll be inside of that folder. Now that we have our folder setup for working with hard hat, we can begin setting up our environment to be incredibly professional using the hard hat framework got a link to the hard hat documentat
ion inside our whole blockchain solidity course, yes, the hard hat documentation is phenomenal. And I highly recommend everybody have it up as they go through the section. Because it's going to give you pretty much everything that you need to know for working with hard hat, you can simply go ahead over to tutorial and get started. If you want to pause the video here and read through the tutorial, I recommend doing so it'll give you a lot of information about how to work with hardhat. And more ab
out hardhat. However, we're just going to jump right into setting up the environment. We've already installed no Gs on Linux, or Mac OS. And those of you who are using Windows, I set you up with WsL. So you can just follow the Linux instructions. Now to create a new hard hat project, you can actually just go ahead and run these steps right here. Instead of NPM, we're going to be using yarn, but if you want to use NPM, you can absolutely do so the hard hat Doc's say run npm init dash dash, yes, w
e're just going to run yarn in it, which is going to create a new project for us in this folder. So let's give it a name, which if we want it set to this hard hat symbol storage FF FCC, we just hit enter, we'll give it a version. And when if we want it 1.0 point oh, we just hit enter. We're going to skip the description for now just by hitting enter. And we're just going to hit Enter for this as well. And for this as well enter for this as well and for this as well and over this as well. Just to
keep those as blanks. And if we look in package json, we now see we have a name Hardhead symbol storage that FCC we have a version we have a main which we're actually going to delete the main and then we have a license as well. yarn in it just sets up this package json for us. Now we're going to do yarn, add dash dash dash of our app. So far, we've just been running yarn add, and then whatever our package name is. But for most of what we're doing, we really want to do yarn add dash dash Dev. Th
e reasons for this is a little bit nuanced. But we can see some of the information on this StackOverflow question here. The main difference is that dependencies are required to run your project. Whereas dev dependencies are required only to develop. For the most part, we're going to be doing just dash dash Dev, when we get to the front end portion of this course, we'll be installing more packages that we don't need just for development. Now in the same directory where we install hard hat, you ca
n run MPX hard hat. So a quick note about MPX is that the yarn equivalent of NPM is just yarn. So yarn goes NPM, the yarn equivalent of MPX is also yarn. So pretty much anytime you see MPX, do something, you can just replace that MPX with yarn, and it'll do the exact same thing. If you want to run this with NPM or MPX, you can absolutely do that as well. So for us, we're going to run yarn hardhat. And we'll see we'll get prompted to actually start creating a hardhat project, run yarn hardhat. An
d we'll get this wonderfully cute prompt right here and saying welcome to Hardhead. What do you want to do, create a basic sample project, create an advanced sample project can advance some project uses type script or create an empty hardhat.config.js. For us, we're just going to select create a basic sample project. And this is going to give us all the boilerplate for a really simple hardhat project. The hard hat project route is going to be this folder that we're in right now. Do you want to a
dd a Git dot Git ignore? Yes, we absolutely do. Because we're going to be using dot env files. Do you want to install this sample projects dependencies with yarn at nomic labs hard hat at a theory and waffle at Chai? We're going to go ahead and say yes, and I'll explain what all these dependencies are in a bit. Let's go ahead and say yes for now. And we're going to install all these dependencies. Now, if we look in our package, JSON, we can see we've added a number of dependencies like nomic lab
s, Hardhead ethers, not MacLeods, Hardhead, waffle, Chai, Aetherium, waffle, and ethers. Obviously, we're already familiar with ethers, but the rest of these might be a little new. We'll talk about those later. And great, we now have a sample hardhat boilerplate project. Let's walk through what we just installed here. The first thing we have is a contracts folder, which comes pre populated with greeted outsole is really minimalistic contract here. Next, you'll see node modules, which of course i
s our installed JavaScript dependencies. Something I want to know because it was really confusing to me when I first started working with this is some of these node modules start with an add sign, and then a lot of them don't. What's the difference between those two, these outside node modules are known as scoped packages, which effectively allow NPM packages to be namespace or yarn packages. This allows organizations to make it clear what packages are official and which ones are not. For exampl
e, if a package has a scope at Angular, you know, it's published by the Angular core team. So it's the same thing with this anything with AP ens domains we know is by the ens domains team, anything with abnormal Labs is going to be by the team that created hard hat. So that's why this at nomic labs, hard hat ethers and at nomic labs, hard at Waffle has this at sign, because we know it's published by the nomic labs team, then we have a scripts section. This is going to be where we're adding any a
nd all of our scripts that we want to write like deploying contracts, interacting with contracts, etc. And then we have a test folder. We haven't started building any tests yet. But tests are incredibly important for working with smart contracts. And this sample test folder gives us a minimalistic test for testing our smart contracts. We of course have Git ignore, which of course comes pre populated with some important things to ignore like Dotty and V. And also node modules because node modules
might get too huge push up to GitHub. And one of the biggest changes here is it adds this hard hat.config.js. This file even though it's minimalistic, right now, you can think of as the entry point for all the scripts that we write, it's the configuration file that determines how the rest of our code is going to work and interact with the blockchain. Then of course, we have package dot JSON, we get started with a readme. Remember how the first time we ran yarn hard hat, we were prompted with th
is Getting Started piece. Now if we run yarn Hardhead, we're actually going to get output of all the different options and commands we can use with running hard hat. Now, if you run into an issue where you run yarn, hard hat, and this pops up, but you don't see a hard hat.config.js in your folder, it likely means that there's a hard hat dot config dot j s in a higher level folder, or there's a node modules with hard hat in a higher level folder. So if that happens, maybe CD down a directory and
do a little LS and look to see if you've got a hard hat.config.js or node modules in earlier folder. And because I've actually seen a number of engineers have a couple of different problems here. My friend CAMI is going to explain A couple of different troubleshooting tips you can take to try to avoid these common errors. As a developer the most annoying thing to deal with our environment set of issues. My name is Camila Ramos. I'm a DevRel engineer at edge node supporting the Graph Protocol. An
d I'm going to show you how to solve two common problems that you might see when working on this project. After installing hardhat. And running the command and px hard hat in your new project folder, you're going to expect to get back a menu of options like this, but sometimes you're not going to get that back. And when you run into this error, there is a solution for you. And it usually just means that you have a config file somewhere that it shouldn't be, and deleting it will get rid of that e
rror. What you're going to do in order to find this file that you need to delete is run the command MPX hardhats space, hyphen, hyphen verbose. And this is going to spit out where this file is if you have one, and it's going to tell you exactly where it is so that you can delete it. After you've deleted this config file, you should be able to run MPX hardhat in your project folder and get back that many that we were expecting. Another problem that is pretty common. And I still run into all the t
ime is forgetting to npm install, whenever you're working with a repo that other people have been working on on GitHub. So let's say you're pulling down some code that you and some collaborators were working on together, and then suddenly, it's not working for you, you probably just need to npm install. So in your terminal, go ahead and navigate to where this project is located and then run the command npm install. If there are any new packages that were installed in the time that you weren't wo
rking on the code, those will get installed locally for you so that when you run the code, it will be able to run successfully. What are some of the main things we can do with hardhat in its raw state here, these are some of the main tasks that we can run with hardhat different tasks or just different commands, we can run with hardhat. For example, we can do yarn hardhat counts, which will print out a list of fake accounts we can use with Hardhead. Similar to the list of fake accounts that we us
ed with ganache, we can compile our contracts by running yarn Hardhead compile. Very similar to what we did with ethers Jas and soap Jas, you'll see when we run compile, we get a cache, which is just going to be a quick way to access solidity files, and we also get an artifacts section. This artifacts folder contains all the information about our compiled code we look in here now we can, for example, look in the build info and see a ton of information about our compiled contract. If you're looki
ng contracts, we can see more compiled information. And then if we look in the hardhat, slash console.so, we can see more compiled information. So all of our compliation information is going to be in this artifacts folder. And whenever you want to look to see what's going on on the lower level when you compile this artifacts folder is what has everything. There are a number of other hard hat tasks that we can run as well. But we'll get to them as we go. So now that we have some of the basics of
hard head down, let's go ahead and try doing some of the same things we did with ethers before but with hard hat. So one of the first things we want to do is we want to write and interact with our smart contracts. So let's go ahead and rename greeter dot soul to simple storage dot soul, you can click on the file and hit enter and should be able to rename it. Otherwise, you can go ahead and right click, delete it, and then create a new file and call it simple storage dot soul. We're going to copy
paste all of our code from our previous simple storage that saw into this file, we can make sure that our simple storage is compiling correctly by running yarn hardhat compile. Whoa, it looks like we ran into an issue project cannot be compiled. See reasons below the solidity pragma version of the file. It doesn't match any of the configured compilers in your config. Hmm, well, what's going on contracts slash symbol storage that's Sol zero point 8.8. Ah, okay, let's go ahead and fix them. So we
can open up our hard hat dot config dot j s. Now a quick note on opening files. If you're on Mac and you hit Command P, you can actually start typing in the names of files to get them to them quicker. Or if you're on Linux or Windows, you can type Ctrl p, this will bring up and interestingly if you type man P or ctrl p and then you hit the greater than key. This will drop you into the command palette, know command palette, command palette, search for files, search for commands in our Hardhead d
ot config. Jas, I'm gonna scroll down to module dot exports and change this to zero point 8.8. So that the version that we're going to compile for simple storage, it's gonna be the same version and that hard hat is looking for. Let's run that same command by just hitting up yarn Hardhead compile, and awesome we see compiled one solidity file successfully. We should now see this in artifacts. If we go to artifacts and contracts. We now see two contracts in here, greater and simple storage and we
can see a ton of the information about simple storage we can also see some more lower level in Information and build info. Alright, so now that we have our simple storage contract in here, the next thing we probably want to do is learn how to deploy it. This is where we're going to write our deploy script. Now, for this section, I'm going to be showing you how to write a deploy script. But in the next section, we're going to do it a little bit differently. But this is still going to teach you ho
w to write scripts and worked with scripts in heart app. So we're going to come to our sample script dot j s, and we're gonna go ahead and hit enter and renamed it to deploy dot j s. And if you want to read all the comments in here, you absolutely can, we're just gonna go ahead and delete them all. A quick keyboard shortcut is if you hit Command A or Ctrl, a, you'll highlight all the text in your file, and we're going to go ahead and delete it all. So now we're just going to start from scratch h
ere. Now the setup for our deploy script in here is going to look really similar to the setup of our deploy script. From our previous section, we're going to do imports at the top, we're going to have our async main function, and then we're going to call the main function. So let's go ahead and define our main function, we'll call it async. function main, like that, and then we'll call our main function. And if you want to just copy paste this from the last section, you absolutely can. So we'll
domain that then. Boom, just like that. And because of these semicolons are going to drive me absolutely insane. We're also going to add prettier, and our solidity prettier plugins. So we'll do yarn, add dash dash Dev, prettier and prettier, plug in solidity. Then we can go ahead and create our dot prettier, rc file, we're going to add tab with four, use tabs, false, semi false, and then single quote, also false. Now we're going to be using this prettier rc file setup a lot. So in future section
s, if you want to just copy paste it, you can absolutely do that as well. We're also going to add a dot prettier, ignore, which tells prettier not to format some files, which we want, we don't want prettier to spend a ton of time formatting all of our files, I'm just going to copy paste from the GitHub repo. So feel free to copy paste from the GitHub repo as well, you'd find all the code for this section, like I said, in the GitHub repo associated with this course. Now, unlike in our last sectio
n, where we had to grab our contract code a little bit more manually, with hard hat, it's actually a number of different ways to grab compiled contracts. The first way we're going to do it, we're actually going to use ethers. And now this is where one of the first confusing changes actually comes in. Previously, we did const ethers equals require ethers. And that was how we went ahead and worked with ethers. However, you'll notice in our dev dependencies, we have this dependency called Hard Hat
ethers. Hard Hat ethers is a package that actually wraps hard hat with its own built in ethers. This is really advantageous because it allows hard hat to keep track of different deployments at different scripts and all these other things for us. So instead of importing ethers directly from ethers, we're actually going to import ethers directly from hard hat instead. This might seem a little confusing at first, but just know if we want to work with ethers and heart it, it's usually much better to
pull it in from heart and you can still do this and ethers will still work the same. But hard hat won't necessarily know about different contract factories in different pieces and, and you'll see that in action in a second. Now that we're pulling in ethers, we can actually immediately grab a contract factory using ethers. We can say const simple storage factory equals await ethers dot get contract. Factory simple storage. So in order to get a simple storage, contract factory, we can just do awa
it ethers dot get contract factory. Now if we pulled right from ethers, the package ethers doesn't know about this contracts folder and ethers doesn't know we've already compiled simple storage dot soul. And it's in our artifacts. Hard Hat, on the other hand, does know about the contracts folder and does know that it's already compiled, which is why this simple storage factory grabbing work so well. Once we have our factory here, we can do the same thing that we did in our previous section and d
eploy the contract. So we'll do a quick console dot log. Deploy flooring, contract done, and then we'll do Kant's simple storage equals await simple store edge factory dot deploy And boom, with that little bit of code, we're already able to deploy our simple storage contract, then to wait to make sure it gets deployed, we can do await, simple storage, deployed. And that's it. Now let's see what happens when we go ahead and run this deploy script. As you know, in our last section, we had to put i
n a private key, and we had to put an RPC URL. Right now, we don't have either one of those defined. So what do you think should the script actually work? Or do you think it'll break because we, we didn't define what blockchain we're going to deploy you. We also didn't find a private key. Well, let's go ahead and try this out. We can run the script in our terminal by running yarn, hard hat, run, scripts slash deploy dot j, s. And again, I'm hitting tab here to do a little auto completion and see
what happens. Well, we got deploying contract, it says done, but that's really it. So what really happened? Well, let's add one more line in here. Let's do console dot log. We'll do some string interpolation deployed, contract to. And then we'll add simple storage. That address. Let's run this now. We get deployed contract, and then we get deployed contract to, and then we get a contract address. Hmm, what's going on here. Hardhead has this fantastic tool built in called The Hard Hat Network ha
rd hat comes built in with Hard Hat Network, a local Aetherium network node designed for development, akin to ganache, that allows you to deploy your contracts and run your tests and debug your code. Whenever we run a command in hard hat, or a script and hard hat or a task and hard hat, we by default deploy to this fake Hard Hat Network. This Hard Hat Network is very similar to ganache, except for instead of having this UI, it runs in the background for our scripts. In fact, if we go to our hard
hat.config.js, we can scroll down to the bottom to this module that exports section and add more information about our default networks. So right now, if we don't have anything in this module that export, by default, it adds this piece called default network hardhat. So anytime we run a script, without specifying a network, it automatically uses this fake Hard Hat Network. And this fake Hard Hat Network comes automatically with an RPC URL and a private key for you. So you don't even have to add
one in. This is one of the major advantages of working with Hardhead. It just automatically gives you this fake blockchain. And these fake private keys, if you want to be a little bit more explicit. And I always recommend being more explicit, we can add the default network in to the module that are experts. So now our default network is explicitly stated as hard hat. However, in any script, you run, you can choose whatever network you want to work with. So if I want to explicitly say I want to
run our deploy script on our fake Hard Hat Network, I can do yarn, hard hat, run scripts, deploy dot j s, dash dash network, hard hat, this is us telling her that, hey, we want to run this script on the Hard Hat Network. Hopefully, you might be able to see where this is going. Having this network flag makes it incredibly easy to switch across different chains, different block chains, different private keys, etc. So we have our default network set the hard hat here, we can add other networks in h
ere as well. The way we do that is we're going to add a networks section. And we're going to define any of the network sections that we want. And remember to put a comment there so that your Visual Studio code doesn't get mad at you. So recently, we worked with Rigby so let's go ahead and add a Rinkeby network in here. So we're gonna say another network is gonna be really cool. So I should just be able to change the network flag to Rigby now, right? Well, not quite. If you try to run that, you'r
e gonna get invalid value undefined for hardhat config networks. Rigby, that URL, it's expecting you to tell it, hey, what the URL is, since this isn't the hard hat network, we need to tell hard hat exactly how we're going to connect to rink B. And this is where a lot of what we learned before is going to come in handy, again, exactly the same as what we did before. We're going to create a new Dotty v file, and we're going to add our Rigby URL in this dot env file. Just remember, dot env is an r
dot get ignore just in case. So in our Dotty env, we're going to add that RPC URL from alcmi back in here before we just said RPC URL. But since we might want to work across multiple networks, it's usually good to specify exactly what network each URL stands for. So we're gonna say Rynkeby RPC URL equals and then paste that URL in here. Now, as you probably have guessed, we can add our URL to our Rinkeby network here. for readability, I usually like to add them as variables right above the modu
le that experts. So I'll say const Rynkeby. RPC URL equals process dot E and V dot Rynkeby RPC URL. And once again, we're going to be pulling that Rinckey RPC URL from our environment variable. Of course, in order to pull that environment variable in, we're going to need to use that dot env package again. So to add that in, we're going to yarn add dash dash dev dot EMV. And at the top of our Hardhead config, we're going to add require dot EMV, and then do dot config to enable the config. Now thi
s means we should be able to pull our rink the RPC URL from our dot env. Now that we have that in our Rinkeby network, we can add URL Rinckey RPC URL. Awesome. So we have an RPC URL for different network. But what else do we usually need? Well, we usually need a private key to work with an actual network, or that doesn't automatically give us a private key for rugby, because Hardhead can't just give us test and the Etherium, we need to have an actual account an actual test nets. Hardhead doesn't
control those. So we have to actually give it a real URL and a real private key. So to add private keys, you actually add something called accounts, you add a list of accounts that you want to give to hard hat for us, we're only going to add one, which is going to be our private key. And for our private key, we're going to do the exact same thing. We're gonna say const private key equals process dot e NV dot private key. And since this private key is going to be a real private key for a real te
st net, again, we are going to have to grab this from our meta mask. So it will go to our meta mask, three dots, account details, export private key, and we'll add our password in here. And then in our dot env will add private key equals and then add our private key. Now I know I've said this 100 times, but please, please, please, for learning this, do not use a real key that is connected to any real money just in case, please use a new meta mask. I've know I've said it a bunch. But some people
go no, I'm going to be okay, I'll be safe. Just to be super, super safe here, please use a brand new meta mask. So now that we have a private key, we're going to add it in here account private key. And now we have an account here. One more thing I like to do is I like to give the chain ID of the network, which for Rigby is going to be for every single EVM base network as a new chain ID and EVM network basically just means solidity works on it. This includes all test nets, there's a good site cal
led chainless.org, which may or may not be going down at some point, it has a list of all these different networks. For example, you can see on here a theory main net has a chain ID of one byte and smart chain is 56, avalanches, 4311 for Phantom, opera 250, Polygon, 137, etc. Each one of these EVM compatible chains has their own chain ID, rank V, the chain ID is for adding the chain ID is helpful here for later on. And we'll get to that in the future. But for now, just go ahead and make sure to
add your chain IDs. Okay, now that we have the RPC URL, we have the private key, we can go ahead and test deploying this to an actual test net, and actually did something incorrect here. And we're gonna get an error here. And I want you to go ahead and try to figure out and debug this error yourself. You're ready. Alright, let's do it. We'll do yarn, hard hat, run scripts, deploy dot j s, dash dash network Rinkeby. And we get this wonderfully weird error, which we see we have deployed contract.
So we know that in our deploy script, we get to at least this line, but then we're getting an error, I highly likely hear what's going on saying cannot read properties have no reading send transaction, if you want, you can absolutely go to this spot. But it basically it looks like it's having a hard time understanding what the private key or what the account of this is. And what do you think I'm going to recommend we do? Well, if it's not clear, after doing a little bit of triaging and debugging
, we're going to copy this air. And we're going to come on over to Google and paste that right in. It looks like we do get a question here from stackexchange Etherium. And it looks like it's really similar to what we're doing. We scroll down. They're running nearly the exact same script that we're running, they're using MPX instead of yarn. They've got a pretty minimalistic deploy file. Let's scroll down and see what the answers have to say. I've seen this error where my private key wasn't prope
rly populated. I would also use an environment variable I'm pretty sure Are environment variables good. But we have a second one saying in your heart head, I can think that Jas, it should be accounts instead of account, it works for me, let's go back to our head config and see if that's what's going on. Uh huh, we put account in this should be accounts. So let's swap that over to accounts. We'll clear our terminal. And we'll run this again. Uh huh. And now it's reading a little bit longer, which
is good. This means that we're probably deploying this to rink B, which is what we want to see. Awesome. And now we can see deployed contract to, and we have a contract address here. So we'll grab this contract. And we'll pop on over to bring the ether scan, that's numbering the ether scan. And we'll go ahead and we'll paste this in. Awesome. And we see our contract was created about 26 seconds ago. Perfect. Now for this part, you don't have to deploy this to rink be with me, if you follow alon
g here. That's good enough. So remember, the flying to test that's can take a long time. So for this one, you don't have to deploy with me. Alright, great. So we've deployed to rink be using hard hat. This is fantastic. Now something that we notice, once again is oof, our contract isn't verified? Do we have to go back through and do this verify and publish and all that stuff again? Luckily for us, we actually don't need to do that. So what can we do? Well, back in our deploy script, we can add s
ome code to automatically verify right after we deploy. So let's go ahead and do that. Right below our main function, we're gonna create a new function called verify, we're gonna say async function, verify. And we're gonna have this function get past some arguments, we're gonna have to get past a contract, address, and some arguments or the contract. Since our simple storage doesn't have a constructor, the arguments for simple storage are just gonna be blank. But in the future, when we have cont
racts that do have constructors, the arguments are going to be populated. And when we get there, you'll see what I mean, we need at least the contract address, and we're going to add some code in here to automatically verify our contracts after they've been deployed. This auto verification process works on block explorers like ether scan, it might not work on block explorers like eath, pler, or other block explorers. But if you want to verify on these other block explorers, I'm sure they have an
API to allow you to do that as well. Now, ether scan in most other block explorers have a section on their website called API documentation, or something to do with API's. These are ways for us to programmatically interact with ether scan, and do stuff with them. One of the main things that we can do is we can actually verify our contracts through this API. Ether scan even has a tutorial in here called verifying contracts programmatically. And the link to this will be in the GitHub repo, they h
ave an API endpoint that we can make some requests to to go ahead and verify our contracts. Now, we could absolutely make the raw API calls and follow the tutorial here. But there's actually an easier way than even going through this tutorial here. Hardhead is an extensible framework, meaning you can add something called plugins to it. There's even an advanced section in the documentation called Building plugins. If we scroll down to the bottom, we can see some popular plugins that the nomic lab
s team or the Hardhead team has created. And also a number of community plugins as well. One of the most used Hardhead plugins is going to be this hard hat ether scan plugin that makes this verification process much, much easier. Install it, you can just run npm install bash, just save dev at nomic labs harden ether scan, and then add it to our hard hat dot config. Since we're using yarn, we're just going to go ahead and use yarn. So back in our code, we'll do yarn, add dash dash Dev, at nomic,
labs, slash hard hat slash hyphen, ether scan. Now that we have this plugin, we can go to our hard hat dot config, scroll to the top and add this plugin do require at nomic labs slash hard hat, ether scan. Now that we have this plugin, the hard hat documentation has some more information about the usage, how to actually use this plugin, and how to run different commands with it. In order for us to use this verification, we actually need an API key from ether scan. This is basically a password fo
r allowing us to use the ether scan API. So we're going to come to ether scan. And we're going to go ahead and sign in. And actually we're going to click to sign up and create an account. And we'll go ahead and create an account. We'll go ahead and verify our registration by clicking the verification link. And we'll click the Login. Now that we're logged in. On the left hand side, we can scroll down to API keys. And we can go ahead and create a new API key. We call this H H hyphen sec, which sta
nds for hardhat Free Code Camp. Great, this new API key will copy this and we'll go back to our code and we'll add this somewhere since the API keys basically considered a password. Where do you think we should add this? That's right in our dot env. So in our dot env, we're going to add a new entry called ether scan API key. And we're going to add that API key that we just got. Now that we have our API key, back in our Hardhead, config, we're going to create a new section in a module dot exports
, tell hardhat that we have this ether scan API key, or new section is going to be called ether scan. And in here, we're gonna say API key is going to be ether scan API key that we're going to define up here the same way we define these other keys. So we'll say const, ether scan API key equals process dot e NV dot ether scan API key. And if something like this pops up, you can generally just hit enter, and it will autocomplete it for you, which is awesome. Great. So now we have an ether scan API
key back in the heart had documentation, it tells us by adding this, we actually get a new task called verify. Let's try that out. So open our terminal back up. And we'll do yarn, RT hat. Let's see what pops up. Wow, we did get a new verification here. When we run yarn hard hat harder, it actually looks into our hard hat.config.js and checks for any plugins. If there are new plugins there, it'll add them as a new task that we can do. You can manually verify your contract by doing yarn or MPX Ha
rnett verify dash dash network, the deployed contract address and any constructor arguments yourself. But we want to be a little bit more programmatic than this. So what we're going to do is we're going to go back and create this verification function, it is good to know how to do it via command line so that if you want to verify something in the future, manually, you can, let's build this verify function though. So we're going to take the our contract address and some arguments. And for our sak
e, we're going to do console dot log verifying contract that that just so that we know we might have to wait for a little bit. And in our code, we can actually run any task from hard hat using a run package. So up at the top, we're actually going to import run from hard hat as well run allows us to run any hard hat task. So in our code here, we're going to do a wait to run. And then we can do there it thought. Now part of that allows you to add different parameters as well in this run. And it's
usually best that you go ahead and add them in here so that we're really specific with what we're doing. If we do yarn hardhat verify dash dash help, we can see what parameters we can actually pass. Well, it looks like we can pass the Verify parameter. So we'll do colon, verify. If you go to the actual GitHub for the verification tasks, you can actually see you can do more than just verify, you can do verify, get minimum build, verify, get constructor arguments, verify, verify, which is what we'
re going to be working with, and a couple of other subtasks as well. The second parameter that goes inside run is going to be a list of actual parameters. This second parameter here is just kind of the sub task, if you will, of our verify task. And this is going to be an object that contains the actual parameters. And this is where we pass in an address, which is going to be our contract address, and then our construct or arguments, which is going to be arcs. Now normally just this right here sh
ould be enough for us to go ahead and use this verify contract in our main function, but we're going to add one additional thing to it. Because in practice, sometimes there's some errors that can come up. One of the errors that often comes up when running a wait is that the contract has already been verified. And you'll actually likely run into this, because ether scan will get smart enough by seeing enough bytecode that is exactly simple storage that it will start to just automatically verify a
ny bytecode that looks like simple storage. And then this await will throw an error, which we want to avoid. So what we can do is we can add a try catch onto this await. So outside of the way, we're going to add a try. And we're going to add these little brackets that wrap around our weight. And then we're going to put a catch. This is known as a try, catch and solidity also has tried catches. But basically, this e is going to be any error that this section throws. So we're going to do is we're
going to say if this message is already verified, then we're just going to continue. So we're gonna say if e.message.to lowercase, we're going to make sure it's to lowercase that includes already there. If five, then we're just going to console dot log already verified like that. Otherwise, we're just going to console dot log e. The reason we do This is because of this errors, our verification function will break, and our whole script will end. And we don't want our whole script to end, we want
our script to keep continuing if the verification doesn't work, because it's not really a big deal. So I know this might seem like a lot of code, feel free to copy and paste it from the GitHub repo to just move along. But awesome. So we now have a verify function using the Verify task in hardhat. Let's go ahead and use this now in our main function, right below our deploy, we'll do console dot log deployed contract two, and then the contract address. But before we call this main function, let's
think for a quick second. What happens when we deploy to our RT Hat Network? Well, remember, if we deploy to our Hard Hat Network, will our contract need to be verified I need to scan? Well, we know there's a we know there's a rink ether scan, we know there's a COVID ether scan, we know there's a main net easy scan. But is there a Hardhead ether scan? No, of course not. Right? The hard at runtime environment is a network local to our machine. So it doesn't make sense for us to verify a hard hat
network deployed contract on ether scan. So we actually don't want to call this verify function, when we're working with our local network. This is where these chain IDs are going to come in quite useful. What we can do is we can check to see if the network that we're running on is a live network or it's a test net, or it's a network that actually can be verified, we can actually get network configuration information by importing a network like this. And we can do something like console dot log
network dot config. Now, if I run yarn, art, hit run scripts deploy.js. On our Hard Hat Network, since I'm not passing a network flag, we get this massive output that looks like this. Our network dot config contains a ton of information about the current network that we're on, you'll see here that the chain ID of the Hardhead network is actually 31337 gas price, which gets set to auto block gas limit the current fork of Aetherium that we're working with, and all these other pieces here. This cha
in ID is really important. Because we can use this chain ID to figure out which one is a test net, or which one is a live network. And remember, running the script is going to be the same as doing dash dash network, hard hat, you'll see our channel ID is still 31337. Again, that's because the default network in our heart had config, it's hard hat, which is the same as saying every single time we run a script, we're secretly running it with dash dash network hard hat. So now we only want to verif
y on our test net. So what we can do is we can say if network dot config, that chain ID equals equals equals four, which is going to be rank B, ad. And a JavaScript equals equals equals is nearly the same as equals equals, except no type conversion is done, which just means in JavaScript, four equals four, and four equals equals the string of four, but four, but if you were to use four equals equals equals four, this is false. This is true equals equals four equals equals would be true, four equ
als equals to the string of four would also be true, but four equals equals equals to the string of four is going to be false. So you can kind of do whatever you want here equals equals or equals equals equals. So we want to say if the network dot config dot Trinity is four, so if we're on Rinkeby, then we can go ahead and actually verify. But we also want to make sure we only verify if our ether scan API key exists. So we can also in here is site and this double ampersand means and we can say p
rocess dot e NV dot ether scan API key. This is some Boolean tricks that we're doing here, basically, so our first conditional we're saying if network dot config chinati equals equals equals four, this section can be true or false, obviously, right? The chain ID that we're running on can be the hardest network, which would mean this doesn't equal four, or it would be Rinckey, which means this does equal four. But there's no conditional on this side. So how does this side work? In JavaScript, if
an object exists, and you try to cast it as a Boolean, it will be converted to true. If it doesn't exist, it will be converted to false. So in JavaScript, basically, if either scan API key exists, if we have this in our data in VI, this will be true. And if not, this will be false. So another way to read this line here is saying if network dot config that Trinity is for AKA, if we're on rink B, and our ether scan API key exists, then do some stuff. And that's what we're going to do here. So in h
ere, we'd want to run verify, or verify function and pass it the contract address which is going to be Simple Storage dot address and the constructor arguments which we know are going to be blank. And since our verify function is an async function, and it deals with promises and stuff, we want to add the await keyword here. Awesome. So we've added a way to actually verify our contract. But we're not quite done. See on ether scan and all these block explorers the instant we deploy the contract an
d the instant we send the contract, ether scan might not know about the transaction yet, it might take a hot second for ether scan to be up to speed with where the blockchain is. So it's usually best practice to wait for a few blocks to be mined, until you actually run your verification process. We've actually learned how to do this already with the deploy transaction. So before we actually verify we run, we want to run a weight, simple storage. Deploy transaction Wait, six. So we will wait six
blocks, and then we'll run our verification process. Now, if you want to go and test this out right now, you absolutely can. I'm going to keep going, though, because again, testing all these on a test net takes a little bit of extra time. So I'm going to finish the rest of our main function, and then I'm going to run everything all together. Okay, cool. So we've deployed our contract, we've automatically programmatically verified our contract. What's next? Well, what did we do last time, we star
ted interacting with the contract. So let's do const. Current Value equals await simple storage dot retrieve. To get the current value, simple storage, that's all. We have a retrieve function, which returns the favorite number, so let's get the current value. And we'll do console dot log, the current value is and then some string interpolation, current value. And then we'll go ahead and update the current value by doing cons. Transaction response equals await simple storage, that store will stor
e the number seven, and then we'll await transaction response dot Wait, we'll wait one block for that transaction to go through. And we'll grab the updated value by saying const updated value equals await simple storage dot retrieve. Then we'll do console log. The added value is updated value. Awesome. And this is going to be our whole script. So if I can zoom out for a little bit, I know it will be a little bit small here, we've got this huge main function, which does what? Well it deploys our
contract. If we're on a test net, it then verifies our contract. And then it updates the value to seven. And we have our verify function down here. And we have a section of our code that calls our main function. Now for run this on the hard hat network. What do you think will happen? Well, let's try yarn, or net run scripts. Deploy dot j s. Alright, awesome, we get exactly what we saw before we get deploying contract deployed contract to current value is zero, update value seven. And there's not
hing in here about verification. That's exactly what we want. Now, moment of truth. Let's try this on Rinkeby. We'll do yarn, RT hat run scripts, deploy dot j s, dash dash network Rinkeby. And it's gonna go a lot slower, because obviously now we're deploying to an actual test net, where the blocks actually need to be mined. And we see we haven't deployed the contract. Now that our contract is deployed. We know that we're currently waiting six block confirmations for us to go ahead and verify. An
d actually I should add console dot log, waiting for block the x's so that we don't get campus weird. Oh, wait, what are we doing now? That it looks like we ran into this error, no such file or directory, it looks like our code might not have compiled correctly here. So here's what I'm gonna do. We're gonna go ahead and delete our artifacts to trash. We're gonna delete our cache as well. And we're going to try rerunning this whenever you run a script with the hard drive command Hardhead will aut
omatically recompile it for you, especially if there's no artifacts folder. So we're going to rerun this command and heartbeat, it's going to compile first and we can see that it does exactly that. And then it's going to go ahead and redeploy. Hopefully this time, it should be able to find the contract that had just compiled looks like this time after I deleted the artifacts folder, we actually did indeed get some successful compilation. And we can see here successfully submitted source code for
contract or verification on the block explore waiting for verification results, successfully verified contracts simple storage on ether scan, and even gives us a link that we can go ahead and Command click or control click into. And we can see the contract indeed being verified. This is awesome. This is perfect. We've now got a successful deploy dot j s script that can deploy, verify, and then interact with our code. This is fantastic. This hard hat thing seems pretty cool. What else can we do
with hard hat like I showed you before. Hard Hat comes with these tasks. And the number of tasks that Hardhead can come with can be extended by us writing plugins, we can actually write our own tasks in hardhat. And in our Hardhead dot config, it can defaulted with this task account, we can see task accounts, prints the list of accounts, and just prints a list of accounts here actually go to the heart had documentation to learn more about creating our own tasks, one of the ways that you can defi
ne tasks is directly in our heart head.config.js. But typically, what people do is they have a new folder called tasks where they put all their tasks. So for now, I'm gonna go ahead and delete this section here. And we're going to create our own task. You'll notice that now that we've deleted that section, if we run yarn RDAP, we no longer see the accounts task in here, because we've just deleted that task. So let's create our own new task. We'll call this block number.js. And we'll use this to
get the current block number or whatever blockchain that we're working with. So let's create this task. First, we need to import the task function, we can get it by saying const task equals require arhat slash config. The hard hat slash config has the task function. To define a task, we can now just say task, give it a name and a description, the name is going to be blocked number. And then the description is going to be prints the current block number. Now that we have this task, there's a coup
le of things we can actually do with it, we can add different parameters to it by using the dot add command, which allow us to pass parameters to the task. And then we could also set actions which define what the task should actually do for us, we're just going to do dot set action. And define what we want this function to do. So we're going to make this an async function, that's going to take as an input, the task arguments, which are going to be blank for us, and the HR E, which I'll define in
a second. Now, let me explain the syntax really quickly. This might look a little bit weird, but this is what's known as a JavaScript arrow function. In JavaScript, you can actually define functions without even using the function keyword. For example, if we go back to our deploy function, we have our async function verify down here. However, another way we could have defined this is is without using the function word at all, and actually turning this whole thing into a variable, we could have
said instead, we could say const verify is going to be an async function that takes contract addresses and arguments. And here's the function definition. These two lines are essentially equivalent. There's some slight differences between between using the function keyword and having your function be a variable. But for the purposes of this course, they're basically the same. Which means though, that this by itself is a function, just not assigned to a variable. But essentially, the two of these
do are exactly the same. And that's the syntax that we're doing here. You can imagine this sort of being like const block task equals async function, which takes the params and then runs that arrow function. Or you can think of it as async. Function, block task parameters, and then the function definition, these are all essentially the same. The major difference is that we're never giving our function a name, we never give it this block task variable. This is known as an anonymous function in Ja
vaScript, because it doesn't have a name. Now that we have our function in here, we can now call some function to get the block number. Well, how can we get the block number when we run tasks, we automatically pass our anonymous functions, the task arguments, which in this one, we don't have any, but we also pass this HR II object. This HRV is the heart hat runtime environment. Back in our deploy script, this is basically the same as this require hard hat in here. So this HRV can access a lot of
the same, this HRV can access a lot of the same packages that the hard hat package can. So we can do Hae dot ethers, just like how you can import ethers from hard hat. And in our ethers package, there's actually a number of functions we can use like dot Pro, biter dot get block number. Let's save this to a variable const blocked number equals, and this is going to be a synchronous, so we're going to want to add a weight here. And then let's do console dot log block number. Or better yet, we'll
string interpolate this and say current block number like this. Now though, if I try to run this task, you'll notice it doesn't show up in the heart Atlas of tasks, let's do yarn. Art app. Hmm, I don't see block number in here. Well, this is because we need to add it to our config dot config will add require dot slash tasks slash block number. And in order for us to import it, and let's add a module that exports I'll explain what this does a little bit later. But now that we've required it, if I
run yarn hard hat, and now see blocked over is one of the tasks that I can use. Now for a run yarn, art hat block number, we get current block number is zero. And this makes sense because this is defaulting to our Hard Hat Network, which gets reset every time we run it. But if I run yarn, hard hat block number A dash dash network Rinkeby, what do you think I'm gonna get? Again, a much larger number, current block number is right here. Because this is the actual block number of Rigby versus the
block number of our heart ad network is going to be zero because it gets reset every single time, we run one of these scripts now scripts and tasks both can basically do the same thing. They both can interact with contracts, they both can deploy smart contracts, they can both pretty much do everything. I prefer scripts just as a general rule of thumb, because I don't always think adding a special thing from the command line makes sense. So I prefer scripts, but you'll see a ton of tasks and exam
ples out there as well. I think tasks are really nice for specific use cases. But for the most part, we're pretty much going to use exclusively scripts, but it is good to know what a task looks like and how to use it. I think tasks are better for plugins and scripts are better for your own local development environment. But if you want to do everything with tasks, you absolutely can. As you're starting to see, this config piece is pretty powerful. And we can use it to modify our entire code base
and our entire project to give our project more functionality. What else can this do? Well, right now, as you can see, every time we work with a hard hat network, every time we run a script, we run that script, and then the Hard Hat Network is deleted, right? We can't interact with our contracts anymore. Well, there's actually a way for us to run a hard hat network. Similar to how we ran a ganache network with a user interface. What we can do in hard hat is run yarn, RT hat node. And what this
will do is it'll spin up a node on a local network, exactly the same as ganache but in our terminal. So you see here started HTTP and WebSocket. JSON RPC server at this address. And just like nosh, it comes packed with all these different accounts and private keys, which is awesome. You'll notice though, interestingly enough that this node that we're running isn't on the Hard Hat Network, well, we can actually create a new terminal to try to interact with this just by hitting this little plus bu
tton and creating a new terminal. Again, I'm using bash, but based off of whatever your operating system is, you can be using a different shell. And here, let's go ahead and run yarn arhat run scripts, deploy dot j s, and see what happens. Well, our typical setup happens, we deploy a contract, we get a contract address, we update the value. But if we look at our node, it doesn't look like any transactions went through what we don't see any locking here. So what's going on? Well, our Hard Hat Net
work is actually different from this locally running network here. This locally running network we often want to refer to as our local host. So it's slightly different than the Hard Hat Network. It's still using the hard hat runtime environment, but it's just not this default Hard Hat Network. It's considered its own separate network when we're running a node that it's going to live. of past the duration of a script. So we can actually interact with this by adding a new network to our hardhead.c
onfig.js, we'll create a new network and call it local host. And exactly as we did up here, we'll give it a URL accounts and a chain ID. So for URL, we can get that URL right from our terminal, I'll put a running yarn hard hat node. by copying that and pasting it in here, we can then do a comma, we'll give it a chain ID of 31337. Because even though it's considered a different network, it actually has the same chain ID as hard hat. Interestingly enough, I know I just said we were going to give i
t accounts, but we actually don't need to give it accounts. Because when we run with this localhost hard hat will automatically give us these 10 fake accounts for us. So you can kind of think of the accounts here for this localhost as, as hard had already placing them in thanks, hard hat. But now, if we go back to our bash here, let's clear the terminal. Let's rerun the script. And we'll do dash dash network local host. Now we should be pointing to this node. And when I run this script, we shoul
d see some logging output at the end of this node. So let's go ahead and hit enter. Well, we see our normal stuff on our deploy script, we flip back to our node Wow, we see a ton of logging here. Similar to ganache, we can see a whole bunch of different logs on what just happened, we can see a contract was deployed, we can see the address the transaction hash from value, gas, and the block number and everything. We can also see our contract call calling the store function to update the value of
our favorite number. This is incredibly powerful for quickly testing and working with things on a local JavaScript VM or hard hat network to be able to see how your contracts will interact on a real test net. And this is much quicker than working with a real test net. Now additionally, same as what we said before, any process that's running in the terminal, we can kill it with Ctrl C. So if you want to stop your node and then restart it, you can hit Ctrl. C, to stop it, and then just up and then
rerun that same command to re spin up your node Ctrl C stops it. And then you can up to start again. Another way you can stop it, of course, is if you hit the trashcan, which deletes the whole terminal, we pulled a terminal back up, we can run it again. And just remember, if you hit the X that actually doesn't delete the terminal, that just hides it. So our hard hat node right now is still running because I just hit it. So I pull it back up, I can see that it is indeed still running. But if I t
rashed candidate, and then it pulled the terminal back up, I can see that it is no longer running. So running scripts is great. But what if I don't want to have to code an entire script to do some things? What if I want to just tinker around with the blockchain? Well, hard hat comes packed with this thing called the console. The console is a JavaScript environment. For us to run JavaScript commands to interact with any blockchain, we can jump to the console by running yarn, hardhat, console, and
then whatever network flag if we want to work on rink B, main net polygon, avalanche, etc. That's just network local host. And now we're dropped into a shell him in the shell, we can do everything that we do in a deploy script. And we don't even have to run these imports, because everything with hard hat is automatically imported into our console. So for example, let's say I wanted to get a simple storage contract factory. Well, I could run exactly this line here. I could say const, simple stor
age, factory equals await ethers dot get contract factory, have simple storage. And now I can go ahead and even deploy this. So I can even just copy this line, paste it. And if we flip back to our node, we'll see that we just deployed a nother simple storage. And now we can do things like await simple storage dot retrieve. And I get the return value which is going to be a big number with a value of zero. I can also make transactions so I can do a weight, simple storage. That store let's do 55 If
I hit up twice, I can go back to the simple storage dot retrieve. call that function and I can see my big number has a value of 55. Now, this is a great way to quickly interact with any blockchain that we want. Now you can exit the shell by hitting Ctrl C twice to get out. Or you can also just you can also Trash Can your terminal if you get confused. This console works with any network we can even do yarn, hard hat console dash dash network hard hat. And we'll get dropped into a hard hat networ
k. Now this is not going to be the same node that's running here, this is going to be one that only runs for the duration of this command. So whenever we cancel this command, this hard hat network gets cancelled. And close out that too. We can also do yarn, hard hat, console, dash dash network Rinkeby Rigby, or polygon or test net or main net or whatever we want. And we can do things like ethers dot provider that can do things like await ethers dot provider dot get block number, see the block nu
mber of Rigby. We can also deploy contracts, we can update contracts, we can do anything that we want, you can do anything in these consoles, and they're great ways to quickly test and tinker in interact with contracts. Now, there's a couple other tasks that are really helpful. You'll see before I went ahead and just deleted artifacts and deleted the cache manually. Well, to do that yourself, you can also just run yarn Hardhead, clean. And that'll delete the artifacts folder and clear out your c
ache. We already know what compiled does. But one of the biggest things that Hardhead is fantastic for especially is running tests. Now we haven't run tests yet so far. However, running tests is absolutely critical to your smart contract development journey. And we're going to spend a lot of time in the future writing really good tests. The reason that writing tests are so important is because we want to make sure our code does exactly what we want it to do, especially in the defy, and the decen
tralized, smart contract world, all of our code is going to be open source for anybody to interact with, and potentially exploit. There's sites like req dot news, which go through a ton of previous hacks and how they actually got hacked and what happened in the smart contract to enable these hacks to occur. So testing, so writing really strong tests is always going to be our first line of defense. And we have this sample test.js, that comes default with the basic package of hardhat. But as you p
robably already know, we're going to rename this and change it. So we're going to rename this to test deploy dot j s. And we're going to delete everything in here and start from scratch. We want to be able to test all of our solidity code locally, so that we know exactly what it's doing. And we can have a programmatic way to make sure that our code does what we want it to do. So let's write a basic test for our simple storage contract. So that we can be sure that it's doing exactly what we want
it to be doing. Hard Hat testing works with the Mocha framework, which is a JavaScript based framework for running our tests, you actually can write tests directly in solidity, if you'd like to, there's a bit of back and forth on whether testing with pure solidity is better or testing with a modern programming language. The argument goes that testing with a modern programming language, you have more flexibility to do more stuff to interact and test your smart contracts. But the argument for test
ing with us with solidity is that we want to be as close to the code as possible. At the time of recording, most projects do the vast majority of their testing in a modern programming language like JavaScript. So that's what we're going to be using here. So to get started with our mocha tests, we do, we're going to write a describe function. Describe is a keyword that hardheaded mocha will recognize, and it takes two parameters, it takes a string, which we're going to just write simple storage f
or now. And then also takes a function, we could make function, test func and then write some stuff in here, and then pass it to our describe here. But the common convention is going to be to do is to make it as an anonymous function, which we can create by typing function, putting an empty parameter here, and then some brackets like that. So our describe function takes a name, a string, and a function. Another way that you'll often see functions in describe is using that anonymous function synt
ax. So you might see just these parentheses, an arrow, and then some brackets, the two of these are going to be basically the same, there are some differences. And this second one is actually best practice, but just know that you might see this arrow syntax in other tests as well. We have described a sample storage and then our function here, which is going to have all of our tests in it. Inside each one of our describe blocks. We're gonna have something called a before each, and a bunch of It's
Our before each function is going to tell us what to do before each of our hits. So we're going to have a ton of it and then we're going to have a before each. All of our IDs are going to be where we actually write the code for running our tests. And before each is going to be some code that tells us what to do before each one of these hits, we can also actually have describes, inside of describes, which again have more before each and more before it's having these nested describes can be reall
y helpful for separating and modularizing our tests. But for this one, we're just going to have a setup that looks like this. And for this demo, we're only going to have one it. So in order to test our smart contracts, before we actually run our tests, we're probably going to need to deploy the smart contracts first. So inside of our before each, we're going to pass the our before each a function, that's going to tell our testing framework what to do before each test. So we're going to pass it a
n async function like this. And in here, we want to deploy our simple storage contract. So to do that, we're going to need to get the ethers framework and do exactly what we did in our deploy script. So in here, we're at the top we're gonna say const. Ethers, equals require art have an import ethers from hard hat. Then in our before each function, we'll say await ethers dot get contract factory of simple storage. And we'll assign this to a const. Simple Storage factory. And then we'll run away,
simple storage factory dot deploy. Cool. And let's also assign this to a variable cost simple. Now, since right now, our simple storage and simple storage factory are scoped just to inside the before each, we actually need to stick these variables outside of the before each, so all of our events can interact with them. So instead of having simple storage, factory, and simple storage, be constant variables, we're going to define them outside of them for each with the let keyword. And we're gonna
say let simple storage factory and we're going to initialize it to nothing. And then we'll say led simple storage. Now, if you have a whole bunch of let's just initializing another way, you can write them in JavaScript, just let simple storage factory comma, simple storage. And that works exactly the same. And then we can get rid of this const keyword. Because it's not a constant since we are assigning it. And now we have simple storage, factory and simple storage that we can use inside of our i
nit function. Now we have a before each section. So before each one of our tests, we're going to deploy our simple storage contract. So we have a brand new contract to interact with for each one of our tests. Now, inside of the ID, this is where we're going to say what we want this specific test to do, and then describe the code that's going to actually do that. So we're going to say it should start with a favorite number of zero. So this is saying what this test should do. And then we're going
to add our async function to actually do that. So we'll say async function. And in here, this is where we'll actually write the code to make sure that our contract does exactly this. We're say const. Current Value, equals await, simple storage.re retrieve. And now in this test, we want to say okay, now check to see that this current value is indeed zero. So how do we do that? Well, we can say const, expected value is going to equal zero. And what we can do is we can do either we can use either t
he assert keyword, or the expect keyword, which we're going to import both of these from a package called Chai. We actually installed Chai automatically when we downloaded the basic parameters when we downloaded the basic packages for hardhats. So at the top, we're gonna say const. Expect and assert equals require Chai, I'm a big fan of using assert as much as possible, because I think the syntax makes a little bit more sense. But there will be scenarios where we need to use expect instead. Now,
assert has a ton of functions that are built in that help us make sure this is what we expect it to be. So I can do assert dot equal current value.to string, because remember, this is actually going to be a big number, comma, expected value. So I'm saying I'm asserting this retrieve to return zero, which is going to be our expected value. Now to actually run this, we're going to run yarn, art hat test. And we see we get an output that looks like this should start with favorite number of zero, a
nd it's indeed passing. You'll notice that if I were to change this to one, and this wasn't correct, it would break and it would say art Pass or not passing assertion error expected zero to equal one. It expected zero to equal one, which is not what we want. We want zero to equal zero. So let's run this again. Tada should start with favorite number zero, and it's passing. Alright, fantastic. So that's how we wrote one of our tests, let's write one more test just to make sure that things are good
. So let's say it should update when we call store, because when we call the store function, we want our favorite number to update. And we'll make this an async function as well. And let's add our stuff in here. So we'll say const. Expected Value equals seven, we're expecting that when we call store it updates to seven. Now we can say const. Transaction response equals await simple storage dot store. And we can even just pass it the expected value here. And then we'll do a weight transaction res
ponse that weight one. Now let's get the current value. So we'll say const. Current Value equals weight, simple storage, retrieve. And now we're going to assert dot equal current value.to string, comma expected value. And now we can run all these tests by running yarn Hardhead test. And you'll see we ran both of these tests. And now if I have 10,000 tests, and I'm only finagling with one test, I can actually just run one test by running yarn, art app, test, dash dash grep. And I can search for a
ny keywords in any of the text here. So I'm going to grep for the store function. Because the store keyword isn't in this tax for this, it, it's only in the text for this it. So if I do grep store, it should only run our second test, which does indeed, one other way we can run only specific tests is with the only keyword. So we can type it dot only like that. And then we can run yarn, art hat test. And it should only run, this should update when we call store. And it does indeed, then we'll go a
head and delete this save, run again, and it should run all too. Fantastic. Now the other way you'll see these tests written is with instead of assert, it'll use the expect keyword. So you'll see something like expect current value.to string.to dot equal expected value, the two of these lines do exactly the same thing. And it's sort of up to you on which one you want to use. And that's all we're going to do for our testing. Now. This is fantastic, great job. Now that we have some tests, we can a
ctually start testing to see how much gas each one of our functions actually costs. One of the most popular extensions for hard hat is the hard hat gas reporter. This is an extension that gets attached to all of our tests, and automatically gives us an output that looks like this, that tells us approximately how much gas each one of our functions cost. We scroll down in here, we can read the instructions on how to actually install this npm install Hardhead gas reporter which we're going to use w
ith yarn. So we're gonna say yarn, add hard hat, gas reporter, dash dash Dev. And now that that package is installed, we can go over to our config and add some parameters in here so that we can work with this gas pit. But our neath our ether scan section, we're going to add a new section called gas reporter. To have it run, whenever we run our tests we're going to do enabled is going to be true. And then up at the top, we can add it by adding require hardhat gas reporter. Now that we have it in
here, we can do yarn hardhat test, and after we run our tests, it'll automatically run this gas reporter. So we see our tests go ahead and run. And then we get this output that looks like this that tells us how approximately how much our contracts and methods cost. So our store function looks like It costs approximately this much gas and our simple storage costs approximately this much gas. This is incredibly helpful for figuring out how to optimize our gas as best as possible. Now I usually lik
e to take it a step further though. Having the gas output it like that is nice, but we can make it even better. I like to output it to a file by doing output file. Yes, report dot txt and then my dot get ignore like to add it in here, but doing gas report dot txt sentence it's not really important for the gas report to get pushed up to GitHub. Do no colors is true. The reason we add this is because when we output to a file, the colors can get messed up basically. And then the biggest addition we
could do is we can add a currency in here. So that we can get the cost of each function in USD for a blockchain like Aetherium. Now in order to get a currency here, we actually need to get an API key from corn market cap, just like we did with ether scan, you can go to coin market cap, corn market cap API, get your API key now, and we'll go ahead and sign up. Choose a basic plan. We'll agree and create my account, we'll get an email verification. And we'll go ahead and verify. Now in the coin m
arket cap dashboard, we can copy our key. And yep, you guessed it exactly what we're going to do with this key, we're going to drop it into our dot env file, or say coin market cap, API key equals and then paste it in there like that. Now that we have our corn market cap API key in here, we can go back to our header dot config and add it in this corn market cap parameter. We're gonna do the exact same way we did above, we'll do const, coin, market cap, API key equals process dot EMV, that coin m
arket cap API key, and then we'll take this sticking in here. So what this is going to do is actually going to make an API call to corn market cap, whenever we run our gas reporter. This is why sometimes you'll see me comment this out and uncomment it because I don't always want it to make this API calls. But now what we can do now that it's enabled, we have an output file, we can see the currency and we have our API key, all we can do is run yarn hardhat test. And after all our tests pass, we'r
e going to see a gas report.tx T that we can go ahead and read from which has that gas report. And now it actually has the USD price of each one of these transactions, it looks like at current prices, with Aetherium being $3,000 per eath, and a gas price of 43 Gwei, the store function would cost $6. And the simple storage function would cost $64. The current the Hardhead gas reporter actually comes with some different options, though, if you're going to be deploying to different network, for exa
mple, with binance, Polygon, Avalanche or hecho. For example, let's say we wanted to deploy the polygon, let's see how much deploying the polygon would cost well in our WMV UHD ad token, Matic And now we'd rerun this test. And if we look at our gas report that takes T will now see the gas price of polygon right now is around 37 Gray per gas. And the cost of Matic is 147 automatic and USD. Now we can see the cost of calling the simple storage method is going to be $0.00. Now this of course is rou
nded down, but it's going to be really, really cheap to call store versus deploying the contract is going to cost three cents, I make it a habit to select false for my gas reporter whenever I don't want to actually work with the gas here. Awesome. Now sometimes when we're working with our code, if we don't have these environment variables specified Hardhead might get a little bit upset with us. So oftentimes, I'll add some code in here. So that these variables are always populated, because we di
dn't specify our rink prpc URL, ring P RPC URL is going to be undefined. And that might throw some errors blow. So oftentimes, what we'll do is I'll add an or parameter here, these double pipes mean or, and in JavaScript, if we say some variable equals something or something else, what is really happening is we're gonna say, okay, rink, the RPC URL is going to be equal to process dot E and V dot rink, the RPC URL. But if this rink, the RPC URL doesn't exist, it's going to be whatever else is ove
r here. And I might write something like HTTPS eath Rinkeby. Example, or something like this, just so that I don't make hard hat mad if I don't use rank B. And we can do something like that for all these. So you'll see this syntax, oftentimes in a lot of code setups. Now the last thing that I'm going to show you before going into the TypeScript edition of This is test coverage. And as we progressed to this course, I'm going to show you more and more tools that you can use to make sure that our s
imple storage contract is safe and secure. And we take all the steps we can to prevent any hacks from happening if we deploy in real life. One of those tools is a tool called solidity coverage. And this is also a hardhat plugin that we can use for our code. solidity coverage is a project that goes through all of our tests and sees exactly how many lines of code in our sample store dot Sol are actually covered. And this can be a Good tip off. If we don't cover some line of code, solidity coverage
will say, Hey, you don't have any tests for this line, maybe you should write some tests for it. We can add solidity coverage the same way we've been adding all of our packages. npm install dash, just save Dev, or since we're using yarn, yarn, add dash dash Dev, solidity coverage. And we can then add this to our config, the same way we've been adding everything to our config, go to our config, and we'll write require solidity coverage. And there's some configuration pieces we can add down here
below for this, but we're just going to use the default now we can do is run yarn, RT hat coverage. And this is going to go through our tests and print out a file that looks like this, we'll also get a file called coverage dot JSON, which is basically this chart broken down a little bit more often put my coverage dot JSON in my dot get ignore. And I know we haven't actually seen dot Git ignore, do what it's supposed to do. But we will soon we can see here that about 50% of the code 50% of our st
atements in simple storage dot soul are covered. About two thirds of our functions are and 50% of the lines, It'll even give us exactly what lines aren't tested right now, which we can see exactly 31 and 32 of simple swords, outsole aren't covered, which makes a lot of sense, because 31 to 32 is this Add Person function, which we didn't call and we didn't add to our tests. If you want to take this time to pause and try to make this solidity coverage be 100% across the board, by writing some more
tests, I highly recommend you do so it'll be a great learning exercise. We'll also add the coverage folder. So covered adjacent and the coverage folder, which again, I'll explain what the dot get ignore folder does a little bit later. Now the last thing that we didn't talk about and here was what is this nomic labs hard hat waffle. We talked about Daddy and V heart and ether scan tasks gas reports. So today, what is this? Well, we can actually Google search this and find out exactly what this i
s Hardhead waffle is actually a plugin to work with the waffle testing framework. waffle is one of these frameworks that allow us to do some really advanced testing, we're going to be working with some syntax that looks really similar to this really soon. And we'll be showing you more and more of this waffle tool as we continue. Alright, the next part of this section, I'm actually going to go over the TypeScript edition of this. But for all intents and purposes, you've successfully created your
first Hardhead project, you've done a ton of amazing things. In this lesson, let's do a quick refresher of what we've learned so far, we learned how to spin up our own hard hat projects. And now we can run yarn, hard hat and see a list of the tasks and different things that we can do with hard hat. We learned that hard hat looks for this hard hat.config.js. And this is sort of the entry point for any task that we run that starts with hard hat, we learned we can add our contracts to this contract
s folder. And then we compile it by running yarn, art half compile, we learned that all the compliation goes into the artifacts and then the cache as well. And if we want to clean reset, we can either delete these two files or just run yarn, hard hat clean. So we learned that we can use scripts or tasks to actually deploy, interact and do things with our smart contracts. We also learned that I'm going to be using scripts for the rest of this course. But if you want, you could absolutely use task
s as well. I've asked this question a million times what's the difference? Nobody really seems to know what the main difference is. But I think the main difference is that tasks are for plugins. And scripts are for your local development Mart, that is mind limiter, we learned that we can import a whole bunch of things, including tasks from hard hat in our scripts, and we can work with our async functions to grab our contracts and deploy them, we actually then can programmatically verify them usi
ng hard hat and using hard hat plugins. And then additionally, we can interact with our contracts very similar to how we did it with ethers. We wrote a wonderful verification script. And we also wrote our own task, we wrote our first test for this whole space. And we showed what our tests are going to look like moving forward. And we talked a little bit about their importance. And I really should stress that writing good tests is going to be the difference between a really professional environme
nt and kind of a side project. Whenever I audit smart contracts, or whenever I'm given a project for someone to tell me to take a look at. The first thing I look at is the readme, of course. And the second thing I look at is the tests. And if tests aren't good, I usually tell them, hey, you need to go back to the drawing board, and you need to level up your tests. So tests are really really important, especially for this space, we learned about a couple of more environment variables we can use.
We learned about a couple of tools to see how good our tests are one of them being coverage. We also learn about a gas reporter to see how much it's going to cost us when we actually deploy to a real network. We learned a ton about the hard hat config, and how there are multiple networks that we can add add to our hard heads, we can make our project our EVM code, work with any network out there, we started working with dev dependencies instead of regular dependencies. Now, READMEs are something
that I'm not really going to go over too deeply in here. But READMEs are sort of like the welcome page of your GitHub repository, and really should give you an understanding of what your code does. Being a part of the web through space. And being a part of the blockchain ecosystem is really more than just you coding your stuff by yourself. You want other people to interact and engage with your code and engage with your projects. I haven't showed you how to use GitHub yet. But don't worry, we're
going to but if you look at my heart had simple storage readme. If you scroll down, usually, you really want to have a Getting Started section where you define how to set up all the code and how to set everything up a Quickstart section, and maybe a usage section and some testing section, which teaches people how to actually use and interact with your code. Since we're just learning more of the code part and not so much the readme part. For now, we're not going to go over how to make a fantastic
readme. However, I will leave a link in the GitHub repository associated with this course, link to this best readme template. It really is a fantastic readme template that you can copy to any of your projects to make them look really good and give them a really good setup, so that other developers can come to your project, and learn and participate with what you're coding. But all right, you have learned an absolute ton, you should be incredibly proud of yourself, and incredibly excited that yo
u've made it this far. Now I'm going to jump into the TypeScript section here. So for those of you who are coding along with TypeScript, feel free to follow along. For those of you who are not, you just finished the Basic section on hard hit, but stick around the next to heart out sections are going to be the ones that really fine grain and hone your skills, and give you all the fundamentals for working with these frameworks. So be sure to follow along with the next two sections, we've got a ton
more fantastic content for you, we are just beginning to get deeper into the smart contract ecosystem. So take that lap, get that coffee, and I'll see you soon. Alright, also now let's do this with TypeScript. So I am going to go ahead and just start this from our JavaScript section. However, if in the future, you want to start a new Hardhead project, you can actually start a new project with yarn, hard hat. And then do great and advanced sample project that uses TypeScript, you'll add a ton of
plugins. And you'll wait a while for everything to get uploaded. And you wait, and you wait a little bit for everything to get downloaded. We're not going to do that though, because I'm going to show you how to convert this to JavaScript Anyways, if in future hearted sections, as we're coding along with JavaScript, if you want to code along with TypeScript, you absolutely 100% can. But let's go ahead and show you what the main differences are. Now that advanced TypeScript thing is going to add
a whole bunch of packages that you may or may not want, I will talk about some of them in our next lesson. But there are going to be some that you absolutely do need. Those are going to be at type chain slash ethers, dash v five, at type chain, slash hard hat, at TypeScript, at types, slash Chai, at types, slash node, at types slash moko, TS node, type chain and TypeScript. And I have a link in the GitHub repo associated with this course, I've got this yarn ad that you can just copy paste, if yo
u want to just copy paste that into your project to run it. Oops, and I should have added those as dev dependencies. So we're going to actually just make them dev dependencies real quick, just by deleting these two lines, and adding a comma here. Awesome, that looks much better. And then of course, what we're going to do is we're going to convert all of our JavaScript to TypeScript. So anywhere where we have J S, we're going to put Ts, obviously, if you're coding this from scratch with TypeScrip
t, you would do the.ts From the get go. This includes our hard hat dot config, that's also going to be TypeScript now. And additionally, we're going to add a TS config dot JSON. This is going to be our TypeScript configuration. Typically, for a setup, we're gonna go with something like this. And you can copy this from the GitHub repo associated with this course. It's basically telling TypeScript, what versions of Typescript and what files to include for working with TypeScript. Now let's go ahea
d and start with our deploy dot TypeScript. For usual, instead of using require, we're gonna go ahead and use import, we're gonna do the exact same thing. We're gonna have import ethers run network, from hard hat. And then in our verify function, we're going to add that we're gonna add the types for these arguments. So contract address, is going to be a string. And args is going to be an array of arguments. So we're gonna say it's gonna be any array, because it could be string, it could be numbe
rs, it could be balloons, it could be anything. We're also going to say for IE, it could be any, even though this is technically an error type, we're just going to put any for simplicity. For now. All of our TypeScript scripts are included in our TS config, or any TypeScript files are manually added here, which we have Our entire scripts folder here, which is good. So now we need to add ethers in here. Well, if we look at our hardhead.config.ts, we're using require here still, and we need to swa
p this out for import for Donnie V, you can use dot env slash config for it to grab your dot env file. Now that we've imported everything, go back to our deploy.ts, we can see that that linting has gone away. If you want to be even more explicit, we can go ahead and add import at nomic labs slash hard hat ethers like so. reason we don't need to import it here is because these two packages also work with Hardhead ethers, so they automatically import it. But if you want to be super explicit, you c
an go ahead and add it like so. Now, we're almost good to go. But remember, our Harnett dot config is also importing our tasks. So we're going to need to update our tasks or block number to be TypeScript fide. So of course, instead of const require, we're going to import task from our that slash config. And we're going to be sure to export our task from lock number as the default. So we're going to do export default task like so. And now we should be good to run our scripts. So we can just do ya
rn, art hat, run scripts, employee.ts. We can do network hard hat if we choose. And awesome. Now, it's when we get to the testing, that things get a little bit different here. So let's go ahead and change this required to import. Just to make it happy there. Let's try to run yarn, art head test, we get a whole bunch of errors, and in VS code will actually go ahead and get these errors right from the linter. One of the trickiest things that you run into as a developer in this space is calling fun
ctions on contracts where those functions don't exist, or vice versa. We're not calling functions on contracts that do exist. Right now the typing for our contracts is just type contract, which isn't super helpful, because type contract doesn't necessarily have all the functions that we want it to have. We want our contracts to be of type contract, but we want them to be of the type of our contract, because if they're the type of our contract, they can have all the functions that we want them to
have. So to give our contracts the correct typing here, we actually can use this tool called type chain, which gives our contracts correct typing type chain has a hardened plugin, which allows us to use type chain and TypeScript natively together, type chain slash hard hat was one of these things that we already installed. And to add it to our hard hat, we got to just go to the hard hat config, and add it in import at type chain slash arhat. Now once we import that in to our config, if we run y
arn hardhat, we now get a new task here called type chain, you read the description, it says generate type chain typings for compiled contracts, this will enable all of our contracts to have their own typing. So we can have a simple storage variable of type simple storage contract, which is much better, because we're always going to know exactly what we can do with each contract. To create this, we run yarn, arhat type chain. And this is going to create a new folder called type chain slash types
. With types for all of our contracts, you can even go into our simple storage sub Ts, which is going to have all the different functions and everything to do with our simple storage contract automatically coded into Typescript and JavaScript for us, which is incredibly helpful. And again, no, I haven't shown you what this is yet. But in our dot Git ignore, we usually want to add type chain and type chain dash types into our dot Git ignore so we don't push them up to GitHub. Now back in our test
, we're going to add the exact types of these different objects here. So we're going to import them from that folder that we just created. So we'll do import simple storage, comma, simple storage underscore underscore factory from dot dot slash types, ain slash types, the simple storage factory is going to be simple storage factory and then civil storage of course, is going to be simple storage. So now when do let simple storage factory which is going to be of type, simple storage, underscore un
derscore factory, and then simple storage, which is going to be of type simple storage contract. And if we command clicked into simple storage, once again, we can see all the contract functions that we know and love, are here. In addition, we have all the functions of the actual contract itself. Once we do that, we're pretty much good to go we just need to have a couple of new things here. Get contract factory returns a type ethers dot contract factory. So what we just need to do is we need to w
rap this in a simple storage factory type. So We'll just do a little wrap like this. And we'll say, as simple storage, I'm just going to sort of factory. And that's good to go. Now that we've added all this, we can run yarn, Hardhead test. And boom, our test run is normal, but with TypeScript and with this additional typing that makes our lives substantially substantially better. And that's going to be all you need to know for TypeScript, reusable, all of the branches have an optional TypeScript
branch that you can use to reference to work with TypeScript. We've learned really just the basics of all the different things we can do with hardhat. And these next few lessons Hardhead fun meme and hard hat smart contract lottery are really going to be the basics for all the fundamentals of all the tools that we're going to learn in hardhat. Lesson Eight is going to be our introduction to full stack and working with front end and building full stack applications. Getting all the way through t
his course will give you all the tools to start your web three journey. But if you're looking to just learn just the basics, make sure you absolutely get all the way to Lesson Nine. And if you get all the way through lesson 18, you are going to know all of the cutting edge tools for this space. And you're going to have the knowledge to become easily one of the best developers in the space. So hope you make it all the way through to the end. Now one of the most important parts of this section of
this lesson is going to be pushing our code up to GitHub, and then sending a tweet celebrating that we pushed our first smart contract our first web three GitHub repository to GitHub. So before moving on to the next lesson, be absolutely sure to get to the end of this and push this code up to GitHub. And then optionally, if you want to celebrate by sending a tweet, but be absolutely sure to get to the GitHub section, because as I've said, many times the web three space is this incredibly collabo
rative community and working with GitHub or GitLab, or any other version control tool is going to be essential for your success in the space. So be sure to get to that part. All right. Now, welcome back to the hard hat Fund Me section of our course. This is the section where we're actually going to upload our first code repository to GitHub if you've never done this before, this is going to be the section where we're going to learn even more about hardhat using a familiar contract base we've alr
eady worked with, which is the fund me contract. And again, if you're using the GitHub repo associated with this course, you can scroll down to the Hardhead Funmi. And all the code is located in our repo. If you'd like to do a quickstart, you can go ahead and get clone it CVU into it, and then run yarn, and then just run yarn hardhat deploy this, I'm going to briefly show you what that looks like. So in your in your VS code, you can do git clone, grab the package, cd into it, and then type code
period. To open it up in a new VS code. Once you're in your folder, you can go ahead and run yarn. To install all the dependencies for working with this project, you plan on working with the test net or working with ether scan or coin market cap, feel free to fill out your Dotty and V with a private key RPC URL, corn market cap key and ether scan key. And then you can just follow along with the readme to use this repo to run yarn, hard hat deploy. And it'll show you deploying some contracts and
some mocks, etc. So let's get to building this ourselves though. Now we're gonna make a new directory for this project, it's gonna be the same setup we've seen before. MK dir, hard hat. And me, FCC, we're gonna cd into heart at Funmi, FCC, and then type code period. And if code period doesn't work for you, you can absolutely open this up by hitting File, Open Folder, like we showed you before. Now, we're in a brand new folder here. And we're gonna go ahead and add hard hat here. And we're gonna
run yarn, add dash dash Dev, hard hat. Now that we have hard hat, in our package, JSON, and in our node modules, we can go ahead and run yarn, start app. And this will say, What do you want to do? I'm going to choose the advanced sample project here, just to show you what's going on. And we're going to set this up in a way that I think works best. So we'll go ahead and do the advanced sample project. Yes, we're going to have that as the root. Yes, we want to add a Git ignore. And there are a lot
of sample project dependencies that it wants us to add. We're gonna go ahead and hit yes. But we're going to end up not using all of these and I'll show you which ones we're not going to use and why. But for now, let's go ahead and hit yes. All right, awesome. And now we have an advanced project in here. Let me walk you through the additional things that are in here. So we have a traditional contract node modules, which is going to be the same scripts is going to be the same test is going to be
the same. But this comes with a dot E and V dot example already packed in for us. It also comes with.es lint files.es lint, RC dot j s.es. Lint, ignore es Lint is known as a JavaScript linter, which helps you find and automatically fix problems in your code for the JavaScript that I work with. I'm not a big fan of ES lint, so I typically don't use it. So I'm going to go ahead and delete the two of these. If you want to keep them in you absolutely can dot Git ignore. We're going to finally under
stand what this file does in this lesson that NPM ignore helps Ignore files if you want to push your project up to be an NPM package, which we're not going to do. So if you want to delete this, you can as well pretty or ignore it and pretty DRC. We already know what these do small hint. And so hint ignore, which we're going to talk about it in a minute, or Hardhead config, which just comes already with a ropsten network, a gas reporter and ether scan package dot JSON with all the additional pack
ages, the readme is a little bit more robust. And then of course, our yarn dot lock. So this advanced project looks pretty similar to what we're going to be working with anyways. Now I do want to talk about this soul hint, though. So what is solvent solvent is known as a solidity linter that we can use to lint our code linting is the process of running a program that will analyze code for potential errors. It also does a little bit of formatting, oftentimes, es Lint is a way to lint for JavaScri
pt code. So hint is a way to lint for solidity code, we use prettier to format our code, and we can use soul hint to lint, our code, they are often used a little bit interchangeably, even though that's not exactly correct, as they are a little bit different. We can run this linter on our code by running yarn, sole hint, and then type the name of the files that we want to lint. So we do contracts, slash and then you can just do start out so everything looks okay, nothing will happen. Well, let's
say we have a variable that we don't explicitly say the visibility of it is. This isn't the best practice because ideally, we always say exactly what the visibility of some variable is. This obviously gets defaulted. But it's usually better to be more explicit. So now if we run yarn, so hint, contracts start up so it'll give us a warning, saying we should explicitly Mark visibility of state, this linter is a good way to check for some best practices for running our code. So we're definitely goin
g to keep a small hint around. Now that we've got a repo here, let's add a couple of our common setup pieces here. So in prettier.rc, we're going to swap this out with what we've been using so far. Tab of the form us tab is false, semi false, single quote, also false. We're going to update our prettier dot ignore node modules, package dot JSON image artifacts, cache coverage ID v dot star, readme, and coverage and anything else you want to add in here. And we're going to scroll up to our contrac
ts folder. And we're going to swap this greeter dot soul out with our fund me dot soul. Now let's go ahead and add our contracts in here. If you're following along with the repo, you go to the contracts folder, there's actually another folder in here and the contracts look a little bit different. So if you have those contracts, steal from remix, let's actually grab them from remix because we're going to make a couple of changes to them. If you don't have remix up anymore, which you probably shou
ldn't, because you should be taking breaks, you can jump back over to Lesson four remix Funmi jump into the repo here and grab the contracts from inside here. Just go to the fun v dash Free Code Camp tutorial and grab the code from there. So we're gonna grab just fun me and price converter dot soul. So go ahead and delete that old file, create a new one and call it fund me dot song. Paste it in there. And then we're going to create the price converter. That's all. Now we have both our Funmi and
our price converter contracts in here. Now one of the first things that we want to do one of the first things that we did last time was we ran yarn compile to make sure that our code is actually working the way we want to. And before we actually hit Compile, one of the things that we're going to need to do is come to our Hardhead dot config, we're going to make sure we're on the correct solidity version. So we're going to do zero point 8.8 here. And let's go ahead and try to compile. So we can r
un yarn Hardhead compile. And you'll see we actually get an error here. Library at chain link slash contracts imported from contracts slash fund me dot soul is not installed, try installing it using npm. In remix, we went ahead and just imported at chainlink slash contracts, right from our NPM and or GitHub. But in our local code, we have to tell Hardhead specifically, where to get this from, we want to download this specifically from the NPM package manager at chainlink slash contracts, we can
download it simply by running yarn, add dash dash dev at chainlink slash contracts. Now that we've downloaded it into our file, we'll be able to see it in Node modules here. Hardhead is now smart enough to know that at chain link slash contracts is going to point to that node module that we have. So we can now run yarn Hardhead compile boom, now we can see compiled three solidity files successfully. So now we have our contracts in here and our code is compiling successfully. We're probably going
Want to deploy our code? Now in our last section, I know we use the scripts module. And we made our own manual deploy script. However, something that you'd notice, the more that you work with just raw ethers, or even just hard hat is that keeping track of all our deployments can get a little bit tricky. If you just use a deploy script, it's not saving our deployments to any file. Additionally, having everything in the deploy script for deploying can make the tests and the deploy scripts, maybe
not work exactly hand in hand. And there are a couple of other things that might be a little bit tricky to work on, we're actually going to work with a package that makes everything I just mentioned, and a couple other things way easier. And this package that I'm talking about is going to be the hard hat deploy package. There's a link to this package in the GitHub repository associated with this course. It's a hardhat plugin for replicable deployments and easy testing. And if we scroll down to i
nstallation, we can see we install it basically the normal way. They're using npm. And we're gonna go ahead and use yarn. So for us to add it, we'll do yarn, add hardhat dash deploy. And then of course, we're gonna do dash dash Dev. Once done deploying this require statement to our hard hat.config.js. Once again, basically the config is our entry point. This is where we're gonna get started. And we can go ahead and delete our deploy.js script. Now if we run yarn hardhat, you see that we have a b
unch of new tasks in here, with one of them being this deploy task, this deploy task is going to be the main task that we use to deploy our contracts. Instead of writing our deploy scripts in the Scripts folder, we're actually going to create a new folder, we can create a new folder by just doing MK dir deploy. Or you can always right click and hit New Folder. This deploy folder is going to be where a lot of hard hat Deploy Module looks to deploy code. And it's going to be where we are writing o
ur scripts. To write our scripts, we usually need to add one more thing in here. Since we're going to be using ethers JS in all of our scripts, we want to add Hardhead deploy ethers to our package here. Now, instead of just doing yarn, add dash dev hard at deploy ethers, we're going to do something a little bit weird. We're going to do yarn add or npm install dash dash Dev, and we're going to install it like this. So let me just copy this. And you can just copy that from the repo. And we'll do y
arn, add dash dash Dev, and paste that in here. What we're doing is we're taking at nomic labs, hard hat ethers, which we've used before, and we're overriding it with hard hat deploy ethers. Remember how in our last project, we used hard hat ethers. So that hard hat could override ethers to use hard hat deploy. We use hard hat deploy ethers, so that hard hat deploy can override Hardhead, which overrides ethers, which is kind of funny. When you say like that, this will enable ethers to keep track
of and remember all the different deployments that we actually make in our contract. So if we look at our package, JSON, and now we can see our nomic labs dashboard had ethers. Now the version of it is going to be MPM. Hardhead deploy ethers. This is our package dot JSON, basically saying the hard hat ethers package is now overwritten by the hard hat deploy ethers package, which is what we want. Alright, great. So now that we have that setup, we can start writing our deploy scripts, the way tha
t Hart had to play works is all the scripts that get added to our deploy folder will get run when we run yarn, hard hat deploy. So a good practice is usually to number them so that they run in the order that you want them to run in. So since we only have one contract that we want to deploy the Funmi contract, we're going to do 01 Deploy Funmi Jas, and in this script, this is going to be where we define how to deploy the fundament contract. Alright, so we're in our deploy Funmi scripts. Now tradi
tionally, what did we do, we did imports, we did the main function. And then we did calling of main function, that Hardhead deploy is a little bit different, we're still going to import our libraries and packages, but we're not going to have main function. And we're also not going to call the main function when we run Hardhead deploy Harnett deploy is actually going to call a function that we specify. In this script here. What we're going to do is we're gonna create a function, we'll call it dep
loy funk. We're going to export this deploy function as the default function for Hardhead deploy to look for, so we could say, module that exports dot default equals deploy funk. To test it out, we can go ahead and do console dot log, hi. And then in our terminal, run yarn, hard hat, deploy. Oops, get rid of the parentheses here. Sorry. Run it again. And we can see it went and ran our deploy func here. Now if this syntax is easier for you to understand, go ahead and use this syntax and we're goi
ng to be passing the heart at runtime environment as a parameter to this function. However, if we go to the heart hat deploy documentation, and we scroll down to an example script, the syntax looks a little bit different. And let me just explain what's going on here and how we're going to be writing ours. So instead of kind of defining everything like this, and defining the function name, similar to what we were doing before, we're actually going to using a nameless, a synchronous function, we'r
e going to make it an anonymous function, similar to what we've seen before. So instead, we're going to say async parameters like this, I'm going to pass our parameters our heart at runtime environment in here. And it's going to be an arrow function. And then we're going to wrap this whole thing in module dot exports. So we're gonna say, module, dot exports, equals this async function like this. This syntax here is nearly identical to what's up here, we just don't have a name for our async funct
ion. So this is how we're going to set it up instead. But if this syntax is a little bit confusing for you feel free to use this above as the two of these are going to be the same. Now the next thing that most of the documentation does is it pulls out the variables and functions out of the HRV that we're going to use. HRV is the heart hat runtime environment. Whenever we run a deploy script, heart hat deploy automatically calls this function and just passes the hard hat object into it similar to
in back in hard hat simple storage. In our deploy script. We had ethers run in network come from hard hat, instead of coming from hard hat. We're coming from HRV, which is basically the same thing as hard hat. For our script, we're only going to use two variables from a jury when you use const. Get named accounts. And deployments. This syntax might look a little bit weird for you. But it's just a way to pull these exact variables out of a tree. It's kind of the same thing as just doing a tree d
ot get named accounts and HRA dot deployments. But pulling them out like this means we don't have to add a tree at the beginning anymore. And then additionally, additionally, JavaScript has something called syntactic sugar. So instead of doing this on two lines like this, we can actually do that whole bit on one line. So instead, we just extrapolate those two variables, right in the function declaration. So this line is the exact same thing as doing this line. This is an asynchronous, nameless f
unction using the arrow notation, or working with our deploy scripts here. And we're default, exporting it with module dot exports. I don't know that was a lot. And another is kind of a lot of syntactic sugar here. But if that's really confusing for you, just feel free to use the above. And whenever we refer to get named accounts, you can also just do a three dot get named accounts, or a three dot deployments. So hopefully, that's clear that this top part is gonna be the same as this bottom part
right here, whichever one you feel more comfortable working with. But alright, now that we've gotten all that out of the way, let's continue with the script. So we're using this deployments object, reason this deployments object to get two functions, those two functions are going to be the deploy function, and the log function. So we're gonna say const, deploy log equals deployments. So we're going to pull these two functions out of deployments. And then we're also going to do const Deployer. E
quals await, get named accounts. So we are grabbing this new deploy function, this new log function, and we're grabbing this deployer account from this weird get named accounts function. What's this get named accounts function, this get named accounts is a way for us to get named accounts. When working with ethers we saw when working with ethers, we can actually get our accounts based off of the number in the Account section of each network. So for example, in this list of private keys, private
keys zero private key one private key two, it might get a little confusing to remember which ones which so instead of working like that, we can add a section at the bottom called named accounts where we can name each one of those spots in the accounts array. So we'll do named accounts. And we'll say one of the accounts that will name is going to be named Deployer. And we're gonna say by default, the zero with account is going to be Deployer. We can also specify which number is going to be the de
ployer account across different chains. For example, on Rigby we wanted the deployer account to be the first position, we could do something like this or on hard hat, we could do it like this. We can create multiple users. Like for example, if we wanted to do a user for some test or something, and we'll just say the default is one or whatever we wanted in here. So back in our deploy fun me We're going to say we're going to grab that deployer account from our named accounts. And then finally, we'
re going to grab our chain ID for reasons that will come clear pretty soon. So we'll do const, chain ID equals network dot config dot chain ID. Now, how do we actually deploy this fund me contract? Well, let's think about this for a little bit. When working with remix, it was pretty easy, right? We just deployed it to a test net. Ah, that's kind of the issue there, isn't it deploying to a rink, the test net is a little bit slow. We don't always want to have to deploy to one of these slow test ne
ts or even a main net when tinkering and fiddling with our contracts, do we know that's gonna be really bad, we really want to deploy to a test net as a last stop after we've done all our testing locally. Or we can deploy it to a test that to see some very specific code work, like for example, with the chain link documentation. So ideally, we deploy this to a local network first. But can we just do that? Well, if we look in our price converter, dot Seoul, we have this hard coded address in here,
this 0x address, if we go to Doc's dot chain that link EVM chains, contract addresses for Aetherium data feeds. That address is the eth USD, specifically for Rinkeby. What if we work on the Hard Hat Network? Example? default network? Hard Hat. And then like I said before, if you don't write this in part, it is automatically the default network. But if we're to point to the Hard Hat Network, harder network is a blank blockchain. And it gets destroyed every time our scripts finish, or even if we'
re working with a local node, this price feed contract won't exist, one of the code there won't be updated with data. So what do we do? How do we test and interact with our code locally? Is there a way we can do this? Well, one of the ways that we can do this that we'll learn a little bit later is actually forking a blockchain, where you can keep stuff hard coded. But usually, it's still better to figure out how to do everything with something called mocks. There's a great Stack Overflow questio
n that just says, What is mocking and mocking is primarily used for unit testing, which we'll talk about in a little bit. And object under test may have dependencies on other complex objects. To isolate the behavior of the object, you want to replace other objects by mocks that simulate the behavior of the real objects. In short, mocking is creating objects that simulate behavior of real objects. Now, this might seem like a lot of words. But basically, what we want to do is we want to make a fak
e price feed contract that we can use and we can control when working locally. So back here, I'm just going to leave a note in here saying, When going for local host or Hard Hat Network, we want to use a mock. Okay, great, well, we can use a mock and we'll learn how to make one of those in a little bit. Well, what happens when we want to change chains, for example, back in dots dot chain to link EVM chains, contract addresses, there are a ton of different block chains that have price feeds on th
em. And on each one of these blockchains, the eth USD price feed is going to be a little bit different. For example, we're looking at ETH USD, the address of eth USD for Aetherium main net is different from the address of eth USD for Rigby, which makes sense, they're totally different contracts on different chains, they have very similar functionality. And they do nearly the exact same thing. But they're still different. We're also going to need a way for us to modularize or parameterize, this a
ddress in here, so that no matter what chain we deploy to, we don't have to change any of our code, we can always have our code be exactly the same. And we don't have to come in here and like flip values and flip variables and stuff. So let's keep that all of that in mind as we write the rest of this. Now in order to parameterize. This, we actually want to prioritize and do a little refactoring of our fundamental soul. Refactoring basically means going back and, and changing the way your code wo
rks. Right now we have this constructor function, right the constructor function is the function that automatically gets called whenever we deploy our contract. Right now it's not doing a whole lot right now it's just updating the owner variable to be whoever sent in the contract. But we can actually have a do much more than that. Since this constructor is a function just like every other function, we can actually have it take parameters, one of the parameters that we might like for it to have i
s going to be the address of a price feed. So let's go ahead and add this and figure out how to refactor all this code. So we're going to add constructor address, price feed for the constructor in here. When we deploy our contract. Now we're going to pass it the eth USD price feed address depending on what chain we're on. If we're on rink B, we'll use this address if one polygon will use a different one b&b, different one, Gnosis hecho, avalanche, etc, you get the picture. So we're going to marg
inalize this like so. Now that our constructor takes a parameter for the price feed, we can actually save an aggregator v3 interface object as a global variable in our price converter, we just create a price feed variable of type aggregator v3 interface, which again, we're importing from the chainlink repo, which is an interface object which gets compiled down to the ABI. If you match an ABI with up with an address, you get a contract that you can interact with. So we're going to do the same thi
ng here. We're gonna say, aggregate Tor, v3 interface, public price feed, ration and call this price feed address so that these don't have the same name. And in our constructor, we're going to say price feed equals, and we're going to do the exact same thing we did with our price converter equals aggregate tore the three interface of price feed address. Like so now, we have this price feed address that's variable and modularized, depending on whatever chain that we're on. Now, what we can do is
we can grab this price feed address, and we can use it for our price converter. So where are we using our price converter? Well, just a quick reminder, we're using using price converter for you at 256. We're using this as a library on top of our unit 256 type. So we're calling message dot value dot get conversion rate. So we look at our price converter, we have this function get conversion rate, which takes an FML as its initial parameter, which again, since this is a library, it automatically p
asses the message dot value into this get conversion rate function. But we could also pass in this price feed, and therefore we wouldn't need to hard code it in the get price anymore. So let's go ahead and figure out how to do that. Well, what we can do is we can do message dot value dot get conversion rate, we'll stick price feed in here. And then we'll have to update our get conversion rate to do a comma so that it takes a second parameter, because remember, again, the initial parameter is goi
ng to be message dot value. And the second parameter is going to be what we define here. So we'll do s amount, comma ag reg gate Tor v3 interface. And we'll call this price feed. And now, when we call our get price function, we can pass the price feed to the get price function. And up here we can have get price. Take, you guessed it an aggregate or the three interface called price feed. And now we no longer need to hard code in the price feed. And we can just delete those lines and have it compi
le like this, which is awesome. So quick refresher, we're parameterizing that price feed address and passing it in with a constructor that gets saved as a global variable to an aggregator v3 interface type, or passing it to a get conversion rate function, which passes it to the get price function, which then just calls latest round data. And we probably could have made this even easier, probably could have just got rid of the get price function and stuck this code in the get conversion rate. But
we'll leave it there for now. Now that we've done that refactoring, let's make sure it works. Yarn Hardhead, compile, invalid value undefined for hardhat dot config dot networks. Let's go to the let's go to the config real quick. That's because the default network needs to be outside of networks. My mistake. Let's try that again. I spelled interface wrong and the price converter. And a quick note, if gives you an error like this, oftentimes, you can command click or control click and open that
file up right in the editor, which saves you some time, we're going to have defined the line and find the file. But yeah, let's spell that correctly. And let's try this again. And awesome. It looks like it's compiling correctly. And we just have some warnings, it looks like these warnings are just about this git version, which is because we're shadowing this, we're creating a new price variable down here, you've no we just created a global price free variable. Let's just go ahead and delete the
get version function altogether since we're not even going to really need it. And we only use the Git version to show you how to actually start working with interfaces. And then we'll compile it one more time for good measure. Boom compiled successfully. Awesome. So now we've just refactored our code. So we can pass a price feed address depending on the network that we're on. Okay, great. With all that being said, let's come back to our deploy Funmi script, and let's learn how to actually deploy
the rest of it. In order for us to deploy a contract we remember from our last sections that we use the contract factories, with heart hit Deploy, we can just use this deploy function. And to use the deploy function, we'll say const Funmi, which is going to be the name of our contract, equals await. And we'll call this deploy function, the name of the contract that we're deploying right now, and then a list of overrides that we want to add here. So we're gonna say who is actually deploying this
by saying from, we're gonna say it's from the Deployer. We're gonna pass any arguments to the constructor In this args piece here, which we just added a single Argh. So these brackets, we're going to make it a list of arguments, we're going to put the price feed address in here, which we'll show you how to do in a second, put price feed address. And then we're also going to do some custom logging here so that we don't have to do all that console dot log stuff that we've been doing this whole ti
me. And we need to put something in here. We need to put an address in here. And you can use this backslash star to put like a common in between your code. We can't just do const address equals, you know the address and stick it in here. Well, I mean, we could but we're not really prioritizing now. Right? We're kind of back to just hard coding it here. So what can we do instead? Well, what we can do is we can actually use the chain ID to do something like if chain ID is x, use address, Y, or if
chain ID is Z use address A. So we can do something that looks like this. And to enable this functionality, we actually take a page out of the Ave GitHub. So Ave is another protocol that's on multiple chains and has to deploy their code to multiple chains and work with multiple different addresses. So what they do is they use a number of different useful tricks. But one of the main ones is using this helper hardhat config. Now they're using TypeScript with JavaScript, but it's gonna be the same
thing. With this config, they have different variables, depending on what network that they're actually on. And depending on the network that they're on, they use different variables. So they use this network config almost to do exactly what we're trying to do here. So what we want to do is we're going to create a new file at the root directory, so just click down here, new file. And we're going to call it helper, hard hat config dot j, s. And this is where we're going to define that network con
fig. And this is where we're going to say, hey, if you're on network, a, use this address network, be this use this address, etc. So we're going to create an object called const. Network config. equals and we're going to add a bunch of stuff in here. So our main network that we're working with right now is rinky. dinky has a chain ID of four. So we'll say chain ID four is going to be named Rinkeby. And the eth USD price feed address is going to be the price feed address of rank B of the eth USD
price feed. So we're going to copied from the documentation or from the GitHub, whatever you want to do, and paste it in here. Now we have a simple methodology of keeping track of different price feeds a different contract addresses across different chains. Let's say for example, we wanted to deploy to Polygon as well. Well, first, what are we going to need? Well, we're going to need the chain ID of polygon. So a quick little Google Search brings us to the polygon documentation. And we see the c
hain ID is 137. So I'll do 137. What's a little brackets here, we'll say name, polygon. Then we'll do a comma eth USD, price feed. And then we'll add the price feed of eth USD on polygon. So docstoc, chain link, polygon or Matic and then we'll look up eth, USD. And boom, we see it right here. We've grabbed this address, and we paste it in. Well, what about the Hardhead? Network? We'll get to that in just a second, don't you worry. And then at the bottom, we need to export this network config. So
our other scripts can actually work with it. So we'll do module dot exports equals network config. And we're going to actually export a couple of things from this file, which is why we're doing it like this instead of that default way that I showed you before. So back in our script, now, what can we do? Well, first, we want to go ahead and import that network config. So we'll say const. Network config equals require, and then we'll import it, we'll go down and directory to help our Hardhead con
fig and save. And I just want to mention this one more time, just so that it doesn't confuse anybody. This syntax here, constant network config with the little curly braces around it is the same is if I went const. Helper config equals this thing, which helper config is now kind of this whole file. And then const network config equals Hopper config dot network config. So again, this index is just kind of an easy way to extrapolate or pull out just the network config from this file. So that's how
that works. And that's why we export it at the bottom so that we can do this, please use the GitHub repository to ask questions and discussions especially about some of this JavaScript stuff. Alright, great. So now that we have this network configured here, we can now do this part of where we say if China d z use a if chain ID is x use y. So Since our helper config is nicely in this kind of dictionary, key value pair style, what we can do is we can say const. eth USD. Price feed address equals
network config at the chain ID, because if Francina D, or it'll be this object, French entity polygon, it'll be this object at the eth USD price feed, we're going to save this to eth USD price feed address. And now no matter what chain we're on, whenever we run hard hat deploy, if I run yarn, hard hat deploy dash dash network Rinkeby. This chain ID is going to be four. And so it's going to use this price feed address. If I do dash test network polygon, and I remember to add both ring P and polyg
on to my networks, like here, the channel is going to be 137. It's going to use this price feed address. So this is awesome. This is exactly what we want. But is it everything that we want? Those of you who have been questioning while I have been coding and talking, you might be thinking, Okay, well, you talked about this marking thing. You talked about localhost and hard hat. And how do we test this locally? Like this is how we go to a test net and a main net. But what about a local network? An
d that is exactly what we're going to talk about now. So we've modularized, our code and parameterize our code so that we're going to use the address based off of the chain that we're on. But what if we use a chain that doesn't even have a price feed address on it? What do we do there? This is where we actually create those mock contracts. The idea of mock contracts here is if the contract doesn't exist, we deploy a minimal version of it for our local testing, or our local testing. And deploying
mocks is technically a deploy script. So what we do actually is back in our deploy folder is we're going to create a new file, and we're going to call it 00 Dash deploy mocks dot j s, we started with 00. Because this is almost like the pre deploy stuff, we only do this, sometimes we don't always deploy mocks, right, we don't need to deploy mocks to Rinkeby, or polygon or or Aetherium main net, because those already have these price feeds, we're actually going to deploy our own mock price feed c
ontracts. And in our deploy Funmi script, we're going to use our own contracts, instead of already established contracts. If we're on a network that doesn't have any price, few contracts, like hard hat or locos, for example. So let's write our deploy mock script. So the setup of this is going to look nearly identical to our deploy Funmi. And again, if you want to set it up like this, you absolutely can. But I'm actually just going to copy this, this part, paste it in here, because that initial p
art is going to be exactly the same. Oh, and over here, I just realized that we're calling this network thing without being defined, JavaScript will kind of be smart enough to know where this network thing is coming from. But it can be a little bit confusing. So it's better to be really explicit, and say, const. Network equals require hard hat, this network thing is coming from hard hat. And we're going to grab this line. And we're also going to use this at the top of our script here. And then o
ur top section is going to look exactly the same as well, we're going to grab these three lines, and paste them in deploy deployer chain ID, boom, it's all going to be the same here, because we're setting up to deploy some stuff. Now we want to deploy a new contract. But if we look at our contracts folder, this is all we have right now. So we're going to need to add this mock this fake contract to our contracts folder. Now what we can do is in our contracts folder, we want to separate this file
from the rest of our file so that we know okay, this isn't part of our project, but it is part of our testing. So we're going to right click Create New Folder. And we can either call it mocks, or test I like to call mine test. And inside of this folder, we can go ahead and right click create a new file, I'm going to create a new file and call it mock, v3 aggregate tore that soul. And this is where we're going to define our mock price feed aggregator ourselves. So how can we create our own fake p
rice feed contract, so we can test everything locally? Well, one thing we could do is we go to the chain link GitHub repo, and go through the contracts and find one of these price feed addresses, source eight, or maybe we'll go back to source we'll maybe we'll check in V six. Looks like we could find some stuff and look around and we probably copy paste all this code, but it really seems like kind of a huge pain in the butt to have to copy all this code. Now we absolutely could we copy paste the
code in here, but we're gonna do something a little bit more clever. So the chainlink repo actually comes with some mocks. If we go to contracts, SRC V 0.6 tests They actually have a mock v3 aggregator dot soul in here that we can use as our mock. So we can copy paste everything, but we'd have to revamp a little bit of it because it's doing some dot dot stuff. It's talking to other contracts that are locally in this file structure that are not going to be in our file structure. So instead thoug
h, what we can do is we can use this node modules package to our advantage, we can just say pragma, solidity, carrot zero, point 6.0, we'll use the same version that that package is doing. And then just do import at a chain link slash contracts slash SRC slash v 0.6. Slash tests slash mock, B, three egg, Reg, gay tore that soul. And then we'll add, and then of course, we'll add spdx, license identifier, MIT. And boom, this is actually all we need. If we just import the code like this, remember,
this is exactly the same as copy pasting this contract into our project, of course, with this path resolve to where it actually is in our node modules. Now, actually, I can run yarn hardhat compile, and it will also compile this contract. Except for of course, we have an issue, hey, compiler versions don't match. Right? What's What's up with that now, you're going to get into situations where you will be working with contracts that are not the same version of solidity as you why well because con
tracts keep being deployed all the time. And there are a ton of contracts that are in version 0.4, solidity, 0.5 0.678, and probably 910, or 15 billion, or however many solidity versions will come to be. So in our config, in our hard hat dot config, when you scroll to the bottom, we can scroll to where we're defining our solidity version. And we can actually add multiple solidity versions, so that our compiler can compile multiple versions of solidity. To do that, we'll say, so Lyd, did T. And w
e'll turn it into an object here, we'll make sure to put this comma here. And inside our solidity object, we'll put compilers and we'll have a list of compilers. Our first one we'll say is version, zero, point 8.8. And we'll say our second one is going to be version 0.6, point six, and then we'll go ahead and save that. And it looks like mine wanted to format it like this, which is fine. Now, we can go ahead, rerun, yarn, Hardhead, compile, and boom, compiled five solidity files successfully. Th
is means that our Mark V aggregator should also have been compiled. And if we look in artifacts, at chain link, do indeed see this at chain link slash contract slash SRC bid, and a v 0.6. In tests, we see this mock aggregator dot soul, which has been compiled. Awesome. So now that we have our mock contract compiled, we now have a contract that we can use to deploy a fake price feed to a blockchain. So how do we actually do this? Well, it's going to be the exact same way that we deployed the Funm
i contract. But we're going to add a little if statement in here, we don't want to deploy this mock contract to a test net or a network that actually has a price feed on it, we could just do something like if chain ID does not equal, you know, some chain ID, then deploy marks, right. And then this is kind of pseudocode. Obviously, this code won't actually work. But instead, what I like is I actually like to specify which chains are going to be my development chains, which chains are going to be
the one that I can deploy these mocks to, in my helper, hard hat config, I'll define these chains. So I'll say const, development chains, equals, and then I'll just say hard hat, and local host. I'll export these. And back in my deploy mocks, I'll import these with const. Development chains equals require dot dot slash helper Hardhead config. And now I'll say if development chains dot includes chain ID. This includes keyword basically is a function that checks to see if some variable is inside a
n array, then we're gonna go ahead and deploy Max, and which is what we want to do. So we'll do log, which we're getting from deployments, which is basically console dot log. And we'll say local network detected, deploying mocks. And we'll do a weight ploy, and we'll deploy our new mock v3 aggregator mock v3 aggregator will do a comma. There a little colons here. If we want to get really specific, we can say contract v3 aggregator which we're kind of already saying we'll say from deployer We'll
say logging is going to be true. And then we need to pass some arguments, we need to pass the constructor parameters for the mock v3 aggregator, which are what? Well, let's go to docs chain to link to find out. Or you can also just go to Node modules chainlink, SRC V 06, tests, and then all the way down to mock V three, aggregated out. So where you could also find the constructor in here, whatever one you like better, sometimes I find it easier just to read GitHub Ctrl plus F or Command plus F f
or constructor. We see it takes a decimals and an initial answer. And if we read through the code, we'll learn that the decimals object is going to be equivalent to the decimals parameter is going to be equivalent to this decimals function and the initial answer. And the initial answer is basically just going to be what is the price feed starting at, we actually get to pick the price of the price feed, which works out really well, because that works out great for testing. I usually like to defin
e the decimals and the initial answers somewhere outside of this function so that I can access it later. One good place you can add it is once again in our helper Hardhead config.js. So I might do const decimals equals eight. And then const initial answer. Answer equals, and we'll do 2000. So since we have a decimals, we'll do 2000 And then 123456788 decimal places, and then we'll export these as well. Export decimals, and export initial answer. We could of course, just do you know, const decima
ls equals eight at the top and then initial answer and then use them down here. But I like to do it like that. So Conce. So now we have to import them in here. const development chains. It's also grabbed decimals. It's also grabbed initial answer, we'll save it. We'll take a look back at the constructor looks like it's decimals first, initial answers second. So in our arguments, we'll do decimals first, initial answers second, and tada. And then we will be all done that we'll do a quick log box
deployed. And then I also like to do kind of like a big line at the end of all of my deploy scripts just to be like, hey, that's the end of this deploy script. Anything else after this is going to be a different deploy script. All right, great. Now our deployed mocks script is actually done. But our deploy Funmi script isn't quite done. Is there a way that we could run only our deploy mock script? Well, yes, there is. Great, thanks for asking. What we can do at the bottom of our deploy mock scri
pt is we can add a module that exports dot tags, equals, and we'll say all and marks. Now what we can do is if we run yarn, hard hat deploy, we can add this flag dash dash tags. And it will only run the deploy scripts that have a special tag. So we'll run our mocks tag, which means it'll only run our deploy mock script. And, and oops, actually, in our helper config development chains is actually hard hat and localhost. And I said, we're going to try to do with the chain ID, sorry, we're going to
do this, we're gonna do development chains dot includes network dot name. Because our helper config is using names and not chain IDs, so if development chains that includes that network the names, then we're gonna go ahead and deploy the mocks. So let's go ahead and run this yarn here and hit Deploy dash dash tags, mocks. And perfect we do indeed see our mocks getting deployed here. This log true means that it's going to spit out stuff like this. It'll say contract, it's deploying, it'll say th
e transaction it's doing and it'll say where it was deployed with how much gas and awesome This means our deployed Mach script is working perfectly. So now we have our deploy mocks script working perfectly. So how do we apply that back to our deploy Funmi script? Well, we're gonna do the exact same thing here. Instead of making eth USD price feed address constant variable, we're gonna say let at USD price you'd variable so that we can actually update it. And we'll say, if development chains dot
includes network dot name, what we can do with hard hat deploy is we can just get the most recent deployment using a command called literally get. So we'll say const. eth USD aggregator equals await deployments dot get. And then the name of the contract that we deployed Mach v3 aggregator, and if you wanted to just do get instead of deployments dot get, we absolutely could, just by doing it like this. Those are exactly the same. So we'll get the address like this and then we'll say eth USD price
feed address equals that eth USD aggregator contract dot address. And then if we're not on a development chain, if we didn't deploy a mock, we're just going to do exactly what we did before. With using the network config. Oh, my goodness. Now, now that we've done all of these steps, let's add a little log thing at the bottom here with just a bunch of hyphens. Now, we should have a very robust script to flip between a local development chain, a test net chain, a main net chain, and allow us to d
eploy literally everywhere without changing any of our solidity. And then we just take this, this eth USD price feed address and stick it into logs here. And then at the bottom, we can do module dot exports, dot tags equals and then we'll just do all and then we'll call this one Funmi. Oh, now moment of truth. If we did all this, right, we should just be able to run yarn, hard hat deploy. And it should work on our local chain, our hard hat chain. And then it should also work on any test net that
we give it. So let's give this a try. Yarn, Hardhead deploy. Let's see if this works. Awesome. And we got this all to deploy locally to our Hard Hat Network, we can see that we went ahead and we deployed mocks, we did our little underline here. And then we deployed Funmi deployed at this address with this much gas. Now, what are the other awesome things about hard hat deploy? When we run our local blockchain, our own blockchain node, hard hat deploy will automatically run through all of our dep
loy scripts and add them to our node. So now if I run yarn, hard hat node, we're going to spin up a new blockchain node, but it's already going to have all of our deployed contracts on it. So every time we spin up a local node, now it's going to come automatically packed with the contracts that we want on it. So we are going to show us doing this on a test net on Rinkeby. But before we actually test it on Rinkeby, I'm going to add a little bit of the auto verification piece in here as well, beca
use we did that in the last lesson. And we wanted to show how to do it in hard hat deploy as well. So right after we deploy our Funmi, we can do something similar here, we'll say, if developer chains includes network dot name, we'll say if developer chains doesn't include network dot name, because we don't want to verify on a local network. So we'll say if not development chains dot includes network dot name, the exclamation mark, aka the bang means not when we're talking about booleans. So we'r
e saying, if the name of the network isn't a development chain, we want to go ahead and verify and same as last time. And if process dot e NV dot ether scan API key, then we're going to go ahead and verify. Now before we had our verify code, right in our deploy code, we're gonna do something a little bit different here. Instead of having our verify code in our deploy scripts here, we're actually going to create a new folder called utils, which stands for utilities. And this is where we're going
to add different scripts that we can use across different deployments. Because let's say we have 50 Deploy scripts, we're not going to make 50 Deploy functions, we're just going to add them to our utils folder, and in our utils folder, or create a new file called verify dot j s, we're going to add that code from our last project in here. So if you want, you can go ahead copy paste from our last project over to this one, or you can pause the video to type it out yourself. Since we're using the ru
n command here, we're gonna do const run equals require RT hat. And then at the bottom, we're going to do module exports. Exports equals verify. Now that we have a verify script in our utils folder, back in our deploy Funmi we're going to say const. Verify equals require dot dot slash utils. Slash verify. And since now in our verified Jas, we have a lot of this trycatch stuff in here, we can just do a wait. Verify and a verify once again takes a contract address and a list of arguments. We'll sa
y await verify, fund me dot address and then the list of arguments. To make the list of arguments easier to put in. You can go const args, equals and then we'll just stick our eth USD price feed in here and then replace this with args and then take this args and pop it on down into the second parameter here. All right, great. Now let's go ahead and deploy this to With the Rinkeby test net, and what do we need to deploy this to the Rinkeby test net? Well, let's jump into our hard hat config first
. And let's clean this up, we don't really need this accounts task, so I'm just going to delete it, I don't really need this comment. So I'm going to delete this too. And let's jump into the network section, we're not going to be working with ropsten. So we're gonna go ahead and dump that. We are however, going to be working with rink B, the URL is going to be that same Rinkeby RPC URL. So we're going to define that up here, like we did before. And if you want to copy paste from your last projec
t, feel free to do so you can also follow along with me or fastforward me the counts is going to be the same. I'm going to go ahead and just copy paste the gas reporter with what we had from before. So we're going to add this constant corn market cap API key equals process dot EMV dot corn market cap API key. Do the same thing with the ether scan API key Licious add everything in here. Now. We have our ether scan section in here already, we're gonna have our gas reporter be false, because I don'
t really feel like using it right now. And then finally, we're going to add one more thing in here. Remember how in our last project, before we actually verified we waited some block confirmations. That way ether scan could make sure to catch up. Well, we can do the exact same thing in here in our hard hat dot config, we can add a section for each test net for how many blocks we want to wait, I'm going to add block confirmations of six. Now back on our deploy Funmi. In a new section, I can add w
ait confirmations of network dot config. That block on for motions, or one is or one means if no block confirmations is given in our Hardhead dot config will just wait for one block. And again, the reason we want to wait for approximately six block confirmations is we want to give ether scan a chance to index our transaction. And I added a chain ID 42 when it should be for my mistake. And of course, we're going to need our dot env file, where we add all of our stuff from the last session, the RI
P ERP CRL private key ether scan API and then coin market cap API. All right moment of truth. Let's try this out. If we run yarn Hardhead deploy dash dash network Rinkeby. It should not deploy any marks because we have this if statement in our mock deployment. But it should deploy our Funmi contract using the correct price feed address. And then it'll go ahead and verify it. Since we're waiting for six block confirmations, we can even be super secure by adding dash dash tags and just running the
funding tag. But we're just going to do yarn hearted deploy network Rigby. And let's see what happens. All right, and we're deploying funding. And we can see the transaction that we have for fun me, this is that logging feature, we have log is true for deploying Funmi. So it gives us the transaction once it has a transaction, and it will give us the address once we have the address. So we're going to wait six block confirmations for this transaction to finish going through. Now we see we've dep
loyed this contract address with X amount of gas. And now we're running the verification process. While the verification process is running, we can pull up Rinkeby ether scan, paste our address in here and see that we have indeed created this contract. And now it looks like we've successfully verified the contract on ether scan. So if we hit refresh, we can indeed see that the contract has been verified. Awesome. All right. So this is fantastic. Our deploy script is looking great, we're able to
deploy to a local chain, we're able to deploy to a test that and if we wanted to, we could deploy to any network that we wanted simply by updating our hard hat config, and then updating our helper config. This is fantastic. Great work so far. Now we're about to jump in and level up our tests. But before we do that, we're going to clean up our Funmi contract a little bit to make it look a little bit more professional. And I'm going to talk about some of the syntax and some of the reasons why some
conventions exist. We're not going to do this full force on all the projects moving forward. But they are good to know and they are good to keep in mind when moving forward and working with our contracts. While we go through this we're going to learn why some of these conventions exist including learning a little bit of low level solidity. So don't skip this part. When we get to later sections. We're going to be a little bit looser and not be as strict with the code style guides but That's basi
cally what we're gonna go over now. And for now, you might see this event funded thing here, please just ignore that for now, in an earlier take, I'd introduced the events much earlier. And now we're actually going to learn about events a little bit later in the course. So please ignore that event funded for now. So let's go ahead and tweak a little bit of our contracts here. Now what I'm talking about tweaking this to make it look professional, a little bit more professional, I'm talking about
the solidity style guide, there are some conventions for naming and ordering that we can follow to make our code look a little bit better. Now, like I said, this is going to be a little bit more optional, because it can be a little bit verbose. And it doesn't really make that big of a difference. But it can increase readability of your contracts by a lot and make your code look a lot nicer. So if you want, you can go through this style guide to learn more about what kind of makes solidity look n
ice, and what makes it not look nice. But well, that's some of these style guides in here, we're not going to follow the style guide exactly to a tee. But we are going to make some best efforts to make our code follow the style guide, we've got a link to the style guide in the GitHub repository for this section, we can read some more about the layout. But the main thing we want to look at is this order of the layout, we want to start with our imports with our pragma statement, our imports, inter
faces, libraries, and then contracts. And then inside each contract type declarations, state variables, events, modifiers, and functions. So let's go back here and make sure that we're up to speed, we want our pragma first. Alright, awesome, we did exactly that, then we want our imports. Okay, awesome, we have those too. Something that's not in the style guide is going to be error codes, which we definitely want next. So next is going to be error codes. Now this is where we're going to bump into
one of our first updates here. As of recent, it's sort of becoming a best practice to add the name of your contract, some underscores, and then the name of your error. Whenever you're running into an error. This makes it a lot easier to understand which contract is throwing the error. So for this, we're going to say error Funmi, two underscores not owner, then we're going to scroll down to the our revert and set it like this. This way, when if we ever run into this error, we know that the error
is coming from the Funmi contract, not from the aggregator v3 interface, or the price converter or some other contract. So that's how we want to write our error codes here. If we had any interfaces or libraries not imported, we would add them here. But then finally, we add our contracts. In this file, we only have one contract here. It's our Funmi contract. Awesome. Now the next thing we want to learn about as far as style guides go is this thing called natspec. natspec stands for Etherium natu
ral language specification format. And it's basically a way of documenting our code inspired by Doxygen uses Doxygen style comments and tags to help document our code, you can click the link here in the solidity documentation to learn more about Doxygen. If we scroll down in the documentation, here, we can see an example of using natspec. Whenever we have a contract or a function that needs documentation, we can add some syntax that looks like this to it. So for example, if we wanted to add this
to our code, we could add a comment explaining this funding contract to start a piece of natspec, you can do three backslashes, or one backslash, two stars, and then another ending star here. Everything we put inside of this comment section basically gets turned into a comment. For the start of our contract, we'll do the Add sign title to explain basically, what this contract is, it's fun, we contract is going to be a contract for crowdfunding, we'll add another star. And we can add the author
of it, which is going to be your name, I'm going to put Patrick Collins, of course, then we'll add a notice, which is just kind of a note to people we can say this contract is is to demo a sample funding contract. And we can also add apt Dev, which is a note specifically to developers. And we can say this implements price feeds as our library. The reason that we want to add these tags here is actually because we can use the natspec to automatically create documentation for us if we download so w
e can actually run solc dash s user doc dash dash dev doc, and the name of our file to automatically generate documentation. So this is also really helpful for automatically creating documentation for other developers who interact with the protocol later on. You can use this natspec For as many or as few functions as you'd like. Most of us probably aren't going to be making documentation. So we really just want to follow those guidelines if we think some function or some section of our code is a
little bit tricky for other developers. Now that we're inside of contract, we can follow the order of our contract. We're first going to start with type declarations which we don't really have any except for the fact that we're using our price converter for the UN 256 type. Okay, great. You Next, after our type declarations, we're going to do state variables. And in this state variables section, this is where we're actually going to change the name of some of our state variables. So we'll do a
little common here state variables. Now in the solidity style guide, kind of adhere to the naming styles, we use upper and lowercase, we use total caps with underscores here. However, these naming variables are going to change in the future in this section. And if you're following along with the GitHub repo associated with this course, these are going to be actually a little bit different than what you see. However, for now, we're going to leave them as they are, because the reason why we're goi
ng to change them isn't going to be quite clear yet. Don't worry. So these names are going to change soon, but not yet. Alright, after state variables comes events, and modifiers. We don't have any events, but we do have a modifier. So we'll copy this. And actually, we'll delete this comment here. And we'll paste our modifier here. Oh, and it looks like looks like we're not auto formatting here. So we're going to uncomment immutable actually, so that it automatically auto formats. Okay, great. W
e're out of formatting now. And Cool. Alright, so now we have our modifiers. Next, we have right here, and then we have all of our functions. Great. We actually want to group our functions in this order that I just print here. So we want the constructor which we have received and fall back, we do have fall back and receive. So we're going to actually copy those and delete this comment. We're gonna stick those veterans Heath here looks like receive goes first. So we'll put that here. Then externa
l functions, then public, internal, private. So we have public public. And that's it. And then we can delete this part down here. Okay. Cool. And if we want, we can do that syntax up here from the net spec for our functions. For example, for fund it, we could even just copy paste, we would remove title, we would remove author, and we just say add, notice, this function, funds this contract. And we can even leave a little dev thing here to talk about it. Now if we have parameters, you can do apt
puram. And say like what the parameter is. And then if we have returns, we can say returns, or returns and then what it returns for the documentation. Since this doesn't have any parameters in here, and doesn't return anything, we can just leave it like this. And great, we've just revamped our contract here to make it a little bit more nicely formatted. Great job. Now, like I said, we actually are going to change the names of our state variables, and we're going to add some functions in here and
a little bit. So if we're following with the GitHub repo, the state of the contract right now is going to look a little bit different. But it'll make sense why change this up in a little bit. Alright, so now that we've cleaned this up, we've got to deploy marks, deploy Funmi. Let's go ahead and start writing some tests. And after we write these tests, we're actually going to run that gas estimator and using that gas estimator, we're gonna go back, and we're going to update this contract one mor
e time to make this even cheaper to use and work with. And remember, that's going to be one of the advantages of writing these tests is how we can optimize our contracts to be even faster, more gas efficient, etc, we want to make sure that we write really good tests, and this is going to be one of our first jumps into these more professional test setups. So we're going to jump into our test folder, we're going to delete this sample test.js. In our last section, we went over a really minimalistic
test, which is great. However, when we get bigger and bigger projects, we're going to want to start testing more and more different things, we're going to get more and more into at least two different types of testing. So if we cd into our test folder, we're going to make one directory called staging. And then we're going to make another directory called unit. And now if we look in our test folder, we now have a staging folder, and a unit test folder. Now we're going to talk about two different
types of tests. The first one is going to be something called a unit test. Now what is a unit test? Unit testing is a software testing method by which individual units of source code are tested. Basically, what we want to do is in our contracts, we want to test minimal portions of our code to make sure that they work correctly. Then once our small pieces of the test work, we want to do a staging test or maybe an integration test. This might be where we run our code on a test net or some actual
network. You can think of a staging test, it's kind of the last stop before you deploy to a main net. They're not always 100% necessary, but they can be really, really helpful. Remember, we do want to be conscientious of how much we use our test nets, but we absolutely would 100% want to make sure that everything works locally and that we unit test and we run all of our code locally. Then we can use staging tests on an actual test net to make sure that our code will work with actual other contra
cts. Now unit tests can be done with local Hard Hat Network or a forked Hard Hat Network, we'll talk about this for tar Hat Network very soon, right, now, let's build these unit tests, these unit tests are going to be basically what we saw in our last section. So let's go in and let's jump in and write some of these unit tests. So let's create a new test, we'll call it on me dot test dot j, s. And we'll start making our tests in here. Now, we did test previously in our last section, but our test
s here are going to look a little bit differently, we're actually going to use hardhat deploy, to automatically set up our tests as if both of these deployed functions had been run. So let's go ahead and get this started. So we're still going to do that same setup that we're gonna do describe, we're gonna say fund me. And this is going to have that async function like so. And in here, we're going to have a before each, and we're going to have some hits and some describes and everything. Now sinc
e we want to unit test this, we're gonna go a little bit heavier on the test here, and then with our last project, but in the future, we'll go a little bit lighter with some of the tests. So let's get started. If we run yarn Hardhead test right now, we're gonna get zero passing. Now, if we run yarn hardhat coverage, we're gonna get something that looks like this, saying, Hey, you're missing a lot of stuff. So let's try to cover some more lines with our tests. And one way we can do that is actual
ly we can group our tests based off of different functions. So let's have our first set of tests be around our constructor. To do that inside of our first describe, we can add another describe, have this describe the just the constructor, this larger scope will be for the entire Funmi contract. And everything inside this one will just be for the constructor. So this will also be an async function. And these tasks will be just for the constructor. But before we even work on this describe, we prob
ably want to deploy our Funmi contract. So let's learn how to do that. So we'll do a before each, which will be an async function. And we're going to deploy our Funmi contract using hard hat deploy. Since we use hard hat deploy, our Funmi contract will come even with our mocks and everything. So above the before each, let's do let me HDMI. And then here, we're going to deploy Funmi, where we're going to deploy our Funmi contract is first by pulling in our deployments object from Harnett deploy.
So we'll do const deployments equals require hardhat. And this deployments object has, has a function called fixture with fixture does is it allows us to basically run our entire deploy folder with as many tags as we want. You'll notice I added this alt tag in both of our scripts. This means that in this deployment stuff fixtures, it's gonna be a wait deployment of fixtures. If I run away deployments dot fixture, I'll run through our deploy scripts on our local network and deploy all of the cont
racts that we can use them in our scripts and in our testing, and we can deploy everything in that deploy folder with just this one line. isn't that helpful. Now, once all of our contracts have been deployed, we can start getting them will say fund me equals await ethers, and we'll pull an ether some hard hat as well. dot and this is where hard hat deploy is helpful. Again, hard to deploy rapt ether is with a function called Get contract, this get contract function is going to get the most recen
t deployment of whatever contract we tell it. So we'll say get contract of fun to me. So this will give us the most recent Lee deployed Funmi contract in just this one line. And now Funmi will be equal to this line here. Now we're going to make a bunch of transactions on our Funmi. To test it. Of course, we can also tell ethers which account we want connected to fund me. So I can say const deployer equals goes away get named accounts, exactly like we did in our deploy scripts. And then we just n
eed to import it from our tap in our deploy scripts we imported get named accounts inside of our input parameters for our deploy function. Remember getting named accounts and deployments was abstracted from if we look up here, from the hard hat runtime environment, and like I said, the hard hat runtime environment is basically the same thing as hard hat. So we can just go ahead and import it like this, actually like this. Because we actually need to abstract just the deployer from getting named
accounts. And now what we can do is we can connect our Deployer to our Fund Me account. So whenever we call a function with fund me, it'll automatically be from that the player account, which is great. Another way you can get different accounts directly from your heart had config. Is you could take const accounts equals await ethers dot get signers, ethers dot get signers is going to return whatever is in this account section of your network. If you're on your default network hard hat, it's goin
g to give you a list of 10 fake accounts that we can work with you then of course, can do something like const. Account one equals accounts. More correctly would be account zero equals account zero and work like that. We'll leave that comment that out, just in case you need a reference to it in the future. Okay, great. So now we have our Funmi contract. Let's go ahead and write some tests for testing the constructor. And we're probably going to want to use this deployer object down here. So we'l
l do let deployer above. And we'll do something a little finicky here. But we'll say deployer equals Wait, get named accounts, dot Deployer. And we'll just wrap this up so that we can just grab this deployer object and assign it to declare like so. Now in here, we'll create our first test, we'll say it will say it sets the Agra Gator addresses correctly. Comma will have this be an async function. And we'll say const response equals await fund me dot, let's get this price feed here, fund me dot p
rice feed. And then we'll want to make sure this price feed is going to be the same as our Mk V three aggregator since we're going to be running these tests locally. So we should get our mark three V three aggregator up top. Let's do let mock v3 aggregate store. And we'll grab this address the same way mockbee Three aggregator equals await ethers dot get contract mockbee Three aggregator comma, we'll connect this one to the deployer as well. So we'll want to say cert dot equals cert dot equal re
sponse comma lock v3 aggregator dot address. And of course we'll want to say const. Assert equals require gy. Import that from DJI. Okay, cool. Now, let's go ahead and try this out. Yarn hardhat. Test. Oops, I spelled response wrong. Let's try that again. Awesome. So this means that we are indeed assigning the price feed address correctly to the Mach v3 aggregator. Okay, great. Awesome. I think for now, that's all we really want to do for our constructor. Now these two are kind of a nice to have
, I showed them more just to kind of demo what they look like, we're going to skip writing tests for them for now. And we're actually going to go ahead and delete them directly from the contract. If you want to go ahead and write some tests for them and leave them in your examples for your learnings. You absolutely can pause the video and write some tests for it if you choose so, but we're going to skip them. Next though, we are going to move on to fund and running some tests for fun here. So le
t's go ahead and write describe fund. This will be an async function. And in here, we're going to do a number of tests. So if we're going to go line by line here, what's the first thing that we should look at? Well, we should look at this require line we should write a test to see if this contract actually does fail? If not enough, eath is sent. So let's go ahead and we'll say it fails, if you don't send enough eath have this be an async function? Now, how do we test to see if something fails? R
ight now we've done assert equals, but if something fails, we might run into an issue. So for example, if I run await fund me dot fund, but I don't pass any value to this transaction. Let's see what happens. I run yarn Hardhead test. Well, our test is actually going to break VM exception. While processing transaction reverted with reason string, you need to spend more eath. So our tests are going to break which is good. We want this to break. But we want to tell our test that this is okay. Right
? Want to tell that this is okay. So the way we can do this, and this is where our waffle testing comes into play. With waffle and with testing, what we can actually do is we can use the expect keyword and expect transactions to be reverted and for transactions to fail. So instead of using assert here, we're actually going to run a wait expect fund me dot fun 2.2 dot B, that reverted and we've actually even be more specific here by saying to be reverted with and then the exact reverted error, yo
u need to spend more eath. Now if we run our tests, oops expect is not defined. So we need to import that from Chai. Which chai is being overwritten by waffle, we see that it does indeed Pass, which is perfect. So now we have a way to both assert things and expect things to fail. Awesome, even with the specific failure codes. Perfect. Let's write some more tests here. Well, we probably want it to correctly update this data structure. So we could say, it updates the amount funded data structure,
it's going to be an async function. In here, we're going to need to call fund v dot fund. However, we're going to need to actually pass some value with this transaction. And for now, we'll just hard code the value that we're going to send, say const. Send value is going to be 112345 678-910-1234 5678, which is going to be one eath. Another way we can write this though, is we can use the ethers utility to make this a little bit easier to read. Because all those zeros are kind of confusing, and it
's hard to tell at first glance what this actually is. So we're gonna actually use ethers dot utils dot parse ether, one, this parse ethers utility converts this one into that one with 18 zeros, which makes life a lot easier. If you go to the ethers documentation, there's also a parts units function where you can actually convert any unit, either ethers or Gwei. Or really whatever you want to do, you could convert any number to any other Aetherium you type. So this is the set value that we're go
ing to use for our fund. And, and this is definitely going to be more than our minimum USD of 50. So after we call this fun function, we'll say const response is going to be equal to a weight, fund me dot address to Mt funded address to Mt funded for the deployer dot address. Because remember, this is a mapping of each address and how much they've actually funded. So if we use the deployer address, it should give us the amount that we actually sent. So now we can run assert dot equal response.to
string, right, because this response is going to be the big number version of how much has been funded by that account. And that should be the same as our send value.to string. Since send value, our one should be the exact same as the amount that we funded, we can run just this one test, or running yarn, art hat, test, dash dash grep. And we'll put this in quotes allow funded for this amount funded line. And it looks like we ran into an issue here, because we don't need to do deployed at addres
s, we can just do deploy here. And great, it looks like we are indeed passing. Now if we even run yarn Hardhead coverage will now see we've got at least a little bit more coverage here. It's still not going to be great. But we have much better coverage. We have some statements, some branches, and at least some functions covered. So this is awesome. Let's keep going. Are we all done testing our fun function? Well, probably not. What else can we do with our fun function? Well, we're also adding fu
nders to a funders array. So let's go ahead and test for that. So it adds funder to array of funders has been an async function. And we'll say await fund mean that fund value is going to be send value. We'll say const response equals await fund me dot calling the funders array at index zero. So this will be funder equals await fund me dot funders zero. And then we'll say assert dot equal funder should be the same as the Deployer. So let's go ahead and run this test. We'll hit up a couple times.
And we'll change the GREP to under to array so that it looks for this line. And perfect. It looks like that one is also passing. Great. So the money's coming through, the minimum amount is coming through and our data structures are being updated. Awesome. Now we could be a little bit more verbose and do even more testing with this fun function. But I think for the most part, we've got the gist, right. So now let's go ahead and move on to the withdrawal function. So we're going to create a new de
scribe or withdraw. This is going to be an async function. And let's see what the withdrawal function does. Only the owner of the contract is going to be able to get the balance, get the money back. And we're also going to reset all of the amounts that each one of these users is done. So let's go ahead and do some withdrawing. Now in order for us to test withdraw, we probably first want the contract to actually have some money and so what we can do actually is we can add another before each in t
he describe to automatically fund the contract before we run any tests. So we can say before each async function. We can say await, fund me dot fund. Value, send value. Now for all of our tests in this withdrawal scope, we're first going to fund it with eath. Let's say it can withdraw, withdraw eath. From a single founder, this would be an async function. And this is going to be a little bit longer test. So I'm going to set it up to be an arrange, act and assert test. So arrange act assert is ju
st sort of a way to think about writing tests, you want to arrange the test, then you want to act. And then you want to run the asserts, and you'll see what I mean in just a second. So we're going to arrange this test, we're going to set this test up, we want to actually check that we're correctly withdrawing the ether from a single founder. So first, we're going to get the starting balance of the fundraising contract and the starting balance of the Deployer. So we'll say const. Starting under m
e, balance, equals await, fund me dot provider, dot get balance, fund me dot address. So we're gonna start with the balance of the fund V contract after it's been funded with some eath. And we're also gonna get costs start starting, deploy your balance goes await, fund me dot provider, dot get balance of deployed employer. So we're getting the starting balance of the Funmi, we're getting to the starting balance of the employer so that we can test later on how much these numbers have changed base
d off of what happens when we call the withdrawal function. Now that we've done a little bit of setup, we can actually run this withdrawal function, we can do the act here. So we're gonna say const, trans action response equals await, fund me dot withdraw. And then we can say const, transaction receipt equals await transaction response. That Wait, one, and now we should be able to check to see that the entire fund rebalance has been added to the deployer balance. So now we can say const ending f
und me balance equals a weight on me that provider dot get balance of Unreal dot address. Then we can say const ending deployer balance equals await, fund me dot provider dot get balance of Deployer. And now we can just check to see if the numbers work out here. So we can say assert dot equal ending fund me balance is going to be zero, right, because we just withdrew all of the money. So ending funding balance should be zero. And we'll say assert dot equal starting fund me balance plus starting
deployer balance. So the starting funds the balance plus the starting employer balance should equal the ending employer balance. Since we're grabbing whatever the starting deployer balance started with plus the starting fund to be balanced, because we just withdrew all of the starting fund, we balance that should equal the ending deployer bots. Now a couple of notes here, since starting Funmi balance is calling from the blockchain, it's going to be of type a big number, we want to use big number
dot add actually, instead of the plus sign here, just because it'll it'll make working with our big numbers a little bit easier. So instead of starting Funmi balance, plus we're gonna be starting from the balance dot add. Like that. And that should be good. One other thing about this, though, is that when we called withdraw our Deployer did what our Deployer spent a little bit of gas. So this actually isn't accurate. We actually also need to calculate in the gas cost, so we wouldn't need to do
dot add gas cost. We'd also have to do.to string because big numbers are objects and so identities a little bit weird. So to test to see if they're equal, we'll just make them both strings. Now we don't have gas costs. So let's figure out how to get the gas cost from this transaction. So we can add it to Are any deployer bounce, so we can run this assertion here. So what we can do is we can actually find the gas costs from our transaction receipt. And I'm going to show you a couple of phenomenal
tricks you can use with VS code. And if using a different editor, then don't worry too much about this. What we can do in VS code actually is create something called breakpoints. unverified breakpoint file is modified to please restart the bug session, or let's put it right here, put it right in this line after transaction receipt is created. But before ending Funmi belts, what this breakpoint does is it stops the script at this line, and allows us to drop into something called a debug console
and see all the variables that are happening. At this time, we want to look at the transaction receipt and see if the total gas cost is in there. This is also incredibly helpful for dropping into tests and dropping into scripts and seeing exactly what's going on that's wrong. So what we can do is we can move down to this run into bug section. And if it's not there, you can hit additional views. And we can click this JavaScript Debug Terminal, which will create a new terminal in our terminal sect
ion. Now, what happens here is if we run yarn, hard hat test, it'll run our testing and everything. But when it hits this breakpoint, it'll stop. Currently, there is no gas cost. So we're just going to delete this for now. So that we compile and we work in everything. But if we run yarn Hardhead test, see, it's gonna say debugger has been attached to start running our tests. And it's going to stop on this line here. And if we look in this variable section on the left hand side, we can actually s
ee a ton of the variables that are in here. And we can read a little bit more about what's going on. And if we go over to our debug console, we can type in things like transaction receipt, and we can see a ton of information about that transaction receipt object, what we're looking for is we're looking to see this transaction receipt, which we could look in the debug console or over here, if there's anything to do with gas in here. And it looks like there is there's a gas used big number. And th
ere's also an effective gas price. So the amount of gas used times the gas price is going to give us all the money that we paid for gas here. So now that we've figured out there's a gas used and effective gas price variables in this transaction receipt, which we could have also found in the documentation here. However, sometimes it's even quicker just to find it out yourself what we can do, we can exit the debugger by clicking this little thing here. Go back to terminal will trash can the JavaSc
ript debugger, we'll remove the breakpoint. And we'll grab those two variables we can pull them right out of that transaction receipt object by typing const. Yes, used comma effective gas price equals transaction receipt. So again, with this curly bracket syntax, we can use this to pull out objects out of another object. And now that we have these two objects, we can create a const gas cost or total gas cost is going to be equal to the gas used times the effective gas price. Which again, since t
hese are both big numbers, we can use a big number function called dot mol to multiply them together. Now that we have this total gas cost, we can come down and we can say the ending deployer balance plus that gas cost to string. Now the two of these should be equivalent. I know there's a lot of math that we're doing in this section and a lot of new things. So I want to just quickly rego over what we just learned. So first off, the font of the contract comes with a provider, we could have also d
one ethers dot provider dot get balance, but we're using fun v dot provider because we're using the provider of the Funmi contract. It doesn't really matter what we use here. We just wanted to use this get balanced function of the provider object which gets us the balance of any contract. We do the same thing with starting deplore balance. The reason that we needed the starting balances is because we wanted to compare it to the ending balances to see if all the money went to the right places, we
then call the withdrawal function. And from the transaction receipt, we grabbed the gas used and the gas price. If you want to debug your JavaScript code, you can add a breakpoint like so go to run into bug, open your debug JavaScript terminal, which is different from your regular bash terminals. And when you run JavaScript commands in here, they will stop where your breakpoints are. Then you can read the different variables and see where different things are. Using that knowledge. We pulled ou
t the gas use and effective gas price from the transaction receipt and used it to get the total gas cost of this transaction, we then got the ending fund, we balanced the ending deployer balance, and used all those variables to make sure all the money went to the right places. And we, we can check this by running yarn Hardhead test dash dash grep withdraw eath in quotes, since there's a space here, and we can see that our test does indeed pass. Great job. If we didn't add the gas cost here, and
we just did.to string, we would see something like this, we would see that the numbers are ever so slightly off, because we're not anticipating we're not calculating the gas here. So we always want to make sure we're using the gas if we're doing calculations like this. Now another incredibly powerful debugging tool that we're not really going to go over here. But it's important to know about because it can be really helpful is that you can actually use console dot log in your solidity with hard
hat. If you're inside of a heart hat project, you just import hard hat slash console dot soul. And then right in your solidity, you can do console dot log, and then type pretty much whatever you want. When you execute these functions, similar to how we do a console dot log in JavaScript, those will actually console dot log out to your terminal. Here's an example of if you run yarn, hard hat test and you have those console dot logs, you'll see stuff like this get printed out. So in addition to th
e Visual Studio Code debugger, importing hard hat slash console dot Sol, and using console dot logs in your solidity can also be an effective debugging strategy. Feel free to give this video a pause, implement this in some of our contracts and try it out in our tests. So we tested that withdrawing eath when there's a single funder works perfectly, let's test withdrawing eath if there are multiple funders, so we'll do it, let's say allows us to withdraw with multiple funders. Why would this be an
async function. And let's do this await Funmi not fun, but with a number of different accounts. So we can create a whole bunch of different accounts of course, by saying const accounts equals await ethers dot get signers. And we can loop through these accounts and have each one of these accounts call the fund function. And we're going to do this with a for loop. So we're going to say for let i equals we'll start with the first index of the accounts because the zero with index is going to be the
Deployer. So we'll say let i equals one is going to be less than let's say six. And we'll do i plus plus. And in here, we'll say const. And me contract Funmi connected contract equals await. And me dot connect two accounts, I, so we need to call this connect function because right now if we scroll up back to the top, our Funmi contract is connected to our Deployer account. And anytime we call a transaction with Funmi, the deployer is the account that is calling that transaction, we need to crea
te new objects to connect to all of these different accounts. So we're gonna say fund me connected contract, which is now connected to one of these different accounts dot fund. And this is where we'll do value, send value. Or excuse me, we'll do await. Great. So this is going to be our our range section. And then same as we did above, we need to grab those starting balances. So we can just copy that, those two lines and paste that down here. Now we're going to move into act, I'm going to call th
at withdrawal function again. So let's say const, transaction action response equals await and MI dot withdraw. And we're going to do the exact same thing as we did above, getting the transaction receipt and the gas costs so we can get everything correct. Once we've done the act, we move on into assert. And we're going to do some very similar things to what we did above, like this, for example, this whole first part is going to be exactly the same. We also want to make sure the funders are reset
properly. So we'll make sure that this funders array is reset properly. So to do that, we can actually just check to see that if looking at the zero with position throws an error so we can run a wait expect fund me dot get on me dot funder on me dot funders of zero. This should revert so we'll say await expect Funmi dot funders dot two dot b dot reverted and then we want to loop through all these accounts and make sure that it makes sure or that in our mapping here, all their amounts are zero.
So we'll say, for I equals one is less than six, i plus plus, we'll say assert dot equal. Wait, fund me dot address to amount funded, of the accounts of I got address should be zero. So we're making sure that all of these mappings are correctly updated to zero. So let's go and test this. So we're withdrawing with multiple founders, we're going to go back to our terminal, we're going to hit up, we're going to change this GREP or this one. We'll see if this passes. And it does indeed, so this mean
s that our withdraw function works really well even when there's multiple funders and we can be happy and go to sleep knowing that. Now the other thing we absolutely want 100% want to test is that our only owner modifier is working, we want only the owner to be able to withdraw the funds from here. So we'll create a new session, we'll say it only allows the owner to withdraw only allows you to withdraw. This will be an async function. And in here, we'll say const. Accounts equals ethers dot get
signers again. And we'll say const attacker equals accounts of one. So we'll say the first account will be some random attacker will connect this attacker to a new contract, we'll say const attacker connected contract equals await on DB dot Connect. Attacker dot address, excuse me a dot connect attacker. Since we're not just connecting the address, we're connecting the account which attacker is an account object. And then we'll do a wait expect attacker connected contract dot withdraw dot two do
t b dot reverted, they should not be able to withdraw. So let's go ahead, we can even just copy this whole thing if we want to hit up, we'll delete this section here. We'll paste that in. And boom. This means that when some other account tries to call withdraw, automatically gets reverted, which is what we want. Now we can be more explicit to make sure that the correct error code is being thrown, not just that it's reverted. Right, it can be very reverted because they sent ether did it they did
something weird, we want to make sure it's reverted with our specific error code. So right now we have this not owner error code. But it's actually a best practice to put the contract name to underscores and then your custom error. This makes it a lot easier in the future when you have a ton of different contracts, and you're not sure where an error is coming from. So we're going to just update this really quickly to be fund me underscore underscore, not owner, now we can do is now that we have
this custom error, we can say withdraw that to be reverted with, then we can add our custom error in here. Now, if we rerun our test, with only allows the owner to withdraw, oops, we need to do a wait here. My mistake, wait a Thursday, get signers. And now let's try this again. And we are indeed passing Perfect. Okay, great. We have some basic unit tests here. And we're going to write some staging tests pretty soon. But before we actually do that, let's go ahead and add the gas estimator. And we
'll see how much gas these contracts in these functions are taking. It looks like the Hardhead gas reporter is already here. So let's scroll down. We'll do gas reporter true. And we won't do coin market cap here. And we'll just look purely at the GUI. So you can just comment it out like that. Now rerun all of our tests. So we'll say yarn, our test. And in doing so we're gonna get that that gas output in that gas report dash text here. So looks like all of our tests are passing, which is perfect.
Now we can look into our gas report and see what's going on here. i Well, it looks like the fundraising function is taking a decent chunk of gas, the withdrawal function, take it some guests to we'd see the min, the max and the average. Of course, we can see how much each one of these contracts cost to actually output. We don't really care about the MOQ aggregator of course, because we're never actually going to use that. Let's say we look at the average gas for these and we go hmm, 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 cheap. If we go back to our funding contract, we look at our withdrawal function. And we noticed 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 gonna look at one of the first gas optimi
zation techniques you can take to drop these down. And it has to do with an R Funmi. 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, if you want to skip over it, you can, because now we're getting into gas optimizations here, this information still is really good to know. So if you want to skip it f
or 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. Okay, 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, they're 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 Son of 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 can always call to see what this contracts favorite number was, well, the way it persists, is it gets stored in this place called storage. A storage box is this giant li
st associated with this contract where every single variable and every single value in the storage section is slotted into a 32 byte long slot in this storage array. So for example, the number 25 in its bytes implementation is 000 with a ton of zeros 19. This is the hex version of the yuan 256. This is why we do so much hex translation, the bytes implementation of a yuan 256. And each store saw increments just like an array starting from zero. So for example, our next global variable or next sto
rage variable just gets slotted at the next slot that's available. So bullions, for example, get transformed from their bull version two, their hex and we modified our some bool variable to be true and X edition of the true Boolean 0x 001. 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? W
ell, 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 two doesn't have the entire array in storage slot two, what has actually is just the array length, the length of the array is sto
red at storage slot two. But for example, if we do my array dot 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 0x 0000 D, so it gets 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 subseque
nt numbers because again, the size of the array can change and you're never going to be sure how many subsequence 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, okay, there is a mapping here, and it needs a storage slot for attaching functional 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 contracts byte code itself, which sounds a little bit weird. But you can imagine what solidity does is anytime it sees constant variables 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 up a storage slot. Well when we have variables inside of a function, those variables only exi
st 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 that we had to say String memory. The reason we need it f
or 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 slowly, just wants to make sure Okay, where are we working with this is it storage is a 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, eve
rything here you can read in the solidity documentation. Now, in the GitHub repo associated with this course, if you go to contracts, we've actually got an example contract section called Fun with storage, where you can play with and look at a lot of this stuff. And we even wrote a little script called deploy storage fun, where it'll print out the storage location of some of the different variables, feel free to give it a run, if you want to try a challenge anybody to write some functions that f
ind the storage slots of the elements of the arrays, and the mappings, and then find the data inside of those as well. We use a function here called Get storage app, which allows us to get the storage at any one of these slots. And this is to reinforce that even if you have a function as private or internal. Anybody can still read it. Anybody can read anything off the blockchain. And you can test it exactly what this if you go ahead and get clone that or copy paste the code yourself. You can the
n run yarn part at deploy dash test tags, storage. And you'll run the deploy script for that storage. And you'll see printing out the location of storage in each storage slot with a fun contract that we made as an example. And you might of course be asking, Okay, Patrick, why are you telling me all this? We're just trying to get this gas price down? Why are you telling me all about this storage thing? Well, the reason I'm telling you all about the storage thing. Anytime you read or you write to
and from storage, you spend a ton of gas. Remember I said when we compile our code, we compile it down to some crazy weird bytecode. Well, let me show you on remix what this looks like. We go to compliation details, we can go to bytecode. And we see this weird hex object zero, blah, blah, blah. But we also see these things called op codes. Now, this bytecode here represents these op codes. Each one of these op codes represents a small piece of everything in this bytecode. And in fact, in our hea
rt hat, we can go to artifacts, build info, and we can see, we can see these op codes in the build info, we can do a command F or Control F for opcodes. We can see op codes for different contracts. These op codes represent what the machine code is doing. And they represent how much computational work it takes to actually run our code and do stuff with our code. The way that gas is actually calculated is by these opcodes. There are a couple of lists here. But here's one that I'm going to use this
EVM opcodes. And again, there's a link to this in the GitHub repo associated with this lesson. Well, if we scroll down, we can see exactly how much it costs for each one of these op codes. So for example, anytime we add, it costs three gas, anytime we multiply, that's five gas, subtracting three gas, we have all of these op codes that cost different amounts of gas in in our functions, here's kind of a sample contract. If we're doing adding, anytime we add it's going to cost three gas. Anytime w
e save to memory, it's going to cost gas from some other opcodes. These op codes combined show us how much gas we actually use. Now, let's look at a lot of these op codes and how much they cost three 510, three, three, balance is 700. So getting the balance is is a ton of gas. Let's keep going. Getting the sides of an Accounts code is a lot of gas copying and accounts code into memory. But oh my goodness, what is this save word to storage costs a ton of gas that is 20,000 gas and s load load wor
d from storage cost 800 gas. These are two of the most important opcodes s load and s store which stands for storage load and storage store. Anytime one of these op codes fires, we're spending 800 or 20,000. You know, there's a big asterisk there because that can change a lot. But we're spending a ton of gas anytime we work with storage as developers. Anytime we work with some stuff in storage, we want to go boy, this is about to cost me a lot of gas and the best convention or making sure we kno
w that we're working with a stored variable and we're about to spend a lot of gas is to append an S underscore right before them which stands for storage right So we're saying address to amount funded is going to be a storage variable wonders is going to be a storage variable. Owner is not going to be a storage variable. It's immutable. The best practice for immutable variables is prefixing. It with an I underscore constant values are also not in storage. So for constant values, we want to keep
them capslock, like that aggregator v3 interface public price feed. Yep, you know what that is going to be a storage variable. So we want to append an S underscore with it. So we're going to do a little bit more refactor, we've appended these appropriately to update everything. So instead of owner, it's going to be I underscore owner, and as a developer will read this, and we'll go ah, this is going to be much cheaper than a regular variable. Okay, that's great. I'm going to work with this. This
I underscore owner for my modifier. Awesome. Is owner anywhere else in here? Okay, right in the constructor. I own underscore owner is message dot sender. Price feed is a storage variable. We should as developers, we should see the s underscore when reading this and go, Okay, we're spending a lot of gas to store this. Perfect. Okay, great. Let's keep going. Great. We've updated all the owners. Okay, well, what about address to amount funded? In VS code? If you do Command F, or Ctrl, F, and you
hit this little down arrow, you can actually find and replace all of these address to amount funded with s underscore address to Mt funded. Hit it like that. And since I updated one, I got a backspace that one no. So now these are all updated. Let's do the same thing with s funders. Let's update everywhere. It has funders just to be s funders. And we probably doubled up here. Yep. Let's undo that. We already updated all the AI owners. So now it's updated all the price feeds. So let's look for pr
ice feed, we'll update it with ES price feed. And then we probably doubled up right here. So we'll undo that. Okay, great. Now that we've updated everything in here, we can scroll down and we can oops, sorry, doubled up there too. Sorry. We can we can green through our code and go okay, where are we reading and writing to storage way more often than we probably need to. And that's when we get to this withdrawal function, which seems rather suspect to reading and writing to storage a lot. So let'
s take a look at what we're doing here. Okay, so first of all, I can see that we're doing a for loop here. And every time we do a for loop, we're just constantly looping through all of this code. Every single time we're doing a little compare option here we're saying, okay, is our funder index less than s funders dot length? S funders dot length, this means the longer our funders array is, the more times we're going to be reading from storage, that's incredibly expensive. We're also recalling th
is, oh my goodness, we're reading from storage a lot and saving it to this memory variable, and then updating our storage variable with it. Wow. So we're reading from storage a ton here, and we're reading from storage a ton here, okay, then we have to reset our funders array, there's really no way around it. And that's pretty much it for our reading and writing to storage, we could probably create a withdrawal function, that's a lot cheaper. So let's go ahead and create a function called cheaper
withdraw, function, cheaper withdraw. That's going to take what we've just learned and make a cheaper withdraw, that's much more gas efficient. So we'll keep this public payable. and have it be only owner, we're not going to change anything there. But what can we do for at least this part here, we don't want to keep reading from storage here. And we don't want to always have to keep reading from storage here. We're like doubling up the amount of storage we're reading from. So instead, what we c
an do, we can read this entire array into memory one time, and then read from memory instead of constantly reading from storage. And that's going to make our lives a lot cheaper. So we can create an address array. Memory funders equals s underscore, funders. And now it's going to start making sense why for arrays and strings in our functions, it makes us say, hey, is this memory is a storage? What is this? And we're telling it, we want it to be memory because memory is going to be a lot cheaper.
So now that we're saving it into our funders, oh, and a quick note mappings can't be in memory. Sorry. They're just too weird and too wacky. So flooding just doesn't let you do that right now. But now that we've saved our storage variable into a memory variable, we can read and write from this memory variable, much, much cheaper, and then update storage when we're all done. So what we're going to do now is we're gonna say for you into V six, fund or index equals zero, and we're going to basical
ly rewrite everything but just using this memory array. instead. We're gonna say funder index is less than funders dot length and instead of s funders dot length, and then we're gonna say funder index plus plus. And then in here we're gonna do nearly exactly the same thing, except we're gonna say address funder equals funders, using our memory array and not s funders have funder index. And then we're gonna say s address to amount funded. funder equals zero. So we're resetting our funders mapping
here, we're using our memory variables instead, then we're going to do the same thing s underscore funders equals new address array of zero. And then we're gonna do the same thing bool success, comma equals S owner, dot call value, address this balance, and we're going to send it nothing and then require success. Like that actually, sorry, Iona on a sonar now that we have this function that we think is cheaper, let's go back to our test. And let's run this same multi test here, but with our che
aper function. So I know this can be a little bit tricky to copy, paste, but let's copy this entire massive test. Let's come down here, paste it, and we'll change the name saying cheaper withdraw, testing dot that done. And in here in in this giant it here, all we're going to change is we're going to change withdraw to cheaper withdraw, and the rest of the test is going to be exactly the same. So with that, let's see if if we were successful in making our withdraw function cheaper with cheaper w
ithdraw, we're gonna pull apart our terminal now. And we do yarn, art hat test, which is going to run our gas estimator because it's enabled right now. And of course, all of our functions have been broken because we renamed everything. So we'll do a quick final replace of funders, to change funders to ask funders. And then we're gonna change price feed to ask price feed. And then do we have owner anywhere? We don't have owner or anywhere. We need to change this one. Address to amount funded. Let
's come in here. Address to amount funded. S adderstone. well funded. What else do we need to change price? We price feed funders. Okay, I think we changed everything. Alright, so let's try our test now. Yarn Hardhead test. All right, great. Everything's passing. And we ran our cheaper withdraw testing. So now, if we go to our gas output here, our gas report, zoom out just a hair, we can see the difference between cheaper withdraw and withdraw, we see something really interesting. Here we see ou
r cheaper withdraw on average was actually more expensive than our regular withdraw. And the reason for this is because actually, if we go to our tests are cheaper withdrawal, we only tested on the multi withdraw. So we had to reset many, many more accounts. But this was also technically its maximum as well. And if we compare the maximum of the cheaper withdrawal, the maximum of the withdraw, it looks like the cheaper withdrawal was indeed cheaper. And if we go to our hard hat dot config, and we
add our API key back in, what we could even do is in our test, we could copy withdraw eath from a single funder, copy that, paste it in and just change withdraw to cheaper withdrawal, rerun it with the key and now do yarn Hardhead test, we can see exactly how many dollars we would save if we ran this on the Matic blockchain. Now let's go back, we'll reopen up our gas report. And we can see, in the minimum cheaper withdrawal was actually a little bit more expensive. This actually does make sense
because if we look at funding, if we only have to withdraw when there was one funder, well this loop only runs one time. And our cheaper withdraw will do the exact same but it will have this this extra thing here of loading them all in, we see that the savings The more people our funders in our contracts. So automatic, we can see we pretty much didn't save anything. But if I change this one more time to eath run the test again. Now we can see people withdraw saved a few cents. This is how we ca
n start optimizing our contracts will be cheaper and cheaper. And this two cents was just in the average. It's not even comparing the max to the max, which was a lot more gas than their averages. We have just learned an absolute ton here. Now, this next part is going to make some of you mad because we're going to refactor our code one more time if you don't want to refactor it and you want to leave all your tests as s underscores you absolutely can but to other users using our application. Deali
ng with this s underscore is a little Little bit gross and actually can make our code a little bit more confusing for those who use it. And additionally, right now all of our state variables are public. And actually internal variables and private variables are also cheaper gas wise. And we don't need to make every single one of our variables public, because anybody can read them off the chain anyways. So one more refactoring that we're going to do is we're actually going to set the visibility of
these to private or internal, based off of whether or not they need to be private or internal, and then we'll create getters at the bottom of our function here. So minimum USD, we can keep this public because we want other people to know what the minimum USD of our contract is, without having to go right through storage, the owner of our contract isn't important for others to know or other contracts to know. So we can go ahead and make this private, and then at the bottom at a function get owne
r. That's a public view that returns I owner, turns address as funders, as funders can be private as well. So at the bottom, we're gonna say function, get funder, and we're going to pass a un 236 index, public U, turns, address, return as funders of index, the address to Mt funded can also be private. So the bottom, we're going to create function, get address to amount funded. And this is going to take an address under the public view returns, you went to 56. And we're going to return amount fun
ded of the funder did this one we did this one, we did this one. And then price feed, function get price feed. This is going to be public view as well, that returns aggregate tour of the three interface that's going to return so I'm just gonna price feed. Oh, okay. The reason why we did that is because we want to have this s underscore so that we as developers can know, okay, this is a storage variable, I want to be very careful about how I interact with this. But we don't want people who intera
ct with our code to have to deal with this s stuff. And we want to give them an API that makes sense, and that it's easy and readable. So we add these getter functions at the bottom to do that. And also changing the visibility can save us some gas in the long run as well, because we're gonna be calling from private variables or internal variables, which are cheaper gas wise, of course, we do need to upgrade our test one more time. And like I said, if you want to just leave them with the S unders
cores, that's absolutely fine. So s underscore price feed is now going to be replaced with get price feed, s underscore amount to fund it is going to be now replaced with get address to amount funded. For now going to change SW, underscore funders, to get funder. We're going to change Iona, there's nowhere else in their mind, we don't need to change them. And I think that was everything. Let's just look for s underscore, we don't see it, I underscore, we don't see that either. Let's just run our
tests one more time to make sure we refactor that correctly. And it looks like we did awesome. Okay, we have just learned a ton. we've refactored our code a ton. And everything is starting to look really, really good here. One more gas optimization we could make. And an optimization for errors as well is we could update all of our requires to instead be to instead be reverts. Because without requires, we're actually storing this massive string, this massive array of text on chain, these error c
odes are much cheaper. But that's optional. If you want to do that. The whole reason we were doing this is we were going through the style guide in updating things here. So we have public internal private, and the bottom is going to be our view slash pure functions, which they are they're just all these getters that we just added. So now our style in here looks good. We've learned a lot about gas, we've learned a lot about storage. This is fantastic. Let's do a quick refresher on everything we j
ust learned because we went through a lot right there. And like I said, this is one of the harder parts of this course. Any variable that is changeable that we want to persist across contract executions and transactions. We save to a giant array called storage this array is sequentially indexed starting at zero. So the first variable the first value that we have in our contract gets stored to the zero with index. The next one gets stored to one and so on and so forth. Dynamic arrays and mappings
and other dynamically sized objects use specific hashing function that you can find in the documentation to determine where the elements of those dynamic Data Structures go memory variables, constant variables and immutable variables don't go in storage. And one of the main reasons talking about storage is so important is because the op codes for loading from storage and for reading from storage and writing to storage are incredibly gas expensive. So in everywhere we can we want to reduce the a
mount that we read and load from storage. And it's one of the easiest ways to save gas and try to optimize our code to be gas efficient. Like I said, some of this gas stuff can be a little tricky and a little bit confusing. So if you don't get this right away, it's okay. It is totally fine. If you're a little bit confused, and you're like, What is he talking about? Like I said, this is some of the more advanced stuff it'll come, the more you work with solidity, and the more you work with everyth
ing here. So don't let it stress you out. Don't let it stop you from continuing. You're doing fantastic being here. So far. We've written some really good unit tests. Let's now write some staging tests. And these are the tests that we can use on an actual test net. This is a test that we're basically going to run after we've deployed some code just to see if everything is working approximately the way we want it to. So let's go ahead and we'll create a new file here. We'll call it fund me. Dot s
taging dot test, dot j s. And it's going to look really similar to what we were just doing with our unit tests. And we're going to assume this is on a test net. So these are tests that we're going to run, right before we deploy this to a main net, this is the last step in your development journey, we want to just make sure that everything is working approximately correctly on an actual test net. So what we're gonna do is we're gonna do the same thing describe, fund me, and I'm gonna go a little
quick through these tests here, because we've basically written this type of test before, so we're gonna say before each, it's gonna be an async. function. We're gonna do the same thing as our unit tests. So we're gonna have a Funmi variable, we're gonna have our let Deployer, we're gonna have our constant send value equals ethers.utils.rs ether of one, and in here, we're going to do const. Get named accounts. Equals require hardhats, we're going to say deployer equals weight, get named accounts
, we're going to wrap this up, dot Deployer. We're gonna say fun me equals await ethers dot get contract. And me, comma, we're going to connect it to our Deployer, we're not going to deploy this, we're not going to do any fixtures like we did in our unit tests, because in our staging tests, we're assuming that it's already deployed here. And we also don't need a mock because on a staging, we're assuming that we're on a test net, now we can actually wrap this whole thing to make sure that we're o
n a test net by using our helper config. And looking for our development chains, we can say we only want to run our describe bit if we're on a development chain. So first, we'll say const. Development chains equals require, we'll pull that that helper config in. And we'll say, development chains dot includes network dot name. And we'll basically will say if developer chains that includes network dot name, we're going to skip and we can actually skip using this, we're going to use something calle
d a ternary operator is basically like a one liner if statement. And you can think of this as a special type of F. I've got a link to this and the GitHub repo associated with this course. And here's some JavaScript documentation, showing it in action. You say, Okay, return is member. And if it's true, have it be $2. Otherwise have a B $10. And that's pretty much it. So another way of thinking about is like, you say, let variable equals true, then we could say, let some var equals variable questi
on. Yes? Or no? Some var will end up being Yes. Because variable is true. If variable was false than some var would be no. So it's literally saying, If variable, if variable, then some var equals yes. Else. Some var equals no, these lines are literally the exact same thing. This one is just a little bit more succinct. That's really it. So that's what this operator does. We're gonna say development chains that includes network dot name. So if our network is a development chain, which we're going
to import network as well from hard hat and ethers as well. Then we're going to do describe that skipped and this tells our test to just skip this whole describe, and then we're going to put this little colon here thing and save and boom. So now we're only going to run this if we're not On a development chain, and we want to take this exact same syntax, we'll go to our unit testing here, and we'll do the exact same thing, we'll paste it will have this be the opposite by putting a little knot her
e, sticking that colon in. So now, our unit tests only run on development chains in our staging tests, only run on test nets. Perfect. That's what we want, allows people to fund and own and withdraw. And this will be an async function, of course, and we probably can make this pretty robust, but we'll just say await, fund me dot fund is going to be send a value. And then we'll say a weight on me dot withdraw. CERT equals require try. Now we'll do kind of a lame final one, we'll say const ending b
alance equals a weight on me dot provider dot get balance, fund me dot address. And then we'll say assert dot equals ending balance.to string, comma zero as a string, we're only going to run this on a test net, I'm just going to give you this one more run to show you it in action. Feel free to skip this part again, because we are going to be working with a test net, I'm going to run yarn, hard hat deploy dash test network Rinkeby. And it's going to run through our deploy. And after it's all depl
oyed, we're going to run our staging tests to make sure that everything works even with a price feed on a real test net, and I need to do const development chains equals require dot dot slash dot dot slash helper heart config. Now for run yarn, hard hat test, we'll see just our unit tests get run. But if we run yarn hard to test dash dash network Rinkeby, we're not going to run nine tests, we're only going to run our singular staging test. And of course, this is going to be a lot slower, because
we're on a test net. Net will we write written all these tests, we can write a couple of scripts. And then we're going to finish this out by pushing this up to GitHub making this our first smart contract GitHub repository, when it comes to the blockchain, when it comes to smart contracts, interacting with community interacting with open source being a part of GitHub, or git labs or whatever Git hosting service you're using is essential to being successful here. So let's write our scripts. And t
hen we'll upload this to GitHub to start building our portfolio. So first, we're going to create a script to interact with our code called fund dot j s. And this is going to be really similar to our tests. And this way, in the future. If we want to just fund one of our contracts very quickly, we can just run this and we can do it, we're gonna do the same thing that we've been doing, we're gonna do an async function main. And down below, I'm just going to copy paste this because we're going to be
copy pasting in a lot. We're going to paste this little syntax here. So let's write a script that allows us to fund our contracts. So first, we're going to need const get named accounts just like in our tests, equals require arhat we're gonna say const Deployer. Equals await yet named accounts, just like that. And then we're gonna say const fund me equals await ethers dot get contract. From funding comm a Deployer. Literally, almost exactly the same as our tests, then we'll do a little console
dot log funding contract that that and we'll do const transaction response equals await funding dot fund. And for the value, we'll do something like ethers dot utils, that parse ether of 0.1 or something, whatever you want to do here, we of course, need to import ethers, which it looks like we already have. We'll do await transaction response dot wait for one transaction. And then we'll do console dot log funded, we can run this little script by running yarn, RT head node will run a local node w
ith all of our contracts deployed. We'll see if our script looks okay by running yarn, hard hat run scripts fund dot j s dash dash network localhost. And it looks like it's funding Great. Let's now write a withdraw script withdraw that J S. And we can even leave our localhost Node running because we're going to withdraw the funds that we've just funded it with. So we're going to do the exact same setup here. We can even copy this main bit to our withdraw Ah, the top will do async function main w
ill say const deployer equals await, get named accounts, which wow, I hit enter and my VS code auto imported it, that's pretty nice. Maybe yours will too, maybe won't if it won't, you just gotta write it out or copy paste from the other one. And then we'll do cars Funmi equals await ethers dot get contract on me, course. And this is going to be the exact same. Now we're going to do console dot log funding data dot, we'll say const transaction response equals await on v dot withdraw, await transa
ction response dot wait one, then console dot log. Got it? Back. And we can test this out by running yarn, hard hit run scripts, withdraw dash dash network localhost, we'll see if this works. And cool and our script is working. Fantastic crushed out two scripts incredibly quickly. And now we have a way to easily interact with our code with our contracts if we want to via a script. There's actually one more thing I want to show you before we actually work and we push all this wonderful code up to
GitHub in our package dot JSON. I've shown you a little bit of this before, but we can add this scripts section to make our lives a lot easier and condense all these long tests into a yarn script for us. So usually, what you'll see in common package dot JSON is you'll see a list of these in here for people to look and just automatically run, one of the most common ones is going to be test. And to run test, we're going to do yarn, hard hat test. So now instead of running yarn, Hardhead test, som
eone can just come to your package once this is saved and just run yarn test. And this will grab this test from your script section and it will run yarn heart at test and Bada bing, bada boom, okay, cool. What else do we probably probably want to do in here? Well, we probably want to have a test staging section that'll run yarn Hardhead test dash dash, network Rinkeby. I'm not going to run that. But that's probably something we want to have in here, we're probably going to want some linting. So
we showed you briefly that linting thing. So we'll have a yarn lint, which will just run yarn, sole hint. And then we'll just have it so hence the contracts folder. And anything that starts out soul. So now if I run yarn, lint, it'll run soul hint, and all of our code here and it'll give us some warnings here, which we can pretty much all ignore. And Solon actually has an auto fix and auto fix that we can add, by doing yarn lint fix, we'll say yarn. So hint, contracts slash start out. So we'll d
o dash dash fix. So now we run yarn, lint fix, it'll auto fix, which there's nothing to auto fix. So nothing happens. But it's good to have anyways. And then we can do our formatter, we're just going to format our code format, that which will do yarn, prettier, dash dash write to, and we'll just do a period to do everything. And then we can just do yarn format. And it's gonna fix all of our, it's going to fix everything for us, which is great. And then we finally can have coverage. By running ya
rn hardhat coverage, now we can just run yarn coverage, will give us this wonderful little coverage report. Awesome. So our packages looking fantastic. Maybe we'll even come into package json. We'll give this a name. We'll call this hard hat. And me give it an author, which is going to be your name. So I'm just gonna say Patrick Collins, and we'll give it a version in here. of 1.0 Point Oh, oops. And let's do icons instead of spaces. Oh, and one more thing. We're not using ES lint. So all this e
s lint stuff, we can dump and we could delete the yarn dot lock and reinstall. But yeah, whatever. We don't have a readme, but that's okay. If you want to go back, like I said, go check out that best readme template and go update your READMEs to make them look as awesome as this, you can do that as well. But other than that, we've got an awesome code repo here. What do we want to do with it? Well, we've been playing around with GitHub so much, we've been looking at all these good hubs. It's time
for us to join GitHub with our own with our first repository. Let's go ahead and let's make this happen in the lesson seven full blockchain solidity course, yes, there is a link to this GitHub Quickstart that we're going to follow to set up our first repository. This is going to be the moment where you are starting to build your portfolio building and GitHub is borderline crucial for your development journey. It's going to be your portal folio, it's going to be where you say, Hey, look at all t
he cool products that I'm engaging with, that I'm working with, that I'm participating in. If you've already made GitHub before, I highly recommend you still push this up to GitHub as proof that you've done it. And then you can also tweet it at me saying, hey, look how far I've gotten. Look where I've done, look at how fantastic I'm learning smart contracts, and be incredibly excited about now, this quickstart will walk you through creating a repository, creating a branch and teaching all this s
tuff, we're going to follow the instructions from the GitHub documentation about adding locally hosted code to GitHub, we already have a project, and we're just pushing it up. Since the Windows users are using WsL, you can just follow the Mac or Linux instructions here, the first thing that we're going to do is in your GitHub profile, or your GitHub login, we're gonna hit this little plus thing, and hit new repository, you can call this whatever you want, let's call it hard hat, fund me b code c
amp, you can put a description if you want, learning from recode camp, and Patrick, about smart contracts. We'll make it public because we want other people to see you being fantastic and learning smart contracts. We'll leave this blank, and we'll hit Create repository. Now, this is our public code repository. This is our first one, if you've done these already, this will be your first smart contract one. It even has some instructions in here, too, that teaches us how to create a new repository
from the command line, you can follow this if you want, or you can follow like so the first thing we're going to do is we're going to initialize a git branch. And from way back when you should already have Git installed. Remember, you can check by running git dash dash version like this. Git is a little different from GitHub, Git is known as version control. And it allows us to make changes to our code, but keep a history of all the code changes that we've made. GitHub is a place where we can pu
sh all of these changes and keep track of all of our code. So the first thing that we're going to do is we're going to create a new branch. And I'm not going to explain Git and working with Git too, too deeply. But if you want to learn about Git Free Code Camp, of course, has a video on Git and GitHub for beginners. So we're going to create this new branch with git init dash b main, now your Visual Studio code might automatically start formatting some stuff. And if it does, that's great. And if
it doesn't, don't worry about it. But what you'll see here on the left is you'll see some stuff is green, and some stuff is gray, open back up that dot Git ignore, you'll see that all the gray stuff is the stuff that we have in this dot Git ignore this is intentional, this is what we want. This is just some some highlighting saying, hey, this green stuff is what you're working with on GitHub. And this gray stuff is what you're not working with and GitHub. And that's what we want. You don't need
to push artifacts, or cash or coverage or node modules, people can install and compile on their own machines, we definitely don't want to push up our Dotty and V if we're using a Dotty and V. And we don't really need to push up coverage dot JSON, either the rest of this we do. So now what's next, after we initialize our main branch, you now should be able to run git status in your terminal and see this huge red output of all these things that are untracked, and we don't have any commits for, wha
t we can do now is we can stage all of our code with git add period, and then commit it with Git commit, we're going to run these one at a time instead of together. Before I run git add, I'm going to add deployments to this list too, because GitHub doesn't really need to know about all the different deployments I make, especially when I make a ton of deployments to my local hosts, they don't need to know. So we're going to add that to, then we're going to run git add dot. And if we do a git stat
us, now, we can see all of our code has been staged for being committed for being a part of this history of our code. And then take a quick look at all these files and make sure your dot E and V file is not and never in here. So now we're going to run git commit dash m and then this message for our commit, okay, so we'll run git commit dash m, we can say, initial commit, or whatever you want in this message here, first commit, initial commit, who cares, and it's gonna say, create mode, blah, bla
h, blah, for all of these files. And if we do git status, now, it's blank on branch main, nothing to commit. And then you might get something like this. If you've never worked with Git before your name and email were added automatically. We're a little bit confused here. We'll talk about this in just a second. So next, what we can do is we're actually going to copy the URL of our GitHub repo. So you can grab that just by copying here or right at the top, that URL right there. And what we're goin
g to do is we're going to add this as a remote repo. To do that. We'll do git remote add, and we'll give this remote repo a name. For us. We'll say origin and then we'll paste that URL there. We're now saying the the origin remote repo is good. Gonna be at this URL, we run git remote dash v, we can see that the origin repo for fetching is at this branch. And the origin repo for pushing is also at this branch. So when we want to get new code, a fetch code will fetch it from here. And if we want t
o push code up, we want to give code to the GitHub. We'll also get it from here. So now we've set the new remote with that remote URL. Now we're going to actually push the changes to github.com. And the way we do that is with Git push, and we pick which remote we want to push to, and we're going to push the origin. And then which branch we want to push to which we're going to push to Maine, it'll probably prompt you for your username and your password, and maybe your email and everything. Now, i
f authentication doesn't work for you, for some reason, you can come over to Settings. Or if you scroll down to developer settings, Personal Access Tokens and create generate new token, some token, give yourself repo access, write access, and hit Generate token. And try to use this token as your password. Instead, be sure to use the GitHub documentation and the GitHub discussion associated with this course, if you get lost or if something doesn't work, as shown here. But once it's done, once you
add all that information in correctly, you come back to your get up and you will have your first GitHub repo with all the code and everything in it like this. And once you complete this step, once you do this, you should absolutely celebrate. If you like, you can shoot a tweet web three community in the blockchain community is absolutely this collaborative space. So Twitter crypto is where a lot of these people congregate to share ideas. So definitely be sure to celebrate and share this and be
really, really excited. And shoot a tweet out like this. Give your friends a high five, share it on Twitter, share it on Discord shared on Reddit, be excited for how far you've gotten, we've got a lot more to go. But by completing this part, you have done fantastically, and I'm so excited for you to start the next section. Now, we're not going to go over the TypeScript addition to this because there's nothing really new here. However, again, if you want to see TypeScript, feel free to jump into
the GitHub repository associated with this course. Alright, awesome. You've just completed Lesson Seven, the heart had fun me. And now it's time to move on to lesson eight, which is going to be our HTML slash JavaScript to fund me, you can find all the code for what we're about to go through, of course, on my GitHub repo. And for this section, we're now going to start to see some of the differences between Node js between that back end JavaScript, and JavaScript in the browser or front end JavaS
cript. And if you come to the GitHub repo associated with this lesson, our main version we'll be using what's considered better front end JavaScript. But we'll also have a no JS addition, as well, if some of the front end JavaScript is really confusing, and you'll see what I mean with some of those differences very soon. Now, people can programmatically interact with our smart contracts at any time. However, most of our users are not compete developers. So we need to create a website, we need to
create a user interface for them to interact with our smart contracts and interact with our protocols. And that's what this section is going to teach us, it's going to be an introduction to building these fullstack. building these front ends on top of our smart contracts. Now, I wanted to show you what this is actually going to look like when we finish it. Because here, we're actually going to make our first front end our first website using the blockchain using web three. And it's going to be
an incredibly minimalistic website. As you can see right here, we're not going to have any styling, we're just going to show you how to get the functionality. And additionally, we're going to do a couple of things that aren't really recommended and are definitely not best practices. The reason we're going to do it like this is the same reason that in math class, before you learn the tricks for derivatives, you learn what a derivative actually is. We're teaching it like this first, so that you ca
n understand what's going on on the websites when you interact with them. And when you work with them. We saw already with Foston, touching the link where we can connect our wallets and we can work with the faucets. All decentralized applications have this website and have this setup where you connect your wallet and then you interact by clicking buttons, which make these function calls to the blockchain. And here's going to be our minimalistic website that does exactly that. So this section is
just going to teach you what's going on under the hood. So you can really understand how to build these applications at a professional level. So for this section, if you don't want to code along with me, you definitely don't have to however, coding along with me will definitely ingrain everything in your memory here. So here's what an application is going to look like. We have our website here, which is connected to our hard hat, our local blockchain, but it's gonna run exactly the same as if it
was on a real test net, the first thing you'll notice is in our meta mask, we are not connected. And we'll go ahead and hit Connect, and meta masks will pop up asking us if we want to connect, we'll go ahead and connect to it. And now we'll be able to interact with our heart at Funmi. You'll notice two buttons here are functions that we're familiar with, we have our withdrawal function, which is going to be our withdrawal function that we just created. And then of course, we also have our fund
function here where we push or we send Aetherium or Matic or whatever, native blockchain token to our smart contract. So we can do it through this user interface. So once we're connected, if we want to see the balance, we can actually right click, hit Inspect, come over to our console. And we'll print out to the JavaScript console, the current balance of our smart contract. So nobody has funded this yet, we can come down, we can choose an amount we want to fund. So for example, maybe 0.1, eath,
we'll go ahead, we'll hit fund, meta masks will pop up, we'll get a little council saying funding with 0.1. And it'll give us all the transaction details that we need to send 0.1 eath, to our smart contract, we can go ahead and hit Confirm. And after it's been confirmed after it's been mined on our local blockchain, we had get balance, we now see that it's 0.1. We could call fund again, we could have multiple funders, we could switch between different accounts and fund with different amounts. An
d we can see that funding amount increase, then we can call the withdrawal function. As long as we're the owner, we can confirm and we can pull out all the money out of our funding contract. And we'll get balance. Now we'll see the balance is reset to zero. So this is what we're going to be building. Are you ready? I sure am. Let's get into it. This is the introduction to building websites with web three. All the information here is available in our GitHub repo, so feel free to follow along ther
e. Alright, so if you're in your heart head Funmi dash Free Code Camp repo, we're still going to want to have this open as well. But we're also going to want to create a new Visual Studio code for working with our new repo. So let's go ahead and CD down a directory. We'll type MK dir, we'll call this HTML, Fund Me Free Code Camp. We'll cd into that. And we'll open this up by typing code period. You can also do File Open Folder, but we just want to open this up in a new Visual Studio Code. New VS
code will pop up but before we flip over to that, we do want to CD down CD back into hard hat fun we Free Code Camp because we are still going to use everything in here. We're still going to deploy In a smart contract using this folder and using this repo, when you're building daps, or websites that are connected to the blockchain, you'll usually have two repositories or repos. One is going to be for the smart contracts, like what we see here. This is our repo that has all the code for our smar
t contracts. And then you'll also have one for the front end slash website. And it's going to be the combination of these two repos, which makes up the full stack. So when people are talking about full stack, they're talking about the smart contracts, which is going to be our back end, plus, plus our HTML slash JavaScript slash website stuff, which is going to be our front end. So smart contracts are the back end, HTML slash JavaScript slash website stuff is going to be our front end. So we have
our back end already. And now we're going to build our front end, we want to keep this up because we're going to need it to test and interact with our front end. Awesome. So we have this new folder now, HTML Funmi, Free Code Camp. Now this course is not a how to learn front end course, we are going to teach you a number of front end concepts. But if you want to learn a full traditional front end course, once again, you can check out Free Code Camp, they've got a ton of fantastic tutorials, I'm
teaching you front end, if you go ahead and follow along with me, though, you'll definitely get a basic understanding of front end as well as front ends and how it relates to our smart contracts. Additionally, you don't have to do the front end parts or the full stack parts. If you only want to take this course, to learn back end and to learn JavaScript, and to learn solidity and learn how to do these smart contracts programmatically, then you can absolutely skip these front end parts. However,
if you want to learn to build exciting websites, and you want to have other people other than developers interact with your protocols, you definitely want to watch this part. Now before we actually jump in here and start writing our code. We need to understand what exactly is going on when work with one of these websites that use the blockchain. So I actually made a video about this recently. So let's watch a segment from that really quick, just so that we can get up to speed with with exactly w
hat's going on behind the scenes of these websites that interact with the blockchain. All right. So here we are, with a website or a front end on top of some smart contracts that we've deployed, doesn't really matter what it is right now. This is typically the interface that you'll see boiled down to a really, really minimalistic level. Typically, you'll see something like connect function, right, and Metamask, or some other wallet connector thing will pop up, we'll hit Next we'll connect here m
ight even say something like connected. And we can also execute functions, we can interact with our smart contracts, we can confirm, etc. Right? This is something you might see something like Avi right, I'll hit Connect on the application, it'll say, hey, how would you like to connect? I'll choose Metamask. I'm going to change my Metamask to main net, but you get the picture, right? This is a simple example of what that would look like. So what is actually going on in the browser when we connect
what is actually going on? And what do we actually need to do, we're going to right click, hit Inspect. And on the right side, we're gonna see our debugger here. Now if we go over to sources, on the top of our browser, you'll see a few things. If you look down over here, right, we'll see this URL, right, which right now is going to be my localhost. And we'll also see meta mask and Phantom and a whole bunch of other stuff. These other things that we see here are going to be what's injected from
our browser extensions. The reason we see this meta mask thing here is because I've meta mask installed, right? The reason I see Phantom here is because I have the Phantom app installed. Meta masks, of course, being an EVM, wallet and Phantom being a Solana based wallet. Now what happens when we have these extensions installed is they automatically get injected into a window object in JavaScript, and in fact, we scroll down to here in the console, again, you can find console, you can click here
and click anything up there. And we type in window. We'll see we have this big window object with all this stuff, right? This window object represents this our window basically right? Now if we scroll all the way to the bottom and we do window dot Aetherium. We also see an object here. Now this window dot Aetherium object only exists if you have a meta mask or meta mask like browser or if you want to look at some other web three wallet you do window dot Solana. So Alana right and we see this win
dow dot Solana. Now let's look at a browser that doesn't have Metamask or phantom installed. What do you think is going to happen in the window now let's go ahead and right click hit Inspect. We'll go to the console. Now let's see what's going on in here. If we go to sources, we first off we don't see that Metamask or that Solana source here. And if we go to console, we still see window if I let me zoom in a little bit. We still see window here. But if I do window dot Aetherium If we get nothing
, or if I do window dot Solana, we also get nothing. So in order for our browsers to know that there's a Metamask, or that there's a phantom, those extensions automatically add these to our window objects, and that's something that we can check for in our JavaScript. The reason these wallets are so important is built into them underneath the hood, they have a blockchain node connected to them. And in order to interact with the blockchain, we always need a note. And you might have seen URLs from
alchemy, or in FIRA because you need them to interact with the blockchain, Alchemy, and infura are examples of third party blockchains that you can interact with and basically rent, right. But you need them to create a provider, or a node to send your transactions to. So you could do it in JavaScript, like something like this is the alchemy documentation where you take that alchemy URL, you stick it into some object and use that to send your transaction. This is a way that you could do it in the
back end. But on the front end, what you normally want to use is you just want to use the user's Metamask, or their Solana or their wallet as the main wallet. Now, there are a ton of other different types of wallets to connect, like ledger, mu, Coinbase, wallet, connect, etc. And there are different ways to set those up. But they all do the same thing where they expose some URL, they expose some node under the hood, they give us that URL. They give us that provider. The way metamath Does it is
with window dot Aetherium. Boom, this is now our URL. This is now our connection. In fact, if you go up to your Metamask, hit the little three dots, expand view. hit Add Network, and then just hit the X so we can get to networks. You can see all of these blockchains that I have in here all have an RPC URL, this the HTTP RPC URL connection of the blockchain No, that's running. I happen to have one running locally right now. All of these also have a node RPC URL and you can actually see them right
in your meta mask right. This is connected to in Fira, these are all connected to in Fira. It's all the exact same thing. Meta mask just has a really nice way of taking that URL, sticking it in the browser for us in this window dot Aetherium or window dot Solana you know or whatever. So this is the main thing that we need to know we need. We always need a connection with the blockchain. And these browser wallets are an easy way to do that. Make sense? Great. Let's take this knowledge now. And l
et's apply it. So in here, let's make a quick readme.md. Just so we can talk about what we're going to be making here. So in this section, we're gonna be using raw HTML slash JavaScript in conjunction with our smart contracts to build this website. Later on. We will use next Jas slash react, which is a more modern stack to build our websites here. But learning understanding how to do everything with HTML and JavaScript first, is going to make our lives a lot easier come later on down the road. B
ut as we know, all websites use HTML as kind of their scaffolding for what they look like. So let's go ahead and create our HTML for our website, we'll call it index dot HTML. And this is going to be the basic scaffolding or the basic bones of what our website is going to look like. Now, in VS code, if you go ahead and just type exclamation mark index dot HTML, and you click the first thing that pops up, it'll automatically populate your code your file here with some basic HTML setup. If it does
n't do this for you, feel free to copy paste the basic setup from the GitHub repository associated with this course, we have our doctype. HTML, we have some HTML tags telling us that everything in between here is going to be an HTML, which is great. However, for simplicity, we don't need most of this. So we're going to make this a little bit easier. We're going to delete this line, this line and this line. And we're just going to change the title to fund me app. And then inside of our body, we c
an do something like or Hello. And now we have the bare bones to create a website just with this. Now to show this on a website, we can do one of two things. If you are using Visual Studio code, I'm going to recommend you install the extension live server. And it looks like this. And I'll have the extension ID for this extension in the GitHub repository associated with this course, this is going to allow us to easily spin up an HTML website. So we'll go ahead and install this. And if you're not
using Visual Studio Code, I'll show you a different way in just a second. Once this is installed, you should have this little go live button at the bottom. And if you don't, you can always open up your command palette, which again, you can open up by hitting View command palette, and you can type in live server and just say open with live server but we're going to just click this go live button. And it's going to say starting and it's actually going to open up your browser with our index dot HTM
L. We can actually see our website is being called Save on 120 7.0 point 0.1. This is known as the loopback, or local host endpoint, we're on port 5501. If you're not familiar with the ports, don't worry about that for now, we have our index dot HTML here. And if we change this to something like what's good, we hit save. If it doesn't automatically refresh, we'd come over here and refresh. And we'd see that being reflected here. If you've never created a website before, you've essentially just d
one it, congratulations, you might get this.vs code folder. a.vs code folder allows you to make settings specifically for the repo that you're working with, for your code editor for VS code, but we're going to mostly ignore it for now. Now, if you're not using Visual Studio Code, what you can do is you can just run this in the browser. So one thing you could do is you could right click it, and I'm using a Mac. So I'm going to hit Reveal in Finder, aka reveal where it's located. And you can just
double click it, and boom, now it's running right in your browser. Instead of pointing to your localhost, it's going to be pointing directly to your local file path. Now one final version that we could do that I'm going to highly recommend you don't do. But it's another option, we're actually going to download a package for you using no Jas, which allows us to serve up HTTP. And we're gonna install it the exact same way we've installed our other packages, we can do yarn, add dash dash dev HTTP h
yphen server. And you may still want to add it anyways. But now, we'll get some node modules for this HTTP server package, we'll get a package json, and of course, a yarn dot lock as well. And what we can do is we can stop this down here, stop that live server. And if we go back to our website, refresh, it'll now be blank. And we can run yarn HTTP server. And this will do the exact same thing. And we get, and if we come over, and we refresh, we'll see what's good. Now this one is a little bit mo
re finicky. And after you make a change, like, Hey, what's good, you might have to close it, and then reopen it and then refresh. So I do recommend that if you're on Visual Studio code, you definitely just use this little go live button, because it'll reflect your changes a lot nicer. So let's go ahead and hit the Go Live button. Hey, what's good pops up. Okay, cool. Our HTML is working perfectly. So the title, of course, is going to be the Funmi app, which we see up here in the title section. S
o let's update this HTML, so that it has those buttons, and it can actually connect and work with our blockchain and work with any blockchain. Something else that you can do in HTML is you can actually write JavaScript inside your HTML. And the way we can do that is by doing this script tag, and then we'll do a closing script tag. And anything inside here inside of our script tags is going to be JavaScript. So I could do something like console dot log, hi, with a bunch of exclamation marks, I'm
going to save it. We'll go back to our front end, we're going to right click, we'll hit Inspect, we'll go to the console. And we can see that Hi prints it out, we refresh, we can see the hi consistently printed out hi from script tag, we'll save it, we'll move back, we see hi from script tag printed out. I know it's a little bit small. So let me zoom in. Alright, great. So we can type our JavaScript in here, it's inside the script tag is where we're going to write our JavaScript to write the fun
ctions that our front end is going to interact with. Now, as we saw before, in this little console, we can check for window dot Etherium, to see if Metamask or is installed. And again, a lot of what we're working with is actually right in the Metamask documentation. If you go to their basic section, they talk a little bit about the provider, which is this window dot Aetherium, you can read how to actually interact directly with meta mask in the meta mask documentation as well. Now using window d
ot Aetherium is just one of the ways we're actually going to connect to the blockchain, there's actually multiple ways because there's multiple different kinds of wallets out there. But for now, we're just going to pretend that window dot Aetherium and meta mask is the only extension out there. So what we want to do is we want to check to see if this wind of that Aetherium exists. This is the first thing that we should be doing. Because if this doesn't exist, this means that they can't connect t
o the blockchain, one of the first things that we're going to want to do is we're going to want to check to see if that exists. So we can do something like if we can say type of window that Aetherium does not equal, undefined. Then we'll do console dot log, I see a meta mask. So now if we save, we come back to our front end, we do see I see a Metamask. I've got a Google Chrome up without Metamask that if we look in the console, and we hit refresh it the same URL where our live server is running.
We don't see that I see a meta mask because it doesn't see a meta mask. We can do else. console dot log, no Metamask refresh, we still see ICD a meta mask where we have a meta mask. You don't have to open up a browser without one but we see no meta mask for Chrome because it doesn't see a meta mask. Now what we could do is We can automatically try to connect to meta mask if we see that there is a meta mask, right? Remember how before, when we hit that connect button meta mask popped up and said
, Are you sure you want to connect? So what we can do is, and you can, again, you can find this in the meta mask docs, we can run this eath request accounts method, which is basically going to be how we connect our Metamask. Now, this is specified by a new EIP and an older documentations. And in older tutorials, you might see Aetherium dot enable, which essentially does the exact same thing. So what we could do here is we could say, a cerium, or excuse me, window dot Aetherium dot request. And w
e could put method F request accounts. And we'll save that. Now if we go back to our browser, we'll actually see, you'll actually see Metamask, go ahead and pop up and say, let's connect so we can choose an account. And we'll hit Connect, will automatically connect our meta mask to our website. And now if we look at our meta mask, we can see this little connected thing. It's saying that our account one is now connected to our website. This means that the website can now make API calls to our met
a mask, we still have to be the ones to approve them. But it can go ahead and connect and try to run transactions, which is awesome, which is what we want. If you want to disconnect, we can go ahead and click that little button and hit disconnect this account. Well that we have our code currently is anytime we hit refresh, this is going to pop up which is going to be really annoying. So what we're going to do instead is we're going to wrap this up into an asynchronous function, the exact same as
we've been doing, we'll do we'll create an async function called Connect. And we'll wrap it up these curly braces here. And then we'll just format this a little bit to make it look nicer. And now if we save, we go back to our website, and we refresh. And we go ahead and disconnect. If we refresh Metamask won't keep asking us Hey, do you want to connect Hey, do you want to connect here do you want to connect, because we need to call this connect function where we can do that is we can add a litt
le button here. So right underneath our script tag, we're going to add a button tag. So this is the opening button tag. And then here's the closing button tag. And inside the opening button tag declaration, we'll give it an ID, which will be Connect button. And we'll say on click equals the Connect connects function. And we'll call this button connect in between these little button tags, we'll call it connect will say when we click it will call the Connect function. So if we save, and we go back
to our front end, we can now see we have a little Connect button. And now if we press Connect, Metamask is going to pop up, we'll hit next and connect like that. And boom, now we are connected. And we can even do a little await here so that we wait for this to finish before moving on. And then after we connect, we can say console dot log connected. So let's actually go ahead and test this out, we'll go back to Metamask. we'll disconnect here, try to never be on Main net if we don't have to be.
And let's go ahead run connect, we'll hit Next connect. And now we see a little console dot log come out saying connected. Okay, great. We can also update our website accordingly. So that we can let users know that we're connected. So we can grab the connect button element ID and say that we're connected once we're connected. So after we await to be connected, we can go ahead and do document dot get element by ID Connect button. And then we'll say dot inner HTML equals connected like that. And t
hen instead of saying no minimize down here, we'll do just the opposite. So we'll copy this line. And instead of connected, we'll say please install meta mask. And we'll save we'll go back to our front end, we'll hit connect. And now if we're already connected, it'll just automatically go to connected. If we're not connected, it'll pop up, we'll get connected. And now we have this button that says connected, which is great. So now we already know that we're connected. So we've connected our Meta
mask to our front end. Now we want to actually go ahead and do some functions here. And this is where we want to create some more functions and some more buttons that are going to use ethers that package that we become so familiar with. Now, as we code, our script section is going to get bigger and bigger and bigger. So oftentimes, we actually want to put our code in a JavaScript file itself. So we're gonna go ahead, come over here, we're going to create a new file, and we'll call it index dot j
s. And instead of putting our JavaScript in these script tags, we're going to put it in this index and then import this index file into our HTML. And the way that we're going to do that is we're actually just going to grab this function. We're going to copy it, delete everything for now. We're going to paste it into our end ext dot j s, and then in our index dot HTML, we're just going to tell our script tag to use index.js. So we're just going to say the source is going to be equal to dot slash
index dot j s. And then we're going to say, the type of this is going to be text slash JavaScript. Now if we save that, and we save our index dot HTML, we come back to our front end, we do a little refresh. And we make sure that we go ahead and disconnect. And we do another refresh, we can see that even with our index.js in a different file, because we're doing src equals index.js, and we're importing it into our HTML, when we hit Connect, it still calls our Connect function. That's how we can
kind of separate our JavaScript into its own js file that we're a little bit more familiar with. Now, if you look in the GitHub repo associated with this course, and you look in the index dot j s, you'll see our Connect function, we've added some quality of life stuff, we've added some try catches just to make handling errors a little bit better, you can go ahead and add those try catches in yourself if you'd like. But I'm not going to demo them in this video here. Now we want to create our fun
function. And then later on, we're going to create our withdrawal function. And this is where front end JavaScript code. And no Gs are a little bit different. In no JS, we've been using this require keyword to import dependencies in front end JavaScript, you can't use require, and it won't exactly work. Now later on, we're going to use the Import keyword, which is really the better way to do this. And this is where our first differences going to be using the Import keyword for front end is much
better than the require keyword, especially since the require keyword doesn't actually work. And for those you who might struggle with this disconnect in this change. Once again, in the GitHub repo associated with this, we do have a Node js edition of this, where you can use the require keyword, you just have to go through the readme and download some packages and run some scripts that basically transform your code that uses require into code that works with imports. But we're going to teach you
the way to work with your front end code here using imports. Now you'll see when we get to next Jas that we will still download code from node modules and using a yarn lock and a package json etc. So summary in future seconds, we are still going to do yarn add. But outside of a framework when we're using this raw JavaScript, this raw HTML setup, like what we're working with here, we're not going to be doing yarn, add node modules will add node modules for framework like next react. But for raw
JavaScript, we'll be using a different syntax, which I'll show you soon. So let's go ahead and start building our fund function here. To make our fun functions, what would we normally do? Well, we'd create an async function called fund. And in this function, we probably would want to take some ether mount as a parameter, because we're going to want to fund it with some amount of Aetherium. When we call this function, we might want to run console dot log will do a little string interpolation here
. Funding with eth amount, dot dot dot, these semicolons are going to drive me absolutely insane. So I'm going to add a our dot prettier dot our rc file into this, and I'm going to go ahead and add prettier in here. Otherwise, I'm going to lose my mind. So we're gonna do yarn add dash dash Dev, prettier, just so we can format our JavaScript with prettier come back to index.js. I'm gonna hit command S, and it looks like it does indeed, auto format with prettier now yay, no matter semicolons, we c
an call this fun function the same way we call connect. So in in our index dot HTML, maybe we'll create a new button. Button. We'll give it an ID of fund will say on click equals fund. And we'll say fund. And this will be our button here, we save it, we're looking at our front end. Now the fund button that if we call, we say funding with undefined because we're not passing it an amount here. So back in our index console dot log funding with and we'll just want to make sure that we can actually c
all that Funmi function. So we'll copy this line again and we'll say type of window dot Aetherium does not equal undefined. We'll go ahead and try to fund here to send a transaction. What are the things that we absolutely 100% Always need? Well, we need a provider slash connection to the blockchain. And we need a signer slash wallet, slash someone with some gas to actually send it and then And we're probably going to need the contract that we are interacting with. And to get that contract, we're
going to need ABI and address. And with these all together, we can send any transaction. So to get our provider, we're going to actually go ahead and work with ethers again. Now, we're going to do it a little bit differently, though, before, the way we worked with ethers is we said const ethers equals require ethers, right. And this is how we pulled ethers. And now like I just said to you, though, require doesn't work in the front end. And we actually don't want to install ethers with a node mo
dules package. So what we can actually do instead is let's go to the ethers documentation. If you go to the Getting Started section, scroll down, they have a section about importing using Node js, which uses require or imports. And then they also have some documentation for working with the web browser. So instead of us doing a node module, what we'll do is we'll copy the ethers library to our own directories and serve it ourselves. So what we do is we can come in here, we can copy this massive
file, which is ethers, but in front end addition, and come back to our file. And we'll make a new file in here. Called ethers. We'll do 5.6 point esm.min.js. And we'll paste that massive thing in here. Now, since I have prettier when I save it, it's going to auto format. And it's just this huge file, which has everything ethers, but front end defied if you will. Now what we can do is we can import this into our index.js. So instead of using require in here, we'll say import ethers from and then
we'll just refer to that file that we just got ethers dash 5.6 point esm.min.js. Now, we only need to do this weird copy pasting of the file import thing in this HTML JavaScript lesson. In future lessons with Node js, we are going to do yarn, add ethers, kinda like we've normally seen. The frameworks like React and next Jas that we're going to use are going to automatically convert those yarn added packages to their front end to five versions. But for this section, this is how we're going to act
ually import the ethers package. Now the other thing we'll have to do is on our front end, we'll have to change this from type text slash JavaScript to type module changes. The type module allows us to import modules into our code, which we're going to be importing this, and we're going to import another module as well. Awesome. And now though, if we go back to our front end, do a little refresh with the connect button, we get Connect is not defined at HTML button.on. Click, so instead of callin
g our Connect button from the front end here, we're going to remove these on clicks from our index dot HTML, and go into our index.js and add those connect buttons in here. So we'll say const. Connect button equals document, dot get element by ID, Connect button. And then we'll say const. One button equals Doc, you meant dot get element by ID. One button, the idea of the connect button is Connect button. The idea the fun button is fun button. And then we'll say connect button.on Click equals con
nect. And one button.on Click equals fond. We go back to our front end, do a little refresh. We'll hit connect now. And it's actually working, we'll go to our Metamask will disconnect, refresh, hit Connect, and boom, it's popping up again. This is just due to that type being module, if it was text slash JavaScript, that on click button adding in here, but since we're doing module, we're going to add those on clicks right in our JavaScript. But now that we've got ethers in here, what we can do is
we can even do like a little console dot log, just paste ethers in here, or actually better yet. We'll add it right above the Connect button. Go back to our front end, we'll do a refresh and we see the entire ethers object right in our front end which is perfect, which is exactly what we want here. And since we've got these two variables here, we might as well update this to just say connect button dot innerHTML equals connected and here as well. Connects button dot innerHTML equals please inst
all meta mask because now connect button is going to be the same as running this document dot get element by ID right here. and great. Let's go back to continuing our font function. So we'll say const provider equals new ethers dot providers dot web three provider, window dot Aetherium. Web three provider is an object in ethers that allows us to basically wrap around stuff like Metamask is web three provider is really similar to that JSON RPC provider, which we use before, which is where we put
in exactly that endpoint, our alchemy endpoint, or when we're working with Metamask. Here, whatever endpoint that we have in our network section is web three provider takes that HTTP endpoint and automatically sticks it in ethers for us. So this line of code basically looks at our Metamask and goes, Ah, okay, I found the HTTP endpoint inside there, Metamask. That's going to be what we're going to use as our provider here. Since our provider is connected to our Metamask. Here, we can get a signer
or we can get a wallet just by running const signer equals provider, dot get signer, this is going to return whichever wallet is connected from the provider, which again, our provider is our Metamask. So if we're connected with with account one, it's going to return account one as the signer connected with account two, it'll return account two, etc. Now, I'm going to add console dot log signer here, and then flip to the front end now and show you what happens when we hit the fund button. You ca
n see in here we have our JSON RPC signer, the signer is going to be the account that we've connected to our front end. Now we have our provider, we have our signer. Now, we're going to need our contract by getting the API and the address. So we're gonna need to say const. Contract equals what? How are we going to get our contract? Well, this is where we're going to need to know the ABI and the address of a working with typically, what you'll see a lot of projects do since once a contract is dep
loyed, the addresses are going to change is they're going to have some type of constants file. So they'll create a new file called constants, dot j s. And in here, they'll add the addresses and any API's and anything like that for us to use in our fund piece here. Now, as we're developing, and as we're building, this, the backend and the front end team are gonna have to interact a little bit, or if it's just you doing the full stack, you're gonna have to interact with their back end. So this is
why it's so important to have both your front end and your back end code nearby. So if we go back to our Hardhead, fund me project that we just made, we can find the ABI in here. Once again, if we go to artifacts, go to contracts, we can go to fund me dot soul, fund me dot JSON, we can find the ABI right here, it's going to be this massive thing right here. So you can go ahead, you can even copy this whole thing in this little non squiggly bracket and this little bracket here, we can copy that.
And then we can come back to our constant.js. And we can just save it as variable, we'll say Export const, Avi, e equals and paste that in there. And then back in our index dot j s, we can import it with import API from constants. Oops. Okay, great. So we have the API. Well, what about the address, since we're going to be running this locally, we want to get the contract address of this locally run contract, we can do that a couple of ways. One way is you can just have two windows open one with
your front end code, one with your back end code, and the one with your back end code, you can run yarn, hard hat node, which will spin up our blockchain node for us, and give us the address in here. Or what we can do. And this will probably be a little bit easier is in your window with your front end code and create a new terminal. And now we'll have two terminals running. And then this second one, we're going to CD down CD dot dot, and then CD, hard hat on Me Free Code Camp. And in here, we're
going to run yarn, art head node. And this is going to spin up our local blockchain in this second terminal in here, where we have deploying fund me deploy that address, blah, blah, blah, right here. And just a reminder, if I hit this x, it just hides the terminal. I can always pull it back up with terminal new terminal, and I can always hide it, but this is still running inside of my terminal. So I'm going to hide it. And what I can do is I can come back over to our constants folder, and at th
e top, we can do export const contract address. equals, we'll pull the terminal back up. And we'll go grab, where it says, pulling fund me deployed at right here. We'll copy that address, put some quotes, and we'll paste it in. And now we're also exporting the contract address, then in our index.js will import the contract address with comma, contract address. And now we have both the ABI and the contract address. So what we can do, we can say const contract equals new ethers dot contract of, we
'll pass the contract address, pass the API, and we'll pass it the signer. Now we have an ethers contract object that's connected to our signer, and we have the contract address, and we have the contract abi, now that we have a contract object, we can go ahead and start making transactions the exact same way we've made transactions before we can just run const transaction response equals a weight contract dot fund. And then we'll pass a value of ethers dot utils dot parse, ether ether mount. So
this is going to be how we're going to go ahead and create our transaction. And if you take this right now, and we go to our front, we give it a little refresh, make sure we're connected and we hit fund, we're gonna get this error value must be a string. That's because at the mount right now is being passed in as nothing. Now normally, we'll pass parameters directly to our functions. But what we're going to do is for now is we're just going to hard code this. So we'll say const. At the mount equ
als, we'll do like 77, or something we had fun. Now, what do you think's gonna happen? Well, we get this other air, insufficient funds for intrinsic transaction cost, or you might get some other error, but you're gonna get a weird error here. And that's because we're not actually connected to our local hard head node right now. Well, if we look at our Metamask, we're currently not connected to the right blockchain, we're connected to rink B, or main net or whatever, we need to get connected to o
ur local host. If you look in your networks, you'll actually have a local host object here already. But let's just be super specific. And we'll add a new network here, we're going to add something called our hard hat, local host. And we'll hit Add Network and we'll add Hardhead. Local host in here, the RPC URL, we can find from our node area, which we scroll to where our node is running, we can copy this URL and paste it into new RPC URL, chain ID is going to be 31337 currency symbol is going to
be go or ether. Even though this pop up says it might have a different currency symbol go, we're just going to put eath in here. And there is no block explorer, right? Because this is a local blockchain, we're not going to have a block Explorer. So we'll go ahead and hit Save. And now we have an account here, which is great. We're connected to our local blockchain. And if we switch our meta mask, we can see we're on the local hard hat. And we are connected. Awesome. Let's refresh. Let's run fun
d one more time. And we'll see a transaction does indeed pop up. This is great. But our account here doesn't have any money we have, we're broke, we don't have any local Hardhead Aetherium. So we're actually going to need to import one of our accounts from hard hat into our meta mask, which we can do so and you can actually do this for any account with a private key so hard that gives us these accounts. And we're going to import the private key of Count zero into our meta mask. So we're going to
copy the private key, we're going to come back to our front end, click on our meta mask, we're gonna hit this big button, we're gonna hit import account. It's like type private key, and we're gonna paste our private key here. A quick note, if you choose json file, remember how back in that ether section, we encrypted our key into a JSON file with a password, you can actually import accounts with that JSON file with the password. So if you encrypt a key and you want to add it to meta mask, you c
an go ahead and add it in just like this. But for now, we're going to use private key, we'll paste the private key in and we'll hit import. And we can see we now have an account, a new account and account three, with a ton of eath from our local blockchain. So we'll refresh one more time, we'll go ahead and connect, we'll make sure that our account three is connected. And if it's not, we'll go ahead and hit this Connect button. So that now our account three is what's connected here. And we'll go
ahead and hit fund. And we now see that we can fund this contract, we can go ahead and hit Confirm. And if we look and nothing's going to happen on our front end, because we didn't tell our front end to do anything once we confirm, but if we go to our blockchain, we can see our fun function was called we've just made our first transaction on a blockchain from our own front end, this is awesome, great work. But it's probably a little confusing to the user. If nothing happens here, they're going
to hit the fun function. And it's going to be like, Oh, okay, cool. What, what happens? Now, we probably want to make it a little bit more obvious that something just happened. And one more thing I want to show you, you don't have to follow along here, if I hit fund, and then I hit reject, it's gonna freak out on us and be like, hey, like, you hit reject, I don't know what to do now. So we're going to make our code a little bit more robust by adding a try catch. So we'll tell JavaScript to try r
unning this transaction. And then if it catches an error, just to console dot log, that error. So now, if I hit fund, and I hit reject, it's gonna, it'll still be a little bit mad, but at least we're catching it and it's not going to break and destroy everything. Okay, cool. We've got a transaction response here. And when we hit fund, our front end goes great. You've funded me I'm I'm super confused. Oh, one other point, something that you'll probably run into multiple times. As we're doing this
. If you get an error that looks like this eath. JS query while formatting outputs from RPC, nonce to high expected not to be too but got form, you will definitely see this a whole lot. Here's what you do to fix this. The reason this happens is because you've closed your hardhat node and then restarted it, and your heart had node goes, Okay, well, I'm starting fresh, I'm starting from zero. But Metamask isn't smart enough to know that, what we want to do is we want to come to our Metamask, we'll
hit this big button, we'll go down to settings, we'll go to Advanced, and we'll go to reset account. And yes, we're going to reset it. This isn't something ideally that you'd like to do with an actual account with actual money on a local network, this is fine. Now if you reset the account, and you reset the node, we can go ahead and hit Confirm. And it doesn't give us that error anymore. So that's kind of the tip there, you want to reset the nuts so that our Metamask and our blockchain are in s
ync with that nonce number. So we have this transaction response. And we probably want our front end to give the user some indication, hey, the transaction went through. So what we want to do is we want to listen to the blockchain for this to finish. So we can either listen for the TX to be mined. Or we can listen for an event. We haven't learned about events yet. But we will. So for now, since we haven't learned about events yet, we're just going to listen for the TX to be mined. Or to listen f
or the transaction to be mined, we're actually going to create a new function called function, listen, or transaction mine in this is going to take as input a transaction response, and a provider. Now you'll notice this isn't an async function. For this section. This is intentional, we don't want this to be an async function. And you'll see why in a second. We're going to be using JavaScript promise JavaScript async functionality to its massive advantage. And this is why JavaScript actually work
s so well on the front end is because of how it's asynchronous. So we're going to create this function listen for transaction to be mined, we're going to await in our fund function. And we're going to have this return a promise. Let's go ahead, and let's learn how to build this. So we're gonna say console dot log, string interpolation, we'll say mining. And then in here, we'll say transaction, response dot hash. All of our transaction response objects have a hash, which just represent that hash.
And we'll do a couple of data dot, we'll put in our console here, we're waiting for the transaction to be mined, then what we're going to do is we're going to return a new promise. And the reason we're going to return a promise is because we need to create a listener for the blockchain. We want to listen for this event to happen. But we want to tell JavaScript, hey, wait for this thing to finish looking, wait for this thing to finish looking. Now here's where this gets a little bit tricky. In o
ur fund function. After we create the transaction, we basically want to tell JavaScript Hey, wait for this TX to finish. So our code is going to look as simple as await listen for transaction mine. And we're going to pass it the trans action response and our provider. So we're saying hey, listen for this transaction finish. And we're using this await keyword, because again, the await keyword says okay, we're gonna stop right here. We're gonna stop until this function is completely done. Now in t
his listen for transaction in mind, we have to define how we're actually going to listen for this. So we're going to say listen for this transaction to finish. Ethers actually comes with a way for us to listen for transactions and listen for events, which again, we haven't learned About, but don't worry about that yet. So we can go to the ethers docs. And we can look up once. Contract dot once. There's a whole bunch of listeners that we can use to listen for events and listen for different thing
s to happen, we can do this thing called provider dot once where we listen for some event. And once that event fires, we call some other function that we've defined. Now, we haven't talked about events yet. And again, don't worry about this quite yet. One of the events that we can wait for is we can just wait for the transaction receipt to finish, right, because once we get a transaction receipt, that means that the transaction has actually finished going through. So we're going to use this prov
ider dot once syntax to wait for the transaction receipt, which is going to be our event, which isn't really an event, but don't worry about that yet. And then we're going to call some listener function that we defined, you can also do provider.on, which will trigger anytime your event fires provider once just triggers one time, we only care about this transaction going through one time. So we're passing our provider object. So we're gonna say provider dot once our event which is just going to b
e transaction response, hash, provided on transaction response dot hash. So once we get this hash, which will pretty much get right away, we're going to call our listener function. Now we can create a function listener like this, and then just pass listener in here. But we're going to do an anonymous function here, because that's typically what we see as the syntax for these loops. And so far, we're doing provider dot once to do this anonymous function, we're going to do just two little parenthe
ses here. And this arrow notation. So this by itself represents an anonymous function. So we're saying, hey, there's some function, it doesn't take any parameters, and it doesn't have any code, this arrow function, this whole thing is saying this is an anonymous function. So we're saying provided at once transaction hash happens, here's the function that you want to execute. It doesn't do anything right now. But let's have a do something. So once this transaction dot response finishes, we're goi
ng to take a trans transaction received as an input parameter, or our our callback function, or our listener function. And all we're going to do is we're gonna say console dot log, completed with a little string interpolation, transaction receipt, that confirmations, confirmations, and then completed with transaction receipt, confirmations, confirmations. So once this provider dot once sees that there's a transaction hash, it's going to give as an input rammer to our listener function, the trans
action receipt, kind of that same syntax that we've been seeing this whole time, once a transaction response finishes, we get the transaction receipt, and we can do stuff with it. And we see how many block confirmations it has. For us, this pretty much should always be one. Now if we save this, go back to our front end, and we hit fund, it's going to work, we're going to give the user some indication that it worked, which is great. But it's not really going to work the way that we want it to wor
k. We have this console dot log done right after we do the await, listen for transaction mine, and we come back and we hit fund, we hit confirm, it actually doesn't go in the order that we want it to go, it goes mining this thing that it says Done. And then it says completed with one trip confirmation what what's going on here, we should write completed before we write done, because that's the order that we have this in. But it looks like it's words, it's going out of order. What what's going on
here, what's going to happen is when we call listen for transaction mine, or listen for transaction, mine function is going to kick off, but it's going to kick off provided on once as its own process. So await listen for transaction, mine will kick off the listener, but it doesn't wait for this listener to find the transaction response. So this function will actually finish before provider dot once finishes. So after it kicks off the listener, it'll run to the next line of our code, which is co
nsole dot log and done. Our front end we'll go oh, oh, you kicked off a listener earlier. Let me go back down and let me recheck to see if it's finished. And if it has finished, I'll go do what it told me to do. And this is where what's known as the event loop kicks in. We don't actually wait for this provider that wants to finish, we add this provided at once onto this queue called the event loop. And our front end is going to periodically check back to it to see if it's finished. So we want to
adjust our code. So we wait for the listener to finish listening, which is where we're going to get into promises here. So what we want to do is we want to adjust this function to now return a promise. And we're going to use this syntax a couple of times in the future. So what we're going to do is we're going to say hey, we want to wait for the listener To finish listening, we're going to wrap this whole thing into a promise. And we're going to say return, new promise. And a promise takes a fun
ction itself as an input parameter. So again, we'll use kind of this anonymous function notation. And it will take two input parameters resolve and reject. So resolve says, hey, if this promise works correctly, call this resolve function. And for us, this promise is going to be done when the listener finishes listening. And then we would reject if there was some type of timeout, we're not going to write the reject function. But in the future, if you were to do this for production, you'd add some
timeout as the reject parameter. Basically, you're saying, hey, once the listener finishes listening, we're going to resolve and if it takes too long, we're gonna say ask for you, you took too long, and instead of closing it off, here, we're going to close it off around this provider thing. So we're gonna say return new promise, resolve, reject. And only once this transaction gets fired, are we going to resolve this promise, like so. So what is happening here, so we're going to put the resolve
inside of this provider at once. So we're saying, once this transaction hash is found, then we're going to call this function, we're gonna say console dot log, and then we're going to resolve so this promise only returns once a resolve or reject is called. And we're telling it only resolve only finish this function once. Transaction response dot hash is found, because it's going to be inside of these little squiggly parentheses for provider dot once, the promise right now only resolves after it'
s fired. It's event here. If this was really confusing, just copy paste this and move on, we're getting a little bit deeper into front end stuff here. So hopefully, this was clear, if not definitely jump in to the GitHub discussions to start asking about this stuff. But now that we've updated this, we can come back to our front end, we can hit the fund button. And hopefully this time, everything will go in order. We'll hit confirm, we see mining completed, and then we see done. And the reason fo
r this is because again, our await keyword is now waiting, it says oh, you're returning a promise, I need to await I need to wait for it to resolve or reject. And we only resolve the promise once our provider finds this transaction hash and this transaction receipt, this is this listen for transaction mine. In future sections, all of this is going to be abstracted away for us. So life is going to be much easier, but it is important to understand what's actually going on here. Awesome. So now we'
re giving the front end some indication of what's going on. Our fun function is done well, no, not really. Why not? Well, because right now we're hard coding the eath amount to 0.1. And on the front end, we probably don't want to hard code it, we probably want to allow users to fund as much or as little as they want. So we actually need to change this from just a button to a input form. So to do this, we're gonna go back over into our HTML. So we'll go back to index dot HTML. And we're going to
change this fun section here, we're going to add some form information. So we're going to keep this button as it is, or we're going to add like a little text box to input as much eath as they want. So I'm going to create a label, we're gonna say it's for, it's going to be fund and this label we're gonna say, is eath amount, and then we're gonna close label, this is basically just going to create a label. And if we go back to our front end, we now just have this Etham out label that isn't labelin
g anything. Now we're going to create an input, and we're going to give it an ID of eath amount. And we're going to give it a placeholder of 0.1. And then we're gonna close the input. So now if we flip to our front end, we have eath amount, labeling this little text box with a placeholder of 0.1. And we can add stuff in here, you know, blah, blah, whatever. And one more thing, if you have some tags, but you don't put anything in between them, you can actually shorten it by just putting the littl
e closing thing at the back of it like this. So if you don't have anything between your tags, you can just close them like this, these two are equivalent, boom, boom, boom, boom, those are the same thing. Great. When we called fund right now we're calling fund and we're not passing any parameters. Let's update our fund to no longer be hardcoding eath amount in here, and we'll have and we'll have our fund function populated by whatever we put in this eath amount input box in our fund function, in
stead of saying const eath amount equals 0.1. We'll grab it from this eath amount ID and we'll say document dot get element by ID eath amount, dot value. So we're going to grab whatever value In this input box here, now, in our index.js, we have console dot log funding with eath amount, if in our front end, we do 1.7. And we hit fund, we now see in our console dot log, it says funding with 1.7. And we'll get 1.7. And our little fun section confirm, it will mine it, it'll complete it, and then sa
y, done. Awesome. So now we've added a little text box here. So people can fund as much or as little as they want. Perfect, this whole thing can kind of be considered a form. There's also a form tag, but we're going to just use this for now. All right, great. We're doing a lot of funding right, and we keep funding our contract with more and more Ethan, we keep adding more and more stuff, we probably want a button to keep track of how much is actually in here. So let's just add a really simple ba
lance button. And let me actually just move this down to the bottom here, much better. So we'll say button, id equals balance button. We'll call it get balance. Now we have a get balanced button. And it's not going to do anything because we don't have a get balanced function. So let's go back to our index.js. And we'll create a get bounced function async function get bounce. And we'll just do what we've been doing so far. If type of window dot Aetherium does not equal, undefined, then we're goin
g to do const provider equals new ethers, ethers, dot providers dot web three provider of window, that Aetherium then will do const balance equals awaits provider dot get balance, contract address, which again, we're importing way up at the top, and then we'll just do console dot log ethers dot utils dot format, ether, bounce this format ether function ethers utils, which you can find in the documentation to make reading ethers, formatted numbers much easier to read. Then same as what we've been
doing before, we're going to go up, we're going to copy this fun button line, paste it will say balance button equals document dot get element by ID, balance button. And then we'll say balance button on click equals get balance, we're gonna come back to our front end, we'll do a quick refresh, we'll do get balance. And now we can see the balance in the console, we can fund with more like 1.8, we'll hit fund metamath pops up, we'll go ahead and confirm mining completed done, we hit get balanced,
and now we're at 3.8. Fantastic. Alright, let's keep it going. What do we need to do next, we're gonna go ahead and eat our withdrawal function here. So let's create that this is gonna look really similar to everything we've done so far. So on our index dot HTML, let's create a new button that we can do by copying this whole line, paste it underneath, call this withdraw button, we'll call withdraw. And we'll call this withdraw. And then in our index, do the same thing, we'll copy this, paste it
below. So with drop button was document get element by ID, withdraw button, withdraw button.on Click equals withdraw. So let's make a withdrawal function down at the bottom. We'll go ahead, say async. Function withdraw, will do the exact same that we've done above. And I can even just copy everything from the get balance and just remove the balance section. If type of window dot Aetherium does not equal to undefined, then we'll grab the provider here. And same as the fund contract, we'll grab t
he signer and the contract. So let's just grab those two lines. Paste them down here called signer equals provider dot get signer. Contract equals new contract, blah, blah, blah. Okay, cool. Now we're gonna do the exact same here as we did with the fun function. So we're gonna do a little try, catch, and then we'll even add the catch here, catch error, console dot log error. And inside of our try, we'll do const transaction response equals await, contracts dot withdraw. We don't need to put any
parameters in here. Oh, then actually, let's do a little console dot log, withdrawing, and then we'll get this transaction response. And then we'll listen for this transaction to get mined as well. By running a Wait, listen for transaction mine transaction response comma, provider And that's it, since we can reuse the functionality from our listen for transaction mine. So now we'll refresh, we'll make sure we're connected, check the current balance, which is 3.8. Now we'll go ahead and withdraw.
We see our little withdrawing console dot log, we'll hit Confirm. And it looks like we've completed it, if we look in our Metamask, our bounced will have been increased by the amount that was added here. And now if we hit balance, we do indeed see zero, we can even double check that this is actually working, we can see our balance is 9.99. Let's go ahead and even fund this with 99 eath. Good confirm, looks like it's completed. Our meta mask now shows 99.00. And if we go ahead and withdraw, conf
irm, that withdrawal has gone through, we can see our balance is back up to 9999. And now let's just go back and change. Hey, what's good. We'll refresh our front end. And now we can see you've done it, we've created a minimalistic website that allows us to connect to the blockchain and call functions from a front end. And from a website, this is absolutely massive, you should be incredibly proud and incredibly excited with yourself. Now, this is definitely a minimalistic version. And we're goin
g to work with more powerful and more modern front end frameworks. But this will give you an idea of exactly what's going on behind the scenes when we're working with those more advanced front ends, and we'll style them up. So they look a little bit better than this. But with that being said, you've just learned the basics of how these front ends work. And now that you know how to push things up to get, I highly recommend you start pushing all of these projects up to your GitHub, they will be a
record that you've actually done the work and you've built these smart contracts. And if you're looking to get an internship down the line, if you're looking to help other GitHub projects, this will be a record of hey, I can do this, what I can build look at what I know how to do so congratulations on your first full stack or your first front end application. Before we move on, let's do a quick refresher of everything we've learned here. So number one, typically, you want the repository or your
code base. For your back end for your smart contracts to be a different repository than your front end, your front end code is going to be a combination of HTML and JavaScript. When we have a wallet like meta mask, we're injecting these browser based wallets into the window object of our browsers like window dot Aetherium. Each browser will have a different extension here, reason we do this, we want to connect to the RPC URL that's built into our meta masks. And in this way, we're making the sam
e API calls to an RPC URL as we do in hard hat as we do in remix as we do in ethers, etc, we created our first promise based function where we had a listener kickoff, and we wrapped it in a promise to say, hey, we want to wait for our listener to finish since this is a promise based function, we set a weight listen for transaction mind and we waited for this transaction to finish so that on our front end, once our transaction finished going through, we can tell the user it's finished going throu
gh and we can continue doing other stuff. Give yourself that round of applause and let's move on to the next section. All right, welcome to the next section. We are now on Lesson Nine, our hardhat smart contract lottery, which again, all the code for this section is going to be available in the GitHub repo associated with this course. Alright, so let me show you what we're about to build. I'm going to show you the front end login, you don't have to do the front end, if you don't want. But the fr
ont end does give us a nice way to visualize the lottery that we're building. Here, we're building an application that allows users completely decentralized to allow us to engage in a fair, a verifiably random lottery. This is the application that would actually fix the McDonald's issue that we talked about much earlier. So first, we got this Kinect Wallet button that we're going to click to connect to meta mask. And here, we're actually going to show you how to connect to more than just Metamas
k wallet connect to trust wallet, math, wallet, any of these wallets, and we'll show you how to customize even more. So we're going to connect to Metamask. Here, we'll choose our account that we imported in from Hardhead, we choose Next we're gonna choose Connect. And remember, for our front end bit, we're gonna go to Settings Advanced reset account, if we're working with a brand new hard hat blockchain. Now, the front end doesn't look super nice, but we have an enter raffle button. And we have
a little bit of UI talking about the current number of players and then the most previous winner of a raffle. So we can go ahead and enter the raffle and allow anybody to pay 0.1 eath. To enter our smart contract, we get a little transaction saying transaction complete, and we get the current number of players is one, we can continue to enter the raffle and anybody can enter this raffle. And this, the smart contract will keep track of all the players in here, we're going to run this on a timer,
the lottery is going to automatically trigger somebody to win. And to do this, to get a pure verifiable random number, we're going to be using chain link VRF to get a pure verifiably random number. And then we're gonna use chain link keepers to trigger the automation to automatically have one of these winners get picked every time one of those time intervals is up. Once the keepers kick it off, they will pick a winner, our decentralized lottery will say the most previous winner is so and so. And
they will get all the money from this lottery making a perfectly fair decentralized lottery, we're going to call our contract, raffle dot soul but you can call it lottery dot soul or really whatever you want. And we're going to make it look really, really nice. So now we're back in our Visual Studio code. This is going to be the project. If you learn this, you have the skills to learn all the rest of the smart contract concepts, and you are going to be able to do great things in the space. This
is going to be your flagship project, this is going to be the one that you can be the most excited and the most proud about for this tutorial. So let's go ahead and let's create a new folder. So we're gonna do MK dir, hardhat, smart contract lottery, FCC or smart contract, raffle, whatever you want to call it, then we're going to cd into our hard hat, smart contract lottery Free Code Camp. And we're going to type code period, or we're going to open this up in a new folder, however we choose to
do. So now that we're in our new folder, we're going to create our new hard hat project. So we're going to do yarn, add dash dash dev hard hat. And we'll get our node modules are package dot JSON and our yarn dot lock. Now we'll do yarn hardhat. To get started with a new project, and we're just going to select create an empty hard hat dot config dot j s because we know what a basic project looks like. And we're gonna give this project the customizations that we want to see, we're going to create
an empty hard hat dot config. And now in here we have a blank hardhead.config.js with almost nothing in here. So we're starting completely from scratch. Now we're going to add all of our dependencies in here. And oftentimes, you'll add these sequentially as you build but we're just going to add them all in one line, and there are a lot of them. So we've left a copy, paste the whole section of the full blockchain solidity course, J S, for you to just copy, paste, so you can install everything in
one go. So grab that line, and it's going to have everything that we've been talking about. And we'll just hit enter, and we'll install all of these. And as you create more and more projects, you'll get the feel of what you like for your dependencies and what tools that you like to use. Remember, at the end of the day, the tool that's best for you and best for the job is the tool that you like the most. There never really is a one tool fits all, there's almost always going to be trade offs. Alr
ight, now that we have all those dependencies installed, if we look at our package, JSON will have this massive dev dependencies, we'll have everything in Node modules will have everything in yarn dot lock. And of course, as we know, in order for any of these to actually work, we need to add them into our Hardhead config. Now, there's a lot of stuff to add in here as well. So like once again, if you want to come to the heart at smart contract, lottery, FCC, and go to the Hardhead config, you can
just copy paste everything and place it into your project so that you don't have to always type everything out yourself. Meclabs Hardhead waffle anomic labs started ether scan harder to deploy slitted coverage, or had gas reporter heart had contract sizer, which we haven't talked about yet. But we will Don't worry. And then require dot env dot config. And as you all know, all these little semicolons are popping up and those are going to drive me absolutely crazy. So once again, we can create a
dot prettier, RC. And if you want to copy this as well, from one of your previous projects are free to do so. One thing that I added in here was a print width of 100. This just changes how long a line can be before it goes on to a new line. That's the only difference here. Now if we go to our config and hit save, they go away, thank goodness. Now if we look at our solidity version, we're currently using zero point 7.3. Let's go ahead and update that to 8.8 or 8.7, or whatever you want to use. No
w that we have all the basic setup, we can begin coding our smart contracts. So we first need to create a new folder called contracts where we're going to store all of our contracts. And let's go ahead and create a new file called lottery dot soul or raffle dot soul or whatever you want to call it. I'm going to call mine raffle dot soul. And you might see this indexing thing happened from time to time. It's our hard hat, solidity extension, indexing all of our node modules. So it knows how to hi
ghlight things and knows how to work with everything in our solidity files. So that's what happens when that pops up. Now before we jump in and create it, let's figure out what we're going to do. So we're going to create our raffle contract. And what do we want people able to do? Well, we probably want people be able to enter the lottery, you know, paying some amount, we're probably going to want to be able to pick a random winner. But we want this to be verifiably random, we want this to be unt
ampered with a bowl. And we also want winner to be selected every X minutes or years or months, aka we want this to be completely automated. So we want to deploy the smart contract and almost have no maintenance almost have nobody ever have to touch it again. And it'll just automatically run forever. This is the power of smart contracts. As we know, since we're picking a random number, and we have some event driven execution, we know that we're going to need to use a chain link Oracle, since we'
re going to need to get the randomness from outside the blockchain. And we're going to need to have that automated execution. Because a smart contract can execute itself, we need somebody to automatically trigger these. So to trigger selecting a winner, we're gonna have to use the chain link keepers. And that's pretty much going to be our entire code. Now, I usually like to do this before I start any project. And the reason that I do a little bit of brainstorming is because we don't want to just
jump in and really do anything, we want to have a good idea of what we're trying to build so that we can write tests for it, so that we can know if we're going in the right direction, etc. Now that we have a good idea of where we're going, let's build it. So per usual, let's do spdx license identifier. And my team will do pragma solidity little caret here, zero point 8.7, even zoom out, just a hair will trash that and we'll say contract, raffle, we can even make sure that we're not going crazy
by doing a little yarn Hardhead compile and compiled successfully, we want it to be able to enter the lottery want us to be able to enter it. So maybe we'll create a function called enter raffle. What else do we want to do, we want to be able to pick a random winner. So maybe we'll create a function called pick a random winner, and boom. So let's comment out pick random winner for now. And let's just work on this enter raffle thing. In the past, we've created projects like Funmi, where people ca
n send ether to our contracts or send whatever native blockchain token to our smart contracts using the message dot value based off of some USD value. For this one, we're just going to have the entrance fee instead be USD based, it's just going to be that native asset. So for our enter raffle, we don't have to set a USD price, we can just set a minimum eath price. So up at the top, let's pick our minimum price. So we'll do a un 256 entrance fee. And now some of our learnings from our last sectio
n should come in here, we now know that this entrance fee is going to be a what, it's going to be a storage variable. So let's prepend it with s underscore let's make a private variable because we always want to set our visibility. But let's have the entrance fee be configurable. Well, let's create a constructor now. And we'll have this entrance fee be settable in our constructor, so our constructor will take a UNT two to the sixth entrance fee, s underscore entrance fee equals entrance fee. Wel
l, if we're gonna only set this one time, we might as well make this a constant or an immutable variable. So let's make this an immutable variable so that we save some gas we'll change this from S to I and now we're saying you interviewed six private immutable I entrance fee equals entrance fee. Now we probably are going to want other users to see the entrance fee. So down below, we can create function get entrance fee, and this will be a public view function which will returns a UN to the set N
ext, and we'll just say return entrance fee. Now we have a function that users can call to get the entrance fee. But we, as developers can use this AI entrance fee to know this is an immutable variable. This is pretty cheap gas wise for us to read from in our enter raffle, we've done a ton of these before, all we need to do is we just need to require the message dot value is greater than that I underscore entrance fee, what we've learned before about those error codes, so we could use require me
ssage dot value, or we could do one of these customers, which is going to be a lot more gas efficient, because instead of storing this string, we're just going to store an error code in our smart contract. So let's do that. Instead, we'll say if the message dot value is less than our eye entrance fee, then we're just going to revert the whole transaction with some error code. And we'll use a best practice naming raffle underscore underscore not enough eath entered. And we'll grab this arrow code
. And we'll have if the user doesn't send enough value will revert with not enough eath entered now that we know they're calling into raffle with enough value, we're probably going to want to keep track of all the users who actually enter our raffle. That way, when we pick a winner, we know who's in the running. So let's create an array of players at the top error here. And then just to make this look even nicer, we'll do a little comment here. And we'll say state variables. And we'll combine bo
th our storage and are not storage variables just in this state variable section. So we'll do address array players. Now players, of course, is going to have to be in storage, because we're going to modify this a lot, we're going to be adding and subtracting players all the time. So we're going to do s players will make this private as well. And we're going to make this address payable players because one of these players wins, we're going to need to have to pay them. So we'll make this address
payable private as players. And since we're going to make this private, and it's probably good that we know who's in the players array, we'll even do function it player. This will be a public view that returns an address of one of these players. And we'll just return s players of index will have this function, take a un 256 index as an input parameter, we know that players is going to be a storage variable. And we're going to add it to our enter raffle Oh, and we definitely want our Inter raffle
to be public and to be payable. Since we're having people send message dot value, and we want anyone to be able to enter our raffle. So it'll be public, it'll be payable, it'll be perfect. Now that we have our array, and someone's entered the raffle, we'll do s players dot push message dot sender. Now, this doesn't actually work because message dot sender isn't a payable address. So we'll need to typecast it as a payable address just by wrapping it in payable. So now we have a way to keep track
of all the players that are entering a raffle. Now one of the concepts that we haven't gone over yet is actually going to be events. And events are really important to our smart contracts. Whenever we update a dynamic object, like an array or a mapping, we always want to omit an event when we get to less than 10. And then especially less than 15 with the next Jas and if T marketplace, these events will make a ton of sense, especially for front end developers. So right now events might be a litt
le bit of a weird thing for you as we explain it. But as we continue on, they'll start to make more and more sense. So we're going to start adding events to our smart contracts. Whenever we update one of these dynamically sized data structures. And to learn more about events and how to use them. We're gonna watch another video that explains all about events. You can actually follow along with this video as a side project. But let's learn all about events. 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 off chain protocols work under the hood. And in this video, we're gonna learn about logging and events in solidity, viewing those events on ether scan, and then working with them in hard hat. Now it's the Ethereum virtual machine, or EVM. That makes a lot of these block chains tick, like Aetherium. 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. Now inside these logs is an important piece of logging called events. And this is the main piece that we're gonna be talking about today. events allow you to print informati
on 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 because smart contracts can access them so that If the trade off 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 ti
ed 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 looking for something to flip and switch, all you have to do is say, listen for event. So a transaction happened, an event is emitted. And we can listen for these events. This is how a lot of off chain 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 it could do something else. It's incredibly important for front ends. It's also incredibly important for things like chain link, and the graph in the chain link network. A chain link node is actually listening for request data events for 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 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 omitting 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 unique 256. For c
alled old number. Are you interested? Is it called new number are you intimidated six called add a number and an address called center. Now for the astute people here, you might have noticed that there was another keyword in here, the index to keyword and this is a really important keyword. When we omit one of these events, there are two kinds of parameters, there are the index parameters and the non indexed parameters, you can have up to three index 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. Index parameters are parameters that are much easier to search for, and much easier to query than the non index parameters. In fact, we recommend F get logs function, it even has a parameter allows us to search for specific topics. So it's much more searchable than the non indexed ones. The non indexed ones are harder to search because they get ABI encoded, and you have to know the API in order to decode them. Now, th
is is 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 a mitt 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 walked through in hard hat. Now in this smart contract, whenever anybody calls the store function, we're going to omit this event. Here's an example of a transaction where we call 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 or the i
ndex parameters of the event data. This is the ABI encoded non index parameters of the event. What does this mean? This means that we took those parameters that were non indexed, we match them together with their API or application binary interface, pumped them through an encoding algorithm, and boom, this is what we got. If you have the API, 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. Now i
n this particular contract, since we have verified the code, we verified the contract ether scan knows what the ABI is, and we can view this in Deke or decoded mode. Hex mode is obviously the non decoded mode, or in its raw, hex or hexadecimal or encoded mode. You can read more about the layout of these events in the solidity docs. Now, so that's the basic introduction of events. And for those of you who want to watch the rest of that video, and who wants to actually practice using events yourse
lf, there's a link to these videos and the code repository associated with that video, if you want to play with it, and if you want to learn more, so feel free Ready to refer back to the full blockchain solidity course, Jas, if you want to go deeper into events now that we're back, and we've learned a little bit more about events, let's add some events to this contract. Remember, these events get emitted to a data storage outside of this smart contract. Let's create an event called raffle enter
a good syntax for naming events, name events, with the function name reversed. So for enter raffle, we're gonna say raffle entered. So up at the top below our state variables, but above our constructor, we'll create a new section called events. And we'll create our first event. So we'll do event, raffle, Enter. And we'll just have this raffle enter take one index parameter, it'll be an address indexed player. So in our Inter raffle, we're going to say omit raffle enter. And we're just going to p
ass it message dot sender. I'm going to remove these comments for now. But feel free to leave them in as you code along. Now in this part of my raffle coding or my lottery coding process, I probably would start already writing some tests and already writing some deploy scripts. The reason that we do this is it's good to test our functionality as we progress. And oftentimes, when I'm writing smart contracts, I'm constantly flipping back and forth between my deploy scripts, my contracts and my tes
ts to make sure everything is doing exactly what I want it to do for the purpose of this course. And just to make it easy for you to learn and follow along, we're not going to do that. And we're just going to keep writing our smart contract almost to complete and then move to our deploy scripts and tests. So in its minimalistic sense, we essentially have a way for people to enter our raffle. Now we need a way to pick the random winner. And this is where we're going to need chain link VRF and cha
in link keepers. So let's again, watch some sub lessons about learning about chain link VRF. And learning about chain link keepers. We've made some videos about these before. So we're just going to play these videos. So you can learn about how taling VRF version two works, and also how chain link keepers works, then we're going to come back and we're going to add them into our contracts here. If you're already familiar, and you already played with them, feel free to skip those sections. And we'l
l just get to building them here. Hi, my name is Steven fluid. And today we're going to be taking a look at chain links VRF. version two, version two has a few different mental models that we should be aware of. And I want to show you what it feels like to be using it. The big important thing to know about Vera version two is that instead of the Vera one model where you'd be funding your contract with Link, instead, you're going to be funding a subscription, which is basically an account that al
lows you to fund and maintain balance for multiple consumer contracts. Let's dive into the docs and see what using Vera fie two looks and feels like. In order to show this off a little bit. I'm going to dive right into the get a random number guide in the chain link documentation. And so it's going to go through a few the requirements of some of the technology we're going to use today. And the first thing it's going to ask us to do is to make sure that we are on the Rinkeby test net. So let's go
ahead and jump over to Rinkeby. Make sure my meta mask is unlocked here. And now that I'm on Rinkeby, great, I should be able to use the VIP version to test net. Now we're going to jump over to subscription manager. And the subscription manager is where we're going to manage our subscription account. Basically, this is the place that you put the funds in order to be able to use it across a bunch of different chains. So we're going to go ahead and connect our wallet here in order to use the subs
cription app. And then we're going to go ahead and create a new subscription. So we'll just use my address as the subscription address here. I'll approve the creation. And as soon as that transaction is confirmed, our subscription should be created. Alright, now we have a subscription. Basically, this is the account where we're going to fund it. And then we can use that account for all of our random Miss requests. So I'm gonna go ahead and just put in 10 link here, you can put in however much yo
u want. The price and link of every random number you request, it's going to be based on the current gas rates on a given chain, as well as the gasoline that you've chosen. On our funds have been added, let's go ahead and add a consumer contract. So it's asking us for consumer address, we don't actually have a consumer address yet. So let's go ahead and jump over to the documentation and create a contract that is going to request a number. So if you scroll down, you're going to see this Vera fee
to consumer that soul contract that we can open it in remix, let's just jump right there. We're gonna notice a few different things in this contract at the top, we've got some input. So now you've got VRF, consumer base version two, we've got an interface for the VRF coordinator, and then also a reference to the link token interface. So all of those are specified for you on the Rinkeby network here in the example code. And then you can refer to the documentation for whatever chain you're going
to be deploying to. And then you're going to see a few new options here. So the key hash option is the way that you specify that gasoline that was described in the documentation. So depending on the key hash you choose for the given chain you're on the gas limit will be set differently for your random number requests. So for example, on a theory main net, we have a 200 way key hash 500 Wiki hash and 1000 graykey hash. You can also see in our contract Hear that we have a callback estimate that yo
u're in charge of. So depending on how much gas you're willing to spend in the fulfill random number, you should set this value appropriately. Next up is request confirmations. So this was something in verify would be one that you could not control. But here now, depending on the chain you're on, depending on the request and the type nature of the request you want to make, you can actually change this number. And then one of the most important and useful features that gives you a lot more flexib
ility and control of your VRF is you can actually specify the number of random numbers you want. And so you specify the number words, and then that will specify how many random you went to 56 as you get back from the network. All right here in the constructor, we're gonna see a address for the coordinator and address for the link token. And then you'll see that the subscription ID is going to be created as we deploy the contract. And so I'm gonna go ahead and get that. So if you remember when we
created the subscription after we found it, and we see this subscription ID, and now when I deploy this, I'm going to use that subscription ID. And we've got two methods that should look very familiar, we've got fulfill randomness method that takes in randomness is going to be fulfilled by the Bureau of Oracle, as well as you got request random words, which is how we're actually going to initiate the request to the Oracle. So I think we're actually are already ready to go ahead and deploy this.
So let's jump to the deploy screen here and select the right contract, which in our case, is your FB to consumer. And I'm going to make sure that I am on injected web three so that we can actually deploy to the Rinkeby network. And I'm going to paste in the subscription ID here. And I'm going to deploy, let's go ahead and pay for that transaction. And as soon as that is confirmed by the network will show up here, and we'll be able to copy this address, and then add that as a consumer and author
ize this contract to use my subscription account. So let's go ahead and authorize this with them another Metamask transaction. Alright, we can have your subscription, we can see how much link we funded it with. And we can see our consumer contract. So now by doing this, we've authorized our consumer contract to make requests for randomness. So let's go ahead and make a request for randomness here. So we're gonna go back to our contract that we deployed here. And we're just gonna use the remix in
terface here to keep things simple. And I'm going to request some randomness. So obviously, this is going to use all of the configuration that I specified in my contract, just kind of hard coded here. So we're gonna get to words of random is here. So we're gonna hit request randomness, confirm the Rigby transaction. And then as soon as that transaction comes back, we should notice that we actually have a request. And then what we'll be doing is we'll be waiting for the Oracle to call fulfill ran
dom words on our contract. And then we'll be storing all of those random words in this s random words, storage variable. Let's go ahead and check to see if our random numbers come back from the Oracle. So I'll go in here into random words. And let's request the zeroeth item of the array looks like we've got a random number there. And because we requested two random numbers, we should also have an item in index one. All right, we we've got our randomness there. And if we go back to the subscripti
on manager app, you're going to see that there's actually an event history item here, we'll see that we spent about point three, three link to get those two random numbers, we've just taken a journey to see what it looks like and feels like to use Veera version two, now that we've learned a little bit more about chainlink VRF, I hope that you took some time to go to doxa chain link and play around with it a little bit so that you understand what's really going on, we're going to use this sample
contract in here to create our function that's going to pick our random winner. This is an on chain contract that coordinates with a verifiably random chain link node to give us a random number, you could look at the code directly on chain, or you can come right to the chain link GitHub and look at all the code for how this is actually happening provably and randomly. And we'll have a link to this in the GitHub repo associated with this course. So we're going to create our function here called p
ick a random winner, this function is going to be called by the chain link keepers network so that this can automatically run without us having to interact with it. And actually, while we're updating this, I want to add some some stars here saying view slash pure functions. Now our pick random winner function, we're actually not going to make public we're going to make external, external functions are a little bit cheaper than public functions. Because solidity knows that our own contract can ca
ll this, we're actually going to change the name of this function, as well, very soon, but we'll get to that in a little bit. So in order for us to pick a random winner, we actually have to do two things, we first have to request the random number. And then once we get it, do something with it. So chainlink VRF is a two transaction process. And this is actually intentional. Having random numbers in two transactions is actually also much better than having it in one. If it's just one transaction,
then people could just brute force tries simulating calling this transaction and we'll learn how to simulate calls soon simulate calling these transactions to see what they can manipulate to make sure that they are the winner. We want to make sure that this is absolutely fair. Nobody can manipulate our smart contract into having them be the winner of the lottery, this function is actually going to request it. And then in a second func the random number is going to be returned. And in the transa
ction that we actually get the random number from the chain link network, that's when we're going to actually send the money to the winner. And if we go to the chain link documentation, the function that the chain link node calls is this function called fulfill random words, this is going to be the requesting one, which we could even change this to request random winner to make it more clear, and then we'll make a function fulfill random words. And this is going to be an internal override, which
we'll explain in a little bit, now fulfill fulfill random words basically means we're fulfilling random numbers. The word comes from a computer science terminology, but you can basically just think of this as fulfill random numbers, because we can get multiple random numbers. Now in order to make our raffle contract VRF a bowl, we have to import the chain link code, we can go back to the documentation, and we're just going to grab this bottom line and we'll grab the top line in a second. So we'
re going to do import, I'm going to write it out. But if you want to copy paste, you can at chain link slash contracts slash SRC slash V 0.8, slash V RF, consumer base, b two dot Sol. And since we're importing at chainlink, slash contracts, we're gonna need to add that in by running yarn, add dash dash dev at chainlink slash contracts. And now that we have this in here, we should be able to import like so. And we're going to need to make our raffle VRF consumer base double, we're gonna need to i
nherit VRF consumer base go into our node modules at chain link src, V 08 VRF, consumer base V two, it comes with this function fulfill random words. And you can see it's an internal virtual function, virtual means it's expecting to be overwritten, the reason that it's in the sphere of consumer base V two is so that the VRF coordinator, which we'll use in a bit knows that it can call this fulfill random words function. And this is the function that we're overriding. So back in our raffle dot sal
t, we're going to inherit it by doing is VRF consumer base V two. And now if we scroll down to fulfill random words, we can add in the input parameters fulfilled pill random words, which are going to be un 256, Request ID and un 256, a memory array random words. And if we hit Save Our linter will now notice, okay, this is what I'm expecting, I'm expecting us to override the Fill random words, which takes these parameters. Now if we look in our docs in our constructor, we need to pass the VRF con
sumer base V TOS constructor and pass that VRF coordinator. Again, this V RF coordinator is the address of the contract that does the random number verification. So right next to our constructor will add the VRF consumer base V to constructor and we need to pass the VRF coordinator v2 address. So in our main constructor, we'll add that as a parameter as well. So we'll say address VRF core to Nate Torre v two, and then we'll pass this as a parameter for the VRF consumer basically till now that we
have that we shouldn't see that little underscore anymore. And we should be able to run yarn aren't had compiled. Awesome. And we can see compiled two files successfully and our code is working great. Now something that I often do is I actually hate running yarn hard hat all the time, because that's too many keys for my little brain to work with. I would prefer to write as little keys as possible hard hat also would like us to write as little keys as possible. So hard hat comes with a shorthand
and autocomplete hard hat shorthand is an NPM package that installs a globally accessible binary called H H, that runs the project's locally installed hard hat and supports shell auto completion for tasks. So what we can do is we're going to start with NPM, like this, but we're gonna install it with yarn, we're going to run yarn, global, add hardhat shorthand. And what this is going to do, we can see here installed hard hat shorthand with binaries H, H, and Hardhead completion. Now instead of r
unning yarn, Hardhead compile, which we can still run, we can just run h h compile, running h h is going to be the same thing as if we had just run the Hardhead command for our local directory. So now we need to actually have our request random winner function requests a random winner. So let's go back to the documentation. And we'll see how to do that. We can look at this function request random words and see exactly how it works. On the Vera of coordinator address. We go ahead and call this re
quest random words function, we're going to need to call this function on the coordinator contract to get the coordinator contract. We're going to use the Vera v2 coordinator interface and the Vir of coordinator address. So we're going to want to keep track of those. We can do that once again in Arkansas. factor, we have the address being passed to our Bureau of consumer base. Let's also keep it as a state variable for us. First, let's get the interface so we can interact with that contract, we
can import that from chain link as well by doing import at chain link slash contracts, slash SRC slash fees 0.8, slash inter faces slash VRF cord to mentor V to interface dot Sol. And now that we import this interface, same as we did with price feeds, we can do VRF, coordinator v2, interface VRF coordinator. And then we can save the sphere of coordinator using the address so we can say VRF coordinator equals this address VRF coordinator veto. And we're just going to wrap that address around the
interface so that now we can work with this VRF coordinator contract. Now we're only going to set our VRF coordinator one time right in our constructor. So what's the best thing that we can do here, private, immutable, you Gosh, darn. Right, let's do private, immutable, you have coordinator and we'll change the name to I underscore the ref coordinator so that we know that your coordinator is indeed an immutable variable. In order to request the random word, we need to give it a number of paramet
ers, I'm gonna go ahead and copy this line into our contract just so that we can talk about exactly what's going on with it. And we don't need the AES Request ID. And instead of coordinator we're going to do I underscore fear of coordinator. So we're going to call request random words on that VRF coordinator contract, and we need to pass it the key hash or the gasoline, I prefer calling it the gas lane, we go to the chain link, Doc's go to contract addresses. And we scroll down we can see differ
ent gas lanes a different configuration parameters for different networks is key hash is going to be the gasoline of the key hash, which tells the chain link node the maximum price you're willing to pay for your guests and way if for example, gas prices skyrocket, and it's going to cost you a ton of money to get that random number setting a ceiling, we'll make it so that random number doesn't come back. For us to pick a gas lane, we're probably going to want to have this gas lane or this key has
h stored somewhere. So let's go ahead and make that a parameter of our constructor as well. And we'll save that as a state variable. So we'll do comma bytes 32, gasoline or key hash or whatever you want to call it. And then we'll make a new state variable. And we're only going to set this once. So we'll make this a private, immutable. I underscore gasoline, and then we'll say gasoline equals gasoline. So now, we can just swap this out, or I underscore gasoline. Okay, what's next, we need a subsc
ription ID, the subscription ID is going to be the subscription that we need for funding our requests. There's actually a contract on chain, which we can use to fund any subscription for any of these external data or external computation bits. And in this contract, there's a list of these subscriptions for people to make requests to. So we need the ID of the subscription that we're using to request our random numbers and pay the link Oracle gas, the subscription ID is probably also going to be s
omething we're going to pass as a parameter to our lottery. So once again, let's scroll up to our constructor, we'll add a new parameter. And our subscription ID actually doesn't need to be a un 256, it can actually be a little bit smaller with a un 64. So we'll pass a un 64 sub scription ID, we'll make a UNT 64. Since we're only going to set this once we'll make this a private, immutable. I underscore sub scription ID down here and we'll say I subscription ID equals sub subscription ID. Alright
, awesome. So now we can change this to our subscription ID. Okay, what's next? Request confirmations request confirmations is a un 16, which says how many confirmations the chain link node should wait before responding. So if you make a request, and there's only one block confirmation, maybe you don't actually send it because you don't you're afraid of some type of blockchain reorganization or something, we're not going to worry too much about this. And we're actually just going to make this a
constant of three. So we're not even going to have this be per amortizable we're gonna have this one be a constant. So we'll say a you int 16 Private constant request, confirmations equals three, and we're using the capslock and underscores for our constant variables here. And now we'll grab request confirmations and stick it in right here. What's next callback gas limit callback gas limit is going to be the limit for how much gas to use for the callback request your contracts fulfill random wor
ds, this sets a limit for how much computation are fulfilled random words can be this is a good way to protect ourselves from spending way too much gas. If, for example, we accidentally code our contract in a way where fulfill random words is incredibly gas expensive. It'll block the random number from responding. We are going to make this parameter sizable because we want to change it depending on how we code our fulfill random word. So in our constructor, let's add one more, we'll add you int
32. Since the size of this is a un 32, callback, gas limit, and we'll save the sub top as a UNT 32, private, immutable, I underscore call back. Yes limit. And we'll save this. I call back gas limit equals call back Yes, limit. And then we'll take this, and we'll stick it here. All right, we got one more number of words, this is going to be how many random numbers that we want to get, we only want one. So we're gonna go back up to the top, we're going to create a you int 32. And we'll make this a
lso a private constant. Num words equals one, because we only want one random number. And then that'll be the last thing we need to add for our IVF coordinator dot request random words. Now this request random words function returns a request ID a un 256 Request ID a unique ID that defines who's requesting this and all this other information. If we want to save it, we can do u and 256. Request ID IVF coordinator requests random words. Now for now, we are going to emit an event with this request
ID. And we'll go over why we're going to do that a little bit later, create a new event at the top. And we're not going to follow the naming convention here. Because we're going to change the name of our functions a little bit, we're going to call this requested raffle winner. And we're going to take a un 256 indexed Request ID. Down here, we're gonna do omit requested raffle winner Request ID. And now we have a function that we can use to request a random winner using chain link VRF. Now again,
we're going to set this up so that the chain link keepers call this on an interval, but we'll do that in a little bit. For now, let's figure out what to do once we get that random number. Once we get that random number, we're going to want to pick a random winner from our array of players up here. So what do we do? Well, let's go in here. And let's pick a random winner using something called the module function. Now we're gonna get an array back of random words, or random numbers, if you will,
since we're only requesting one random word, this random words array is going to be of size one with one random word in it. Now this random word is a un 256. So this random word could be something like this. Well, obviously without the hyphens, but it could be something absolutely massive like that our players array is only going to be so big. So how do we get a random winner from this potentially massive random number, we can use something called the modulo function, the module operation, a mod
N yields, the remainder are after the division of an operand a by the blah, blah, blah, blah, blah. So what does this mean? Well, we can use the mod function to get a random number out of our players array. So let's say our players array or excuse me, our s players array is of size 10. And a random number is 200. So how do we pick a random person out of this players array, or, let's say our random number is 202. If we do 202, which is our random number, mod 10, we're gonna basically do 202 divi
ded by 10. But instead of having the decimals, we're just going to say, Okay, how many times is 10 evenly divide into 202. And what's the remainder, what doesn't divide evenly into 202? Well, 20 times 10 equals 200, with two leftover, so two doesn't evenly divide, or multiply into 200. So that means 202 mod 10 is going to equal to two. So that's how the module function works. And we can use that so we're always going to get a number between. So we're always going to get a number here between zer
o and nine, which works out perfectly because that which works out perfectly, because those are the indexes of the 10 people in our array. So let's use that here. We'll say a un 256 index of winner is going to be equal to random words, at index zero, because we're only getting one random word module, the S underscore players dot length. So this will give us the index of our random winner to get that address of the winner will do address payable, recent winner equals s players at this index of wi
nner so awesome. So now we'll have the address of the person that got this random number, the person's that's going to be our verifiably random winner. Now, it might be kind of cool to brag to people that you're the recent winner. So let's go ahead to the top and we'll create a new state variable for our most recent winner make this state variable in a new section called lottery variables. We'll say address private s underscore recent winner and it'll start out as nobody but as we get winners up
date it with s recent winner equals recent winner and we'll probably want people to know who this is winter is so down below, we can do function get recent winner, it's going to be a public view that's going to return that address. And then we'll just say return s underscore recent winner, since again, the recent winner is going to be a storage variable. So now that we have a recent winner, what else are we gonna do? Well, we're probably going to want to send them the money in this contract. So
we're going to do exactly what we did before with sending the money, we're going to do that bull success, comma, blank equals recent winner, call, I'm gonna say value, it's going to be address of this dot balance, we're going to send all the money in this contract, and we're going to pass it no data. And now we could say require, you know, success, whatever, we're going to be a little bit more gas efficient here. And we're just gonna say, if not success, then we're going to revert a new transfer
failed error. So we're gonna go to the top, or say, error name of the contract is raffle, underscore, underscore, transfer failed, like that, then go back down, and we can now do revert, raffle transfer failed like that. And now that we've picked a winner, right now, we don't have a way to actually keep track of the list of previous winners. So we're just going to omit an event. So there's always going to be that easily query double history of event winners. So we're going to create a new event
in the events section called the event winner picked. And this is going to be an address indexed winner. And we'll scroll down and we'll do MIT winner picked the address of the recent winner. This looks pretty good. This looks pretty good here. Now you'll notice our request ID as this little underscore here and saying, hey, it's an unused function parameter, since we don't use this, but we still need fulfill random words to take a request ID and a random words array. But we don't use Request ID
, we can just comment out just the request ID part like this, this tells our function, hey, yes, we know that you need a un 256. But we're not going to use the request ID. So we'll leave it in here. But we'll leave it blank. Now let's run a little compile here. We'll use yarn, hard hat, compile, or hh compile, we'll see if we're coding things correctly. And indeed, we don't see any errors. So perfect, we can continue. So we've added the chain link VRF, where we have a way to verifiably get a ran
dom winner. This is fantastic. Now let's update this contract so that not only can it pick a verifiable winner, but it can also do this all programmatically and automatically trigger picking a random winner based off of some time interval without us having to interact with it. And in a decentralized context. In order for us to automatically trigger smart contracts based off of some parameter be a time parameter, maybe the price of some asset is some number, maybe there's a certain amount of mone
y in the liquidity pool or really whatever trigger that you want, we can use chain link keepers. To do this. Steven fluid has done once again, an amazing introduction to chain the keepers. So we're going to follow along with another sub video section of Steven explaining chain link keeper sauce, he's going to be using the COVID test net, but be sure to use whatever test net is in the documentation. When you play with this and you try this. My name is Steven foon. Today, I want to show you how to
use the chain link keeper network in order to automate your contracts and give them access to off chain computation. Let's go ahead and dive in. So what we're going to look at today is we're going to start on the chain link documentation webpage. And if you just scroll down a little bit, you're going to find using chain link keepers. Now there's really two parts to building a chain link keeper up kept smart contract. So the first thing is you need to write a smart contract that's compatible by
implementing these two methods. And then second, you want to register that smart contract for upkeep with the channeling keeper network. So let's go ahead and do both of those things. So let's start off just by copying and deploying this sample code that we've got. With this one click to remix, what we're gonna see here is a very, very simple contract. That is just a simple counter. So we can see it's got a counter here. So it's got just a simple number. And then you're able to specify when you
create the contract and update interval, and then the contract is going to verify Hey, has enough time passed. And if it has, let's update the counter. And you're going to notice that chinley compatible or timekeeper network compatible contracts use two really important methods that are part of this keeper compatible interface. The first is check upkeep, and check upkeep is special because this is where the off chain computation happens. So this is a method that's not actually run on chain. This
is run off chain by a node from the channeling keeper network. And so what's really nice about this is that the gas used here isn't actually gas, it's on chains. This is just being run by a chain link node. And then what happens is if your check upkeep method returns, the upkeep is needed. Then it's going to go ahead and perform upkeep. On chain, so you can actually generate data off chain, and then pass that in. That's called the check data. And then that becomes the performed data that's pass
ed into perform upkeep. And so the PErforM upkeep method is where you're going to want to verify that things are correct. And that things actually should be modified and run on chain, and then actually make the state change. And so let's go ahead and compile this contract and deploy it to the COVID network. So let's go ahead and within remix, we can do this compilation. And we're going to compile and deploy directly to COVID. So the zookeeper network is currently as of the filming of this, avail
able on both COVID as well as the theory of main net. And let's go ahead and play the counter contract. And let's see what's not updating more than every 30 seconds. And so let's go ahead and deploy. So meta masks can ask for a little bit of payment, in order for me to deploy this contract to the COVID network. And it looks like that is live. So now what I'm going to do is I'm going to be able to take this keeper contract, and copy its address. And now we're going to register that contract for u
pkeep. So we're going to jump over to the application that powers the champion keeper network, there's a few different ways you can use, you can interact directly with the registry contract. But there's a very, very nice interface that lets you do this. So let's go ahead and register a new upkeep and it's giving me an error that says you need to connect your wallet. So let's go ahead and do that. So I'm going to just connect wallet here, and I'm gonna give it access to my account. And then from
there, we should actually be able to register. So I'm going to use an email address here. I'll give my contract a simple name. I'll paste in that address from the deployed contract, and then I'll give it a gas limit. And then check data is this special thing where you can actually register multiple upkeeps On the same contract in passing data to specify how you want checkup keep to be run of, we're just going to ignore that that is an optional one. And then we'll give it a starting balance of ar
ound 10 link, it's gonna go ahead and use Metamask again to register that transaction on the network. And once it's confirmed, my upkeep should be registered with the network and funded with 10 Link To kick things off. Alright, if we go ahead and view the upkeep, we can see it's registered. And as soon as the next round of the keeper nodes executes, which should be roughly about every block, we should see that the check upkeep method is going to return that hey, upkeep is actually needed because
the timestamp is more than 30 seconds ago. And then we should go ahead and perform upkeep. So as soon as I take a look at this in remix, I can actually make this bigger here, we're going to be able to see from the methods of the contract, if we check the counter, it's going to start at zero. And as soon as that 30 seconds has passed, we'll be able to hit the counter again, we'll see that the channeling keeper network has performed upkeep on my contract. Alright, we just refresh and we see the b
alance of the upkeep has been decreased by about point 01 link. And we should also see within our contract that our counter has now updated via proof that perform upkeep method call. And now our counter is at one showing us that our contract is being approved by the chainlink keeper network. And everything is working exactly as we expect. So as you can see, it is very, very easy to create a contract that is compatible with the keeper network. And it's very easy to register that upkeep and start
seeing that your contract automation and option computation are working flawlessly. Now that we've learned a little bit more about how chainlink keepers work if you want to take some time to go through the documentation and open up way down below this open and remix button. So you can actually work with one of these and see these in action for yourself on a test net, feel free to do so we're gonna be using a setup very similar to this keepers counter setup in the chain link documentation. So now
let's update our code so that this request random numbers automatically happens using chain link keepers. And if we look at the example contract can actually read more about what's really important for this to work. And we need a check upkeep and a perform upkeep function in our code. So instead of request random winner, this is going to be the PErforM upkeep that we're going to change. But first let's make this check upkeep checkup keep function is basically going to be checking to see is it t
ime for us to get a random number to update the recent winner and to send them all the funds. So let's go ahead and make that function. I'm going to add some notes here, just so that it's clear what's going on. And maybe I'll even do natspec To tell developers what's going on with this function. So we're going to create this function check upkeep. And if we look at what this needs, it needs to be external override external override. And if we see this override keyword, this means that okay, ther
e's probably a perform upkeep somewhere else. And if we scroll to the top, and we're going to import this keeper compatible interface, so that we make sure that we implement both check upkeep and perform upkeep in our code here. If you want you can just import keeper compatible in here or just the keeper compatible interface in our code. We're going to do import at chain link slash contracts slash SRC slash V 0.8 point two interfaces slash keeper compatible interface that soul and now we're just
gonna say contract raffle is Veera of consumer base V two and keeper compatible interface and this keeper compatible interface inheritance just make sure that we add checkup keep and perform upkeep, which we're going to add in a little bit. And if we look back at the docs we can see checkup keep takes a bytes called Data check data as an input parameter. So we'll do bytes called data. Check data as a parameter. Now this check upkeep bytes call data allows us to specify really anything that we w
ant when we call this check upkeep function. Having this check data be of type bytes means that we can even specify this to call other functions, there's a lot of advanced things you can do by just having an input parameter as type of bytes for us though, we're going to keep it a little bit simple. And we're actually not going to use this check data piece. So similar to how below we're not using Request ID, we can just comment it out. However, we still need to make sure that this parameter is ty
pe of bytes called data. Now anyways, let's go ahead and annotate this check upkeep function, we'll say this is the function that the chain link keeper nodes call they look for the to return true. Look back at the documentation, we can see that this check upkeep returns both and upkeep needed and to perform data, which again, we're going to ignore this upkeep needed is going to be true or false. If it's true, that means it's time to get a new random number following should be true in order to re
turn true. So in order for it to be time to request a random winner, what should happen, our time interval should have passed, which we haven't defined yet. But we will lottery should have at least one player and have some eath. And then our subscription is funded with Link similar to how with channeling Vir f your subscription needs to be funded with Link, the same thing needs to happen for check upkeep and keepers to run your subscription needs to be funded with link. Now we're going to add on
e more additional piece here, we're going to say for the lottery should be in an open state, something that we want to avoid when we're waiting for a random number to return. And when we've requested a random winner. We're technically in this weird limbo state where we're waiting for a random number to be returned. And we really shouldn't allow any new players to join. So what we actually want to do is create some state variable telling us whether the lottery is open or not. And while we're wait
ing for our random number to get back, we'll be in a closed or a calculating state. Now what we could do at the top of our contract, we can just say Boolean, private, s underscore is open. And we can just set this to true if we're open otherwise false. Well, what if we have a ton of different states? What if we want it to be like pending, open, closed, calculating, etc? What do we have a ton of different states? Well, we could make this a U and 256. Private s underscore state. And we could just
keep track of the state having like zero b pending a one reopen to be closed, three, be calculating, etc. But this can be a little tricky to keep track of. So a better way to actually keep track of all this in our code is to use an enum enums, can be used to create custom types with a finite set of constant values. So we can create, for example, a state created locked inactive, and it's basically a new type for a smart contract for us, we're going to create a new type. And if we go back to the l
ayout of variables, and our smart contract types should actually be first thing in our contract. So we're going to create an E new called raffle state. And for now, and we're just going to have it be open, we're just gonna have to be open or calculating. Now when we create an enum like this, we're kind of secretly creating a un 256, where zero equals open, and one equals calculating. However, this is much more explicit that we know what each one of these numbers actually means. Now that we've cr
eated this new type called raffle state, we can create a new lottery state variable of type raffle state. So the exact same way we declare any other variable, we'll name its type, which is going to be raffle state. And this is going to be a storage variable. So we'll go ahead and do private s underscore raffle state in our constructor, right when we launched this contract, we should open up this raffle. So we'll say s, raffle state equals and we could use a un 256. Wrapped in type raffle state l
ike so. Or we can be more explicit and say raffle state DOT open. Now we know that the raffle state is in an open state and we only want checkup keep to work is if the lottery is actually open. Additionally, we probably only want people to be able to enter if the law battery's open. So let's go ahead and create another if statement and revert if the lottery isn't open. So we can say if s underscore raffle state does not equal raffle state DOT open, then we're going to revert with a new error, we
're going to create raffle underscore underscore, not open. And of course, at the top will create error, raffle not open. Now additionally, let's go down when we're requesting a random word. Let's update the state to be calculating so other people can't jump in here. So right above our VRF coordinator dot request, random words will do s underscore raffle state equals raffle state DOT calculating so that nobody can enter our lottery and nobody can trigger a new update. And then once we fulfill af
ter we pick our winner, we'll say s raffle state equals raffle state DOT open again. Something else that we forgot to do was after we pick a winner from s players, we need to reset our players array. So let's add that in here as well as players equals new address payable. array of size zero. So we'll reset the raffle state. And we'll reset our players array. Alright, great. So now that we've learned about enum, let's add it to our checkup keep here, we're going to check these four things. And if
they all pass checkup keys will be true and will trigger the chain the keepers to request a new random winner. So first, we'll say bool is open. It's going to be equal to raffle state. That open equals equals s underscore raffle state. So you can think of that as this boolean is open is going to be true if raffle state is in an open state, and it will be false if raffle state is in any other state. So great. We haven't is open Boolean that we can check later on. What else do we need? Well, we n
eed to check to make sure our time interval is past well, we don't have a time interval yet. So let's create a time interval. In order to check the time we can use another one a solidity is globally available variables with block dot timestamp block that timestamp returns the current timestamp of the blockchain to get the current timestamp, we're gonna need block dot timestamp. But to get if enough time has passed, we're going to need to get the current block dot timestamp minus the last block t
imestamp, which we don't have yet. Let's go ahead and create a state variable to keep track of the previous block timestamp. So this is going to be a new state variable that we're going to make. I'm gonna say u and 256. Private s underscore last timestamp. And right when we deploy this contract, we'll update this with the current timestamp s last timestamp equals block dot timestamp. Alright, awesome. Now we have a last block timestamp. But we're going to need to check that the difference betwee
n the current timestamp and the last timestamp is greater than some interval. So we also need to create an interval. And this is going to be some interval, this is going to be some number in seconds of how long we want to wait between lottery runs. So let's go ahead and add this to our constructor as well. And do a comma here. And we'll do u and 256. Interval. And we're going to create another global variable u and 256 Private s underscore interval. And in our constructor and we'll say s interva
l equals interval. Now interval isn't going to change after we set it. So instead of making a storage variable, let's make it an immutable variable to save some gas. Okay, perfect. Now that we have all this, I'm actually create a boolean to check to see if enough time has passed. So we'll say Boolean time passed equals the current block that timestamp minus s underscore last timestamp. And we should check to see that this is actually greater than I underscore interval. So we have a Boolean check
to see if we're open. It'll be true if we're open and we'll have a boolean to see if enough time has passed. This will be true if enough time has passed. What else should we check? While we should check to see if we have enough players. So we'll do Boolean has players equals and we'll check to see if s underscore players dot length is greater than zero. If s players dot length is greater than zero as players will be true, otherwise it'll be false. And we'll also see if we have a balance so we'l
l do Boolean has balance equals address. This dot balance is greater than zero. Then finally, we're going to take all these booleans and turn them into the return variable that we're looking for. We're gonna say Boolean up keep needed. Equals is open and time passed. And as players and as balance, like that, so all these combined is gonna be this Boolean upkeep needed. And if this returns true, it's time to request a new random number and it's time to end the lottery. If this is false, it's not
time yet, it's not time to end the lottery up. Now again, if we go to the chainlink, documentation upkeep needed, actually needs to return that Boolean upkeep needed and some bytes memory perform data. So we need to update we need to update our function here. And say returns full upkeep needed, comma, bytes memory, perform data star slash. And since we've initialized Boolean up, keep needed up here, we don't need to say what type of upkeep needed is down here. Since this will automatically get r
eturned performed data is something that we can use. If we want to have checkup, keep do some other stuff. Depending on how this checkup keep went. We don't really need it to do anything else. So we can just leave it as such. Right. So now we have a check upkeep, we have a way to check to see if it's time to trigger picking our random winner of our lottery or our raffle. Now that we learned how to actually do this trigger, let's write the function that gets executed after this returns true. This
is going to be our perform upkeep function, which we can see an example again in the chainlink documentation. Now when it's time to pick a random winner, actually, what we're going to do is just we're just going to call this request random winner function. So instead of having this extra function, let's just transform our request random winner function into this perform upkeep. Since once check upkeep returns true, the chain link nodes will automatically call this perform upkeep function. So in
function request random winner, let's rename this to perform upkeep. And we'll have it take the input parameter bytes called Data perform data bytes, called data, perform data. In our checkup, keep we had to perform data, we would automatically pass it to our performance keep, we're not going to pass anything to perform upkeep, we can leave it commented out like this. Since perform upkeep is actually identified in the keeper compatible interface, this is now going to have to override that funct
ion. Now we want to do a little bit of validation before we continue here. Because right now anybody can call our perform upkeep function. So we want to make sure that it only gets called when checkup keep is true. An easy way for us to do that is to actually call our own checkup, keep function. Now right now, checkup keep it's an external. So we actually can't call our own checkup keep function. So let's change it to public so that even our own smart contracts can call this checkup keep functio
n. Now that we've made it public in perform upkeep, we can call checkup, keep passing nothing, and then return the upkeep needed and perform data which we don't really care about. So we'll get we'll get that ball up keep needed. And then we don't care about perform data. So we'll leave that blank equals check up keep. And we'll pass it a blank called data. Now, we want to make sure that this is true in order to keep going with the function. So we could write a require here, but we're going to do
if not up keep needed, then we're going to revert with a new error that we create raffle. upkeep not needed. And we're going to pass some variables to this error so that whoever was running into this bug can hopefully see why they're getting this error. So we'll pass the balance of this contract just in case there's no ether in here. We'll add the players dot length, just in case there's no players. And we'll add a un 256 s underscore raffle state. Make sure that the raffles actually open. And
then of course, we'll need to create this air at the top air, raffle upkeep not needed, which is going to take a un 256 current balance un 256 non players and you went to fit six raffle state. Our code is starting to look really professional. This is awesome. Now something that we forgot to do back in the fulfill random words because we actually forgot to reset timestamp every time a winner is picked. We want to reset the timestamp as well so that we can wait another interval and let people part
icipate in the lottery for that interval. So we'll scroll down into fulfill random words. And right after we reset players will also reset the timestamp. Okay great and I think we're just about done here. Let's add a little bit of natspec to make this look even more professional and and give people who are reading our contract even more information. So let's add title here at title and we'll say a sample raffle contract will say an author is going to be me Patrick Collins or you can put your own
name there as well at notice. This contract is for creating and untampered orrible decentralized smart contract. And then we'll do add Dev, this implements chain link VRF v two, and chain link keepers. Alright, awesome. We've got our type declarations, we've got our state variables, we've got lottery variables, which are still state variables, we've got our events. Now it's time for our functions. Afterwards, we've done a little bit of natspec, at least on our check upkeep. If you want to add s
ome more natspec on things like enter, raffle, perform upkeep, etc, you can absolutely do so. And then down at the bottom, we have our views slash pure getter functions. Let's see, do we want any other getter functions here? Well, we probably want to give people the chance to get a raffle state. So we'll do function, get raffle state, this will be a public, you returns a raffle state. We'll say return s underscore raffle state, we probably want to give people the chance to get the number of word
s. And this is going to be a little bit interesting here running. So if we do function, get num words, public view returns, you went to the six return num words, you'll see something interesting happened here. We pull up our compiler and run hh compile. Hopefully everything works here. Oh, and everything doesn't work because I didn't import this correctly. Let's fix that. Let's try again. Oh, there's a couple things I missed. Let's fix es players. This is why it's good to compile as you code as
players dot length. Let's try again. And I spelt interval wrong. I underscore inter vol strike to compile again, see how many more spelling mistakes I made. And there it is. I underscore in error go to paste that and we do get another error here. Invalid type for argument in a function call invalid implicit conversion from literal string to bytes called data requested. Since we're passing this empty string here. And checkup keep needs a call data called data actually doesn't work with strings. S
o we need to make this bytes memory instead. And our compiler is now happy with us. And I spell it the timestamp wrong. That's a lowercase s so and you might see some squiggles here on Check upkeep, we could make this a view function since we're not actually modifying any state. But I want to keep it public for reasons I'll show you a little bit later. But finally we get the the yellow squiggly that I was looking for here. And if we run hh compile, we should see a warning in our compiler as well
. Okay, so we see all those yellow squigglies here. Unnamed return variable can remain unassigned. We need this bytes memory in here because that's what the keepers are looking for. Morning function state mutability can be restricted to view for our function checkup key. You can make a view if you want, but I'm going to keep it public for reasons I'll show you a little bit later. And finally, function state mutability can be restricted to pure this is what I wanted to show you since num words is
actually in the bytecode, since it's a constant variable technically isn't reading from storage, and therefore this can be a pure function. Returning num words doesn't actually read in storage, it literally will go and read the number one. So doing get num words in solidity with num words being a constant variable, it's going to literally be the exact same as saying get one and we would return one here, we might also want to get the number of players. So we'll create a function get number of pl
ayers. And this will be a public view, returns a un 256. Turn s underscore players dot length. We're also probably going to want the latest timestamp. So we'll do function get latest timestamp. public view returns you in 256. And we're just going to return s underscore last timestamp. And maybe we'll want to do request confirmation. So we'll do function GET request confirmations. Public pure since request confirmations is also a constant function returns you went to you went to 56 Turn request c
onfirmations. All right, we've got some wonderful getters here. Some views slash pure functions, we have a way to get a random number we have a way in a decentralized context. Automatic automatically execute. picking a random winner we have a way for people to enter our raffle to enter this lottery. And we have a bullet proof way to solve creating a truly fair decentralized lottery. Oh my goodness. Let's do one more compile for good measure H H compile. And these are just warnings. So we're good
to go here. Our code is compiling successfully. Like I said Normally, this definitely isn't going to be the way that you're going to write your smart contracts, it's almost impossible to write a full smart contract without making any mistakes. And without flipping back and forth between documentation, I have already written this contract many times myself, and I still made a whole bunch of mistakes. So it is totally reasonable and totally rational for anybody and everybody to make mistakes goin
g through this. And to use resources and to write tests along the way. Now that we have our raffle dot Seoul created, it's time to add everything else. So we're going to come over here, we're gonna create a new folder, and add our deploy folder per usual. And we're going to do exactly what we've already done a couple of times, we're going to create some scripts to deploy our raffle contract. Now with our raffle contract, there's a couple of things in here that we want to make note of first thing
is that our constructor right now is absolutely massive. There are a ton of parameters in here that we need to account for. Let's take a look at our constructors and see if there's any contracts that we're already interacting with. Okay, VRF, coordinator v2. This is a contract address, entrance fee, no gasline, no subscription ID no callback, guestimate No, and interval. No. So knowing that this is an address should be a tip that Ah, okay, we're probably going to need to deploy some mocks. For
this, since we're going to need to interact with a VRF coordinator contract that's outside of our project. But let's go ahead and start working on our raffle deployment script first, and we know we're going to have to deploy some mocks. So we'll just keep that in mind. So let's create a new file. Oh, one, deploy raffle.js. And let's get started deploying our raffle contract. Now, this is going to look really similar to what we've done before. And we're going to do it again here. If you want to u
se your previous deploy scripts as a reference, I absolutely recommend you do so. But let's get started with module that exports equals an async function. That's going to take get named accounts and deployments. As input parameters, then we're going to do const. Deploy log equals deployments, then we're gonna say const, Deployer, equals await, get named accounts. Let's go to our config and update module that exports to to have this I'm just going to copy paste, so that employer is going to be de
faulted to account zero and player is going to be defaulted to account one, if you want to go ahead and write this out, feel free to pause and write out your name accounts. Right now, there's gonna be a lot of boilerplate in our heart hat.config.js. So feel free to have the GitHub repo for this lesson up with you or your previous scripts that you've already written as a reference named accounts Deployer. And we're also going to have a player named account so that we can separate different users
or different players who are interacting with our contracts. But for now, we're gonna grab our Deployer. And we're gonna get started. Now similar to last time, we would just do const, raffle equals await ploy, raffle, comma, and then add all of our stuff in here, right? So this would be from Deployer. args, we're going to have a ton of args. So we're going to come back to this. And then log is going to be true. And then we're going to have wait confirmations, there's a little bit more boilerplat
e we need to work with here in our Hardhead config, we don't have a network here. So let's add our network information. So we can get those block confirmations will be specific in here, as well. And we'll say default network is going to be hard hat. And then we'll say networks, and we'll add our network information that's going to be working with heart hub, which has a chain ID of 31337 miles, we'll put that in here as well. And block confirmations were just set to one lot this column here, we'r
e also gonna be running some staging tests on the Rinkeby network. So we'll add rink B in here with a chain ID of four, block confirmations of six, and we need to add a URL and then also some accounts for our URL. We've done this 100 times. We'll do const. rinky dink could be RPC URL equals process study and v dot rake, the RPC URL, that's private key, blah, blah, blah, we're going to add all these same variables from our last projects. So I'm going to ask you to pause here and just copy paste a
ll those variables from our last project. Boom, like so since running rink, prpc, URL, private key corn market cap and ether scan, we're also going to want to make sure you folder, excuse me, new file, dot env. And we're going to drop all of our information in here our rink, prpc, URL, private key, ether scan API key, and then our coin market cap API key as well. Now that we have our private key or ring prpc URL down in URL, B RPC URL, and for accounts, we're just going to add that single privat
e key. Now for weight confirmations is going to equal For network config dot block con formations, or one, we're gonna have to import network from Hardhead, which looks like my VS code automatically did for me. Thanks VS code. So this is how we're going to deploy a raffle. Obviously, we have a ton of arguments that we need to account for. So let's get to it. Let's look at our raffle constructor to see what we need to get. Okay, well, the first thing that we need to get via of coordinator v2, we'
re gonna use the same strategy we used in our Funmi project with using mocks, if we're on a development chain, and using the actual contract address if we're on a test net, or a live network, so let's get to it. So let's go ahead, recreate that helper, hard hat config dot j s and create that const. Network. Config, say it equals for hard hat, we're going to use a mock. So we don't need to put that in here for now. But for rink B, let's go ahead, but a foreign here, so the name is going to be Rin
keby. And we're going to need to go to the chain link documentation, the VRF contracts, and we're going to need to grab the RF coordinator for the Rinkeby. Test net, we're going to grab this address here, plop it in here, we'll say V RF core did an eight tour v two, bam, right like that. So back in our deploy raffle, we're gonna have to pick whether or not to use the V RF coordinator v two in the network config or some mock that we deployed, which of course, leads us to us having to deploy a moc
k, let's create the new file 00. Deploy marks.js. So same thing module that exports equals async function where it's taking, get named accounts, and deployments, as its input variables from the heart at runtime environment, or do const deploy COMM A log equals deployments. And then const, Deployer equals await, get named accounts, Excel, and then we're going to grab the chain ID as well as we're going to only wants to deploy this on a development chain. So we'll do const chain ID equals network
dot config dot chain ID. Now we're going to only want to deploy mocks, if we're on a development chain. So once again, we're going to go to our helper config, we're going to add those development chains in here. We'll say const, development chains equals hard hat, and localhost. And then we're gonna want to export both of these. So module, dot exports, equals network config, and development chance. Now in our deploy mocks, we're gonna want to grab those are saying const development chains, equal
s require dot dot slash helper helper hardhat config. Now we can check to see if development chains dot includes the network dot name that we're currently on. If we're in a development chain, we're gonna go ahead and log local network, the protected, deploying box. And now we'll have to deploy a mock VRF coordinator, where do we get a mock VRF to coordinator Well, let's go ahead and create one of those. We go to the chainlink. GitHub again, we go to contracts. So C 0.8, actually have a mocks fol
der with VF coordinator v2 Mach dot Sol, and we're just going to use this as our mock. So in our contracts folder, we're gonna create a new file called test new file called V RF core, in a core, the two mock dot Sol, and we're just going to import this mock and have it be our mock. So we'll do spdx. We'll do pragma, solidity, carrot zero, point 8.0, or seven or whatever we want to do, we'll do import at chainlink slash contracts slash SRC slash v 0.8. Slash, mocks, slash VRF. Pour did a tour B t
o mock that soul. And we'll just check to see if it compiles with Hardhead compile, and it looks like it's compiling as well. Awesome. So now that we have our mock contract, we can actually go ahead and deploy it. So we'll do a weight loi, the RF core de ne Tor V to Mach comma, and then we'll give it our parameters in here. We'll say from Deployer. Log is going to be true, and then we're going to do our arguments. Now, what are the arguments of this VRF coordinator, v2 Mk. Well, if we open the V
RF coordinator v2 Mock, right in our VS code, or on GitHub, we can actually see We will roll over to the constructor that it takes two things. It takes a base fee and a gas price link. What are these first one? Well, the first one is this const base fee. If we go back to the documentation, we can see that there's this premium section of 0.25 Link rink B, this means that for each request, there's a base fee of 0.25 link for every request. So anytime we want to request a random number on Rinckey,
it's going to cost us 0.25. Link, or you can think of it as 0.25 Oracle gas to make this request. So back in our deploy mocks, we can say base V equals, we could resemble Rinckey here and do 25, blah, blah, blah, or we could do ethers dot utils dot parse eath, of 0.25. And I'll even put a little comment here, say 0.25 is the premium, it costs 0.25 Link per request. And remember, the reason that this cost 0.25 Link per request versus the price feeds didn't cost anything is because the price feeds
. If we look back at a chain that link, each one of these price feeds is being sponsored by a group of protocols who are paying for all these requests already, since there isn't a sponsor for this, we are the only ones requesting the randomness, we get to be the ones to actually sponsor getting this random number, then the second thing here is going to be the gas price link. So let's create another const here to const. gas price link. But what this is, is actually a calculated value is a calcula
ted value based on the gas price of the chain. Here's an example if we were to request a random number on Aetherium, and the eath price skyrocketed up to like to like a billion dollars, gas would be incredibly, incredibly expensive. Now when chain link nodes respond chain link nodes pay the gas fees, who give us randomness, and do external execution, the chain link nodes are actually the ones that pay the gas when returning randomness or executing an upkeep or etc. If we go to our raffle dot sou
l, and scroll down to perform upkeep, or fulfill random words, it's actually the chain link nodes that are calling these two functions and paying the gas for it, they get paid in Oracle gas to offset those costs. But if the price of eath, or any native blockchain skyrocketed the chain that nodes itself to pay the gas fee. So the chain link nodes have a calculated price have a calculated variable called the gas price per link, which fluctuates based off the price of the actual chain, so that they
never go bankrupt. Basically, the price of a request changes based off the price of gas for that blockchain, you can kind of think of this as the link per gas, if you will, for now we can kind of just set it to whatever we want. And we'll just set it to one e nine, which is going to be equivalent to 1123456789. So now that we have the base fee, and the gas price link, we'll grab this base fee, we'll have these be the arguments for our VR chord, enter V to mock, so we'll say and actually we can
delete that will say const, args equals base fee, and gas price link, then we can take this args variable and just plop it in here. Now we can do log mocks deployed, then we can do log that a little line like this to let people know that this deploy script is done, then we'll just do a module that exports dot tags equals all and mocks. So now that we have a view of coordinator v2 Mock deployed, we'll come back over to our raffle and make some code around it. Similar to what we just did with our
deploy mocks. We can say if development chains that includes network dot name, we'll do some stuff. And we need to import development chains from our helper Hardhead config. And we need to import network from hard hat. My VS code automatically added them Wow, thanks VS code. Let's even just do const args and make this variable down here. Stick it in args. Our first argument is going to need to be this Vera fi to coordinator so let's make a variable we'll say let VRF core need torby to address an
d if we're on a development chain, we're going to grab that mock contract. So we'll say const PRF, Cor de ATAR V to mock equals await ethers dot get contract, the RF cord the cord to NATO Tor v two MK, and then we can set the RF coordinator v two address equals VRF core denater V two mach dot address. Cool. We have that address here. Else if we're not on a local network, the VRF v2 coordinator address is simply going to be derived from our network config. So let's import the network config as we
ll from our helper Hardhead config and we'll say else VRF coordinator v2 address equals network config of our chain ID. Let's which actually sorry, we do need the chain ID cons chain ID equals network dot config dot chain ID, chain ID of VR coordinator V to chain ID. You're a coordinator v2. Alright, perfect. We've got the setup to work with our VRF coordinator v2 address. What else do we need from our raffle? Well, we need an entrance fee, we probably want to change the entrance fee depending o
n what chain we're on, we're on a more expensive chain, we might want to make this higher than others. So let's go ahead back to our helper Hardhead config and make an entrance fee based off of the blockchain, so for NP, maybe we want to make it 0.01 eath. So we could say ethers dot utils, parse ether of 0.01. And once again, thank you VS code for automatically dropping that in for me. And we're also going to want an entrance fee for our heart app, we can also set a default in here, but let's ju
st be a little more explicit. So we'll say 31337. The name of this is Art app, we don't need to give it a veneer of coordinator v2 address because we're going to deploy a mock. But we do want an entrance fee. And let's just give it the exact same entrance fee here. So we'll say ethers dot utils dot parse ether 0.01 E. Alright, great. So on our deploy here, we can just say const entrance fee equals network config. Chain ID of entrance fee. Let's start populating our arcs here. So the first one is
going to be your Fe two coordinator address. Next one is going to be our entrance fee. Got it? Got it. Now we need our gas lane. On Rigby and other networks, there are different gas lanes that we can choose from, let's grab the only gas Lane from Rinckey, the 30, gray key hash, let's drop this, of course into our network config as gasoline, pop it in here, we're hard hat, our mock actually doesn't care what gas line we're working on, because we're going to be mocking the gasoline anyways. So we
can just say gas lane, we can just go ahead and use the same one or really anything here, it doesn't really matter. Now here we'll say const, gasoline equals network config. Chain ID, gasoline, and we'll grab the gas lane. And we'll stick it into our argument array, we've got this one, we've got this one, we've got this one. Now it's time for the subscription ID. Now if you haven't run through docstoc chain link for the chain link VRF, I highly recommend you do so so that you can understand wha
t this subscription ID is we know that we can actually make a subscription ID using that front end using that website VRF dot chain dot link, which is great and all but what if we're on all local chains, we can get a subscription ID no problem in here. But it's a little bit harder on a local network. Now I'm actually going to teach you how to create and fund subscription it is completely programmatically. So you don't even need to use the UI if you don't want to. However, for the purpose of this
course, we're still going to use the user interface, we're still going to use that website for us to get our own subscription IDs. But you could 100% automate the process of creating a subscription ID and funding a subscription ID. Because when you create and fund subscription IDs, you're just calling create subscription and fund subscription on that smart contract. So on our development chain, we have our V RF coordinator v2 Mock, and what we're going to do and on our development chain, we're
going to create that subscription. So we're gonna say const, transaction, response equals await VRF coordinator v2 Mock dot create sub scription. And then we'll run const transaction receipt equals weight trends action response, dot Wait, wait one block confirmation. And inside this transaction receipt, there's actually an event that's emitted with our subscription that we can get this is another place where emitting events is incredibly helpful. So in fact, if we open back up a Vera v2 coordina
tor mark, and we look for create subscription, we see we emit subscription created with the subscription ID, we can actually get this event emitted from our transaction receipt. Now to assign it, let's go ahead and create a sub subscription ID up here. And then we'll say subscription ID equals transaction receipt that events of zero dot args dot sub ID. And again, be sure to watch that events video if you want to learn more about how to work with events in hardware. Now that we have a subscripti
on, we need to fund the subscription on a real network, you'd need the link token to actually fund the subscription. The current iteration of the mock allows you to fund a subscription without the link token. So what we can do is we can just run a wait your F corps inator Mark, if coordinator B to Mach dot fund subscription, and we'll give it the subscription ID and we'll need to do some fundamental this, we can just create some variable, we'll say const VRF, subscription fund amount equals ethe
rs dot utils, dot parse ether, of, we'll say 30 VRF subscription, fundament. We'll just paste that down here. We could do this as well for a real test net or live networks. But just so that we become familiar with the user interface, we're not going to do a test net programmatically. And for a test net, we're just going to use exactly what we've been doing so far. Or we can put a subscription ID and our helper config. So we'll say subscription ID, we'll put something in here right now, we'll jus
t leave it as zero. But later on, when we actually create a subscription, we'll update our subscription ID. And so we'll say subscription ID equals network config. Change ID of subscription ID. Perfect. Now we can add this to our arguments array. What else do we need subscription ID, we need a callback gas limit or callback, gas limit is going to vary network to network. So once again, we're gonna go into our helper configure callback gas limit. And for us, we'll set a pretty high limit of 500,0
00 gas. So we'll say call a gas limit of 5.123 500,000. Gas. And for hard hat, we'll do the same thing. So we can say const, callback, gas limit equals network config, chain ID, callback, gas limit, grab this, put it into our argument array. What else do we need? All we need now is the interval. So we can change this network to network as well. Rigby will say, interval will ever just be 30 seconds for both hard hat and for Rigby. So we'll do the same thing here. Say const. Interval equals networ
k config. Chain ID, interval, and we'll grab this, pop it in the end of our array. All right, awesome. Now we have an argument array and drop it right in here and perfect. Everything in our constructor for our raffle contract. Great. This is looking fantastic. We've got wait confirmations we got logging arguments Deployer. Okay, well, what next? Well, let's go ahead and add that verification piece. So once again, create a new folder utils, new file verify.js. We can either copy paste this from o
ur last project, or we can grab this from the GitHub repo associated with this course, once we have our verify script in here, we're going to import it by saying const. Verify equals require dot dot slash helper Hardhead config. And then we can add that same bit of code down here to verify our contract, we'll say if we're not on a development chain. And we have process studying v dot ether scan API key, then we're going to log verifying dot dot and then await verify raffle dot address and the ar
cs. Now we'll just do a log of a whole bunch of hyphens say that this script is done module dot exports dot tags equals say this will be all and raffle. All right, so let's test this out. We'll do hardhat deploy, or yarn, hard hat deploy and see if this script works correctly. Looks like we ran into an error network config not defined. So let's spell this right. Network config. There we go. And that looks much better. Let's try this again. It looks like our deploy scripts are working well. local
networks protected, deploying mocks deployed VRF coordinator v2 Mock mocks deployed and then we went ahead and deployed our raffle. Awesome, this is massive. Now we're not going to test the deploying this to a test net quite yet, because well, we don't have any unit tests yet. We need to write unit tests before we want to ever test running this on a test net. So we have our deploy script, we have our contracts, that means it's time for us to write some tests. We'll come over here we'll create a
new folder called test. And for now, we'll just make our unit tests. So unit tests, and in here we create a new file called raffle.test.js. And let's write some unit tests. Now for these unit tests, we are going to be a little bit verbose here, we're going to make our coverage really, really good here. It's not gonna be perfect, but this is going to be pretty verbose. So I'm gonna go pretty quickly here. So you can feel free to pause, slow me down, speed me up whatever you need to learn this se
ction. It is really good muscle memory to go through writing these tests and understand what you should be thinking about when you're writing these tests. So feel free to speed up the parts You already know and slow down the new parts. Because we are going to go over some new information here. writing tests may seem like a tedious process. But I promise as you get better at writing these tests, you'll realize that these are the things that you can rely on when stuff doesn't work. And when you're
not sure how to code, something, getting this muscle memory down, writing these tests is going to make you a fantastic engineer. So let's go through and we'll write some of these verbose tests here to try to make this really good and have this have really good coverage. And if you want to go back later on, and see if you can give it even more coverage, and even better tests, please feel free to do so. But let's get started. Let's write some tests. So we're going to start out pretty much the sam
e way we've been starting everything out, we're going to grab our development chains, so that we only run our unit tests on a development chain. So we'll do const development chains, equals require dot dot slash dot dot slash helper, RD, hard hat config, and then we'll say not development chains, that includes network dot name, and describe that skip. Otherwise, we'll do describe, so this first describe is going to be our raffle unit tests. And this is going to be an async. function. So raffle u
nit tests so that it comes on the next line, it looks a little bit better. Alright, great. Now, what are some of the main things that we're going to need to deploy? Well, we're gonna need to deploy a raffle, we're probably going to want a VRF core to a tour be to mock graded before each, that's going to be an async function, where we go ahead and we get these will say const. Employer equals await, get named accounts. So we're gonna need to import get named accounts or require get name accounts f
rom hard hat, then we're going to want to deploy these using our fixtures. So we can say await deployments. And then we're going to import deployments as well from hardhat dot fixture, and we're going to call all, we're going to deploy everything. And again, if we look at our one, our raffle has the alt tag, and our Oh, our mocks also have the alt tag, okay, perfect. Once we deploy everything, we can say raffle equals await ethers dot get to contract. And we got to import ethers from hard hat, l
ike so. And we'll say it will get the raffle contract and we'll connect it to our Deployer. And then we're going to do the same thing with VRF coordinator v2 Mock equals await ethers dot get contract, the RF coordinator, B to MK connect this to deployer as well. Alright, great, our first set of tests describe, they're going to be the constructor. And this is going to be an async function. And let's do this. Let's create an IT initial initializes the raffle correctly, this is going to be an async
function. Now I just want to make a note, because ideally, we make our tests have just one assert, or it just keep that in mind is that ideally, we want to have just one assert for it. But we're going to have a bunch because like I said, we're being a little bit loose here. So we want to just make sure that our raffle is initialized correctly. So we'll say const raffle state, and we'll get that raffle state because we want to make sure that we start in an open raffle state. So we'll say const,
raffle state equals await raffle dot get raffle state. And then we want to say assert dot equal ope and then we need to import assert from Chai. So assert equals require Chai assert dot equal raffle state.to string because again, raffle state is going to be a big number. And even though a raffle state is of type raffle state, it'll return a zero if it's open and a one if it's calculating. So this gets transformed just into a un 256. When we call it like this, a raffle state variable here will be
a big number. So we want to just to string a file. So assert dot equal raffle state DOT two string zero. We'll also make sure our interval gets set correctly. So we'll do const interval equals await raffle dot get interval. And I don't know if we have one of those it's actually C inter ball see if we have one of those. We don't have a good interval let's go ahead and add again interval function so we'll do function get in trouble. We have public view returns you went to six return I underscore
interval will have good interval will say raffle dot get interval and will also say assert dot equal interval.to string. It should equal one Ever is in our helper config, right? Because we're using the interval and helper config. So we say interval.to string should equal. So we'll import that as well. Network config. And we'll say the interval should equal network config. Of let's also make, get our chain ID up here, chain ID, say const. Chain ID equals network dot config, a chain ID, network co
nfig of the chain ID of interval. Alright, cool. So let's test this so far, HH test or yarn, hard hat test. And cool looks like it passed. And we have our little gas output here. Awesome. Let's go to our Hardhead config, just so that it doesn't always print out at gas, but there for now. So I'm going to copy paste the gas reporter section from our last project, like so. And we're going to have enabled gas be false for now. So now if we run a Hardhead test, again, we shouldn't have that gas bid p
rinted out, we should just see the tests and perfect, that's what we see. And our constructor test passes. Yay, what's next, got our constructor. And we probably could have written more tests for the rest of these. But let's just move on. Alright, enter raffle, that's going to be our next describe block. So it will do describe, enter, raffle. And this is going to be an async function. And we'll say it reverts when you don't pay enough, right, because one of the first things that we check is that
they're paying enough. So we want to make sure that this actually reverts if they don't pay enough. So this will be an async function. Where we're going to do that same expect await thing. So we're going to import expect from Chai, which comes from those waffle matchers. And we're gonna say await, expect raffle dot enter a raffle. And we're not going to pass any value here, we're going to expect it to dot b dot reverted with. And if we look here, we want it to be reverted with this raffle not e
nough eath entered. So we can put that in quotes raffle not enough eath entered. Now we can try this out. Make sure that it actually works. Ah ah test dash dash grep. Put this in quotes that you don't pay enough. And awesome. We're passing there. What else do we want to test? Well, we want to test that if the raffle isn't open, we also revert but we'll test that in a little bit. As we kind of test the rest of the functionality. We want to see that it records players when they enter. So this will
be an async function. And now we'll enter the raffle. First we're going to need that raffle entrance fee. Let's go ahead and save that at the top. So we'll say let raffle VRF coordinator be to mock raffle entrance fee and then our before each will say raffle entrance fee equals a weight ethers dot get entrance fee. This should be raffle dot get entrance fee. So now we have this raffle entrance fee, you can use it to enter the raffle we'll say a weight raffle dot enter raffle with a value of raf
fle entrance fee. And we can make sure that our Deployer here has been correctly recorded. So since right now we're connected to the Deployer. We'll just make sure that that deployer actually is in our contract. So we'll say const player from contract equals await raffle dot get player of zero, because we record them in our players array and we have our get players function which pulls them out. And then we'll say assert dot equal player, player from contract should be the Deployer. So now we ca
n grep for this in our hard head test. Make sure this works. HH test dash dash grep. Deployer is not defined. We've got it up here. But we actually didn't save it globally. So we got to do let common Deployer. And we'll say deployer equals await get named accounts. And we'll wrap it like this to get the deployer Awesome. Let's try this again. And awesome. What else should this do? Well, it's also emitting an event. So let's make sure it emits an event. So we'll say it emits event on enter. This
will be an async function as well. And this will be the first time that we're testing to make sure a function emits an event and the syntax is going to look really similar to what we test for when we check to see if an error is fired. So we're gonna say await expect raffle dot enter raffle with value of raffle entrance fee dot two dot omit and this.to dot emit we get from During woful, these chime matches for emitting events we can do a wait expect to emit, and then the event that we're expectin
g to emit. So we're saying to omit the raffle contract to emit a raffle enter event. We can copy this, try to test this in our terminal. So we'll say hard hat. Test dash dash grep. Just put this in quotes. And that passes as well. Great. Let's now go ahead and test to make sure that we can't enter the raffle whenever this raffle is not open or it's calculating. So we'll say it doesn't allow entrance, when raffle is Cal cumulating. And this will be an async function. And first we'll enter will sa
y await raffle dot enter raffle value is raffle entrance fee. Now what we want to do we want to get this raffle into a closed state. So we want to get it out of its open state. Well, how do we move this raffle from raffle dot open to raffle dot closed in perform upkeep, remove the raffle from raffle that open to raffle dot calculating but perform upkeep can only be called if check upkeep returns true. Otherwise, it'll revert with raffle upkeep not needed. So what we need to do is we need to make
check upkeep return true. And we will pretend to be the channeling keeper network to keep calling checkup keep waiting for it to be true. And once we make it true, then we'll pretend to be the channeling keepers and call perform upkeep to put this contract in a state of calculating. Now how do we actually do that? Well, in order for checkup keep to be true, we first need to see that we are indeed open, which we are. The next thing that we need to do though, is we need to do this time passed bit
. We need to actually wait that 30 seconds for time to pass. Now, that kind of sounds awful. Do we have to wait 30 seconds for all of our tests? What if our interval was 10 days when we have to wait 10 days to run our tests? It sounds ridiculous. Well, hard hat actually comes built in with a ton of functions for us to manipulate our blockchain to do literally whatever we want it to do. In the hard hat documentation. There's a section called Hard Hat Network reference inside the Hard Hat Network
section. And in here, there's a ton of information about how the hard hat network actually works and different configs that we can do with it. If we scroll down low enough, we can see the JSON RPC methods that we can use on this blockchain, we can do eath accounts block number call chinetti. We can do all these RPC methods that a normal blockchain has. Additionally, we can do even more than that, we can use these things called Hard Hat Network methods. Since this is our local Hard Hat Network. A
nd we're using this for testing, we want to be able to test any scenario. And it's these methods that give us the ability to do that, you can go through this and play around and see all the different things you can do. One of them in particular is going to be set storage set where you can set storage at any place, which is really fun. But some of the special testing debugging methods are going to be EVM increase time, and EVM. Mine increased time allows us to automatically increase the time of o
ur blockchain and EVM. Mine allows us to mine or create new blocks, because if we increase the time, it doesn't do anything unless there's a new block mined. So what we can do is we can run a wait network, and we'll import network from Hard Hat Network await network dot provider that send EVM in crease time, comma, we can send a list of parameters to send with it, which for us are just going to be our interval.to number. And then we'll do plus one. Now right now, our interval isn't stored global
ly, so we're probably going to want to do that. So let's go ahead and do interval. And then in our before each, we'll do interval equals await, raffle dot raffle dot get interval, I'm just going to copy this and we're going to delete this whole line. Wait raffle dot get interval. Since now we're just going to call it interval at a global level, since we're going to use it a lot. Now we're gonna say interval that to number plus one. So we want to increase the time by whatever our interval is to m
ake sure that we can actually get that checkup keep to return true. So additionally, we're going to want to do a weight network dot provider. Dot send EVM mine with an empty array just because we just want to mine it one extra block. You can also do network dot provider that request with an await here, these two would be basically the same, but this one's a little quicker, right? So we've increased the time of our blockchain. We've mined a block to move forward. It should be open time has passed
. Do we have a player? We do indeed, because we've entered the raffle. We should have a balance because we've entered the right Apple, check upkeep should now return true. So we should be able to call perform upkeep and pretend to be a chain lock keeper. So we're going to pretend to be a chain the keeper and call await raffle dot perform upkeep. And we're going to pass this some empty call data just by passing a blank array like that. And now this should be in a calculating state. So now that it
's in a calculating state, we can say our enter raffle reverts correctly if the raffle isn't open. So now we'll say await, expect raffle dot enter, raffle. And we'll send it value of raffle entrance fee. We're expecting this.to dot b dot reverted with that raffle underscore underscore not open error. Okay, let's try just this in our tests now. So we'll run Hardhead test dash dash grep. Put this in quotes. And perfect that passes as well. Now if we run Hardhead test, let's just test everything to
gether right now. And everything is passing. Oh, this is wonderful. Awesome. Let's keep it going. And if we run Hardhead coverage, we'll see our coverage is bumping up, we are already drastically better than where we were before. Let's keep going well, let's go ahead and test our check upkeep now. So we'll do describe, check upkeep. And this will be an async function, where we'll say it returns false. If people have been sent an E, E, it's been a sync function. So we'll have everything in here b
e true except for the fact that nobody's entered yet. So we'll do a weight network dot provider dot send EVM increase time, comma interval.to number plus one will do a weight network dot provider. That send UVM mine. No parameters. Now we're going to call check upkeep. Now here's the thing, check. upkeep is a public function. So if we just run await, raffle dot check upkeep, and we pass nothing in this is going to kick off a transaction, because hard had knows Oh, okay, it's a public function, t
hey're clearly trying to send a transaction here. If this was a public view function, it wouldn't, it would return that view. But the thing is, I don't really want to send a transaction. But I want to simulate sending this transaction and seeing what this upkeep needed would return. Well, I can actually get that by using something called call static, I can simulate calling this transaction and seeing what it will respond. So instead of raffle dot, check upkeep, I can do raffle dot cost static, t
hat check upkeep. And this will give me the return of upkeep needed and the bytes perform data, I can extrapolate just the upkeep needed out of this return or writing const upkeep needed equals this, and then I can do assert not upkeep needed, because right now upkeep needed to return false. So we'll say assert, not false, which is true. If upkeep needed was true, then this would be false. And this would break. So that's what we want to do. So let's go ahead, we'll run this, see if it worked. Ou
r hat test, dash dash grep. And we're in passing, we are in business. Awesome. So this is working perfectly. Well, and let's also test that it returns false. If raffle isn't open. This will be an async function. And we'll do everything except and we'll do everything in here. But we'll make the raffle in the calculating state. So do a weight, raffle dot enter, raffle value, raffle entrance fee await network dot provider that send and I'm just going to copy these two lines here. Because we're goin
g to go ahead and do those. We're also going to do a weight, raffle dot perform upkeep. And another way to send a blank bytes object is to do a string like 0x hardhat is smart enough to know that this should be transformed into just kind of a blank bytes object. So either one of these should work. Now we're do const, raffle state equals await, raffle dot get raffle state and we'll Get upkeep needed. So we'll say const. upkeep needed, we'll do exactly what we did above raffle dot call static dot
check upkeep. Let's say excuse me a weight, raffle dot call static. Now we can do assert dot equal, say raffle state is going to be, or excuse me raffle state.to string, it's going to be calculating, and I started dot equal upkeep needed, it's going to be false. Let's run a GREP on that. And perfect. That's also working correctly. Great. Now I'm going to skip over these next two tests, because we haven't really learned anything from them. So I'm just going to copy paste them from the GitHub, we'
re going to return false if enough time hasn't passed. And we're going to return true. If enough time has passed, we have players Eve and is open. So we're just asserting true down here. And we're starting not true up here, you want to pause the video and copy paste these and write these out, you absolutely can copy paste them from the GitHub repo, you absolutely can't like I said, going through this and making yourself write these and making yourself understand these tests is going to make you
a substantially better coder. And let's just test that it all looks good with hh test. Now, as I was recording this, I just realized that for all of our describe blocks, I've been making them async functions describe blocks actually don't realize and can't recognize and can't work with promises. So having the be async actually doesn't do anything. So in your describe block, we want to get rid of the async word because it's actually not helping us at all. In fact, it's just an extra word, and it
looks kind of gross. So now all of our describe blocks, we're gonna get rid of that async keyword, and just have them be functions. Of course, all of our it's, though, are going to be using asynchronous functions, which is what we want. So we've written some tests for a checkup keep. Now let's go ahead to perform upkeep. Let's create a new describe, block, ascribe or perform upkeep. This is going to be a regular function. And in here, we're going to start and say it can only run if check upkeep
is true. And this will be an async function. Because we only want to perform keep to work if checkup keep is indeed true. So we'll say await raffle dot enter. raffle we'll send it some value, raffle entrance fee, I'm sorry, there should be curly braces instead. And we'll do a weight network dot provider that send EVM increase time inter vol.to number plus one await network dot provider that send UVM mine an empty array there to the reason that we're moving time forward and moving our block forwa
rd, of course is gonna be the same thing as above, we want our check upkeep to return true. And then we're gonna say const X or transaction equals await raffel dot perform upkeep. We can either do a blank array, or we could do 0x Doesn't matter. And we can assert the X. Now if TX doesn't work, or this error is out or something, this will fail. Right. So that's how we know that this actually can work. So let's test this out. We want this only to work if checkup keep is true. And we made checkup k
eep true by all the stuff that we did above. So now we'll do yarn hardhat test dash dash grep with our IT block here. And I spelled perform upkeep wrong perform upkeep. Let's try spelling things correctly. And let's run that test again. And great. That's working. I will What else do we want to do? We want it to revert with raffel. upkeep not needed if checkup keep is false. So in here we're gonna say it reverts. When check up keep is false. This will be an async function. And we're going to do t
hat same syntax await expect raffle dot perform upkeep empty bytes object that to.be reverted with. And what do we want it to be reverted with? Or hoping it's reverted with this with that, we can run this test here Hardhead test dash dash grep paste that in. And we see that is indeed passing now something that you'll notice here is that our revert actually goes ahead and reverts with all this extra stuff as well. Our test is smart enough to know that if all we do is put the name of the error tha
t is getting reverted with then it's good enough. If we want to be super specific, we can actually go ahead and make this a string interpolation and add all of these in here. So we can add the balance that we expect we can add the players that we expect. And we can add the raffle statement for now we're just going to keep it as we're expecting this but if you want to be super specific you can have your tests expect for exactly the specific values that you're looking for. But alright, what is the
last thing we should expect form? Well, we should check to see that this actually gets called the raffle state gets changed. And we admit this event. So let's go ahead and add that. We'll say it updates the raffle state admits an event and calls the VRF coordinator to be an async function as well. Let's do this. So let's go ahead and let's make checkup keep true, I'm just going to copy paste these first three lines, since it's going to be exactly the same. We're going to enter the raffle we're
going to increase the time we're going to mind a new block, then we're going to call perform upkeep. So we're going to say const, TX response equals await raffle dot perform upkeep with an empty bytes object, and we're going to do const TX receipt equals await TX response dot wait for one block. From this receipt, we're gonna get the request ID, we're gonna say const Request ID equals, we can get the request ID. From this omitted event. However, we should look at our VRF coordinator mock again,
when we call request random words, both in the mock and then in the actual contract, you'll notice that it also emits an event with random words requested. And if you look in here, the second parameter that it has is indeed the request ID. So in reality, US omitting the request ID is redundant, we can just use the admitted Request ID from the VRF coordinator for the purpose of this course and showing you what an event looks like. We're going to leave it in there. But if you want to go back and r
efactor this, you would definitely want to remove this omit. But for this test, let's do TX receipt dot events. And this is going to be the first event instead of the zero with event because before this event gets emitted, this function is going to emit an event. So instead of the zero with event, this is the first event that gets emitted after this one. So tax receipts dot events of one dot args dot request, ID, and then we're gonna say cert request id.to number is greater than zero. And then w
e'll also assert that the raffle state equals equals one. So we're gonna do const, raffle state equals await, raffle dot get raffle state. And this should actually be raffle state.to Number, or to string and then you know, do whatever we want to do. And this is a very big it, but we're going to copy the whole thing anyways. HH test, dash dash grep, paste that in there, we run it, excuse me.to string equals equals one, transformer time and perfect, we are passing Great, now it's time for fulfill
random words. And this is where we're going to learn a lot of fantastic stuff here. So we're gonna make a new describe block zoomed out a little bit here. And this is going to be our fulfill random words. It's going to be a function, of course. And in here, we're actually going to add another before each want to have somebody have entered the raffle before we run any tests in here. So we're going to do a before each, which will be an async. function. And we're just going to run await, raffle tha
t enter raffle with a value of raffle entrance fee. And then we're going to do a wait network dot provider dot send EVM increase time of interval, that to number plus one, and then a wait network dot provider dot send EVM mine. Comma. Before we've tried to do any testing of or fulfilled random words, we're gonna have somebody enter the lottery. And we're going to have increased the time and mined a new block. Okay, cool. So the first thing we want to do is want to see that fulfill random words c
an only be called so long as there's a request in flight, so long as there's a requested as long as request random words has been called. So we can actually check that by running it can only be called after perform. This will be an async function. And in here, we're going to revert on some requests that don't exist. So we'll do await, expect the RF core didn't a tour be to mock dot fulfill random words. And if we look at our V RF, coordinator v2 Mark in here has the fulfill random words function
, which is what the chain link node actually calls and inside Add this function in the actual contract calls another contract that does the random number verification. So we're basically checking this part right here. If the request doesn't exist, we're going to get this non existent request here. And as you can see, it needs a request ID and a consumer address. So we're going to guess zero. And the consumer addresses, of course, it's gonna be raffled out at address, we're going to expect this t
o be reverted, with non existent request. And then we're going to do this exact same thing with a different Request ID or request ID one. And hopefully, we're also going to get non existent requests. Now ideally, no request here would ever allow this fulfill random words to go through. Now, it obviously would be really hard for us to test every single possible Request ID, we're going to see a way in the future to actually test for a ton of these variables with something called fuzz testing. But
we'll get to that in the future. And I spelt the scribe wrong, let's let's actually spelled the scribe correctly, go ahead and run this hh test dash dash grep. And great it passed. Now I'm going to make just one more test here, that's gonna be way too big. But right now the test that we're about to write is going to be it's going to be a really big test. And we probably want to split it up into different sections, but actually figured that this was actually the best way to show this section. And
it's going to be exactly what we're going to do. When we get to our staging test, we're going to write this test literally almost exactly the same. So let's write it, this is basically going to be the test that puts everything together. So we're going to test that this indeed, so winner resets the lottery, and sends money, which is kind of a lot for a single it, we probably would want to split those into their own pieces. But for this, we're just going to put them all into one, and it's going t
o be an async function. Now we are going to learn a couple of new tricks here. So definitely be sure to follow along. Now for this one, we're also going to add in some additional entrances additional people who are entering this lottery. So we'll say const, additional, and trance equals great. We're gonna have some more of those fake accounts from ethers enter our lottery here. So we're gonna say const. Starting account, index equals to, since deployer equals zero, excuse me equals one, since th
e player is zero, so we're going to have new accounts start from index one. And we're going to do a little for loop or let i equals starting count index, i is less than the starting count, index, plus additional and trend sees there's gonna be entrance. i plus plus, we're gonna do a little loop and connect our raffle contract to these new accounts. And then we're going to have these new accounts, enter our raffle contest. Count, connected raffle equals raffle dot connect accounts of i and do we
have accounts defined somewhere we don't. So let's get accounts to find somewhere. We'll say const accounts equals await ethers dot get signers. And then we're going to do a weight account connected raffle dot enter. raffle with a value of course of raffle entrance fee, we're going to connect three additional entrance to our raffle. So we're going to have a total of four people connect into this raffle. Now that we have them in here, we're going to keep note of our starting timestamp. So we're g
onna do const starting timestamp equals await, raffle dot get last timestamp. And here's where we're going to get a little bit tricky. What we want to do is a couple of things we want to we want to perform upkeep, which is going to mock being chainlink keepers, which will kick off the chain link, which will kick off calling fulfill random words. And we're going to mock doing that as well. Mock being the chain link VRF. Once we do that, we can of course just check to see okay, did the recent winn
er get recorded the raffle get reset just play as we said as the timestamp is everything reset. But we want to do this in a specific way. If we're doing this on a test net after we call fulfill random words, we will have to wait for the fulfill random words to be called. Now since we're working with a hardhat local chain, we don't really need to wait for anything, right because we can just say okay, boom, snap our fingers and adjust our blockchain to do whatever we want. But we're going to simul
ate that we do need to wait for that event to be called. So in order for us to simulate waiting for that event, we once again need to set up a listener. Now if we set up a listener we don't want this to Just to finish before the listener has is done listening, so we need to once again create a new promise. And this is going to be incredibly important, especially for our staging tests. So we're going to do await, new promise. And this is going to be exactly the same as we set it up before, it's g
oing to be an async function that's going to take resolve and reject as parameters. And we're going to use this little arrow syntax here saying, this is an async function, basically, and we're going to set up once again, that once syntax, we're gonna say raffle that once, what's the event name, winner picked. So we're gonna say, Listen, for this winner picked event, we're gonna say raffle dot once winner picks happens, do some stuff. And again, this is just an anonymous function. So we're gonna
say raffle dot once the winner picked event gets emitted, do some stuff. So we're setting this up. Now it's in this function, we're going to add all of our certs and everything because we want to wait for winter to get picked. Now before the event gets fired, though, we of course, need to actually call perform and call fulfill random words. So this is going to seem like it's a little bit backwards. But that's because we want to set up our listeners so that when we do fire, the methods that will
fire the event, our listener is activated and is waiting for it. So we're going to put all of our code inside of this promise. Now, because we put it outside of the promise, we put all the code outside of the promise, this promise will never get resolved, because the listener will never fire into vent. So if down here, you know we call fulfill random words with something, you know which the spelling is bad. But let's say we call the down here, this piece of code will never reach this fulfill ran
dom words, because it's always going to be waiting for this wants to get resolved. So we need to add all of our code inside the promise. But outside this raffle dot once now we don't want to wait forever, right? Maybe there is an issue here. And we want to be able to reject this, if there's an issue. Now what we can do is in our heart hat dot config, we can add a timeout. So we can add this mocha section, we can give ourselves a timeout of 200,000 milliseconds, which is going to be 200 seconds m
ax, if this event doesn't get fired in 200 seconds, this will be considered a failure and this test will fail, which is what we want. And I typically like to just wrap this in a try catch because if something fails, it'll cause you a whole bunch of headache catch E. And if anything fails, we'll also reject, there's an issue with us calling some function, we'll just say, Hey, okay, that's a failure. But you fail, that way, our promise can get resolved in a timely manner, we're going to add this c
ode in a little bit. But let's keep going. Let's keep going. And excuse me, the trycatch should be in the ones, the ones above the results, excuse me, because this is the listener. So sorry, we want the trycatch to be inside the ones if this takes too long, we want to just go ahead and throw an error. Otherwise, we're going to resolve now outside the listener, but inside of the promise, we're going to do this bit here, where we go const TX equals await raffle dot perform upkeep, and we'll pass i
t the empty bytes object, we'll get const TX receipt equals await TX dot weight of one block. And then we're going to do a weight VRF core didn't a tour be to mock dot fulfill random words, CX receipt dot events of one dot args dot Request ID come a raffle that address. So then the final thing that we're going to do is we're going to get this veer off coordinator be to mock we're going to have it call fulfill random words, which takes the request ID and the consumer address. So we're going to mo
ck it, give it the request ID which we get from the transaction receipt, and the consumer address here. All inside this promise, we're setting up a listener for this winner picked event. And then we're mocking the channeling keepers and then we're mocking the chainlink VRF. And once this function gets called this function should emit a winner picked event. So this raffle that was set up that was listening for this to get emitted will pick up and go Ah okay, I found it I found the winner picked e
vent. Now we can go ahead and do some stuff. So once the winner picked event gets fired, we'll do a little console dot log found the event like this and we'll jump into our try catch and this trycatch is going to be basically us doing all these asserts in here. So first we want to say const recent winner equals await raffle dot get recent winner and we're going to be checking just everything in this raffle right we're gonna be checking that the recent winners right that that the raffle state's b
een reset the players have reversed, you know, players has been reset, etc, etc. So we'll say const raffle state equals awaits raffle dot get raffle state we'll say const. Ending timestamp equals await, raffle dot get last timestamp. And let's start doing some asserts. So first we should assert that this es players array has been reset to zero. So if we call get number of players it should be zero. So we can do const num players equals await raffle dot get number of players like so. And we can d
o assert dot equal nine players.to string is going to be zero. What else can we assert? Well, we can assert dot equal raffle state should be back to being open. So raffle state.to string should be zero, we should assert that the ending timestamp is now greater than the starting timestamp. Because the last timestamp should have been updated. We also want to make sure our recent winner is correct. But we'll do console dot log recent winner. Now we can go to the VRF coordinator mock. And we could s
imulate this and try to figure out who the random winner is to console dot log accounts to. And then just to show a bunch of them, we'll do 01 and three a raffle dot once this needs to be an async function, not just a regular function. Let's try that one more time, get latest timestamp is the correct function. So let's update this with the correct latest. Let's put latest in there. Because I'm spelling something's wrong. I sure am looks like we're printing out recent winner here when we haven't
even initialized it. So let's move it up. And then we'll do console dot log recent winner. So I know this is a massive test here. But let's give it a try and see if everything kind of does what we think it should do. And it's slowing down here, which is good because we're doing a lot of stuff. And uh huh, we finally get this passing thing to come out. And we did a ton of console dot logging so so there's a lot of stuff in here of the signers are getting printed out. So let's just make this a lit
tle easier to read. We'll add dot address to all these, we can see who the winner is. So it looks like the winner is going to be account number one, which is great. So what we can do now that we know account number one is going to be the winner, we can get that winners starting balance way down here before we call fulfill random words. So we'll say const winner, starting balance equals await accounts one dot get balance, yes, you can just call get balance right like that. And now that we have th
e winner starting balance back in our tests, we can say const winner, ending balance equals await ounce one dot get balance. And we can make sure that this winner got paid what they need. So now we're going to do a big assert with some money stuff, just trust me, this is what the math is. So we're going to do assert dot equal winner balance.to string, excuse me winter ending balance.to string should equal the winner starting balance dot add the raffle entrance fee that multiplied by the addition
al and trance that add the raffle entrance fee that we paid.to string. So this math is basically saying the winner should end with a balance of all of the money that everybody else added to this contract. And that's it. So we can run this test one more time. And Gosh, darn it, it passed. Okay, so there was a lot of code here. And this might have been one of the hardest pieces of this entire course is going to be this part right here. So if you struggled a little bit with this, don't let that bog
you down. This is probably one of the more difficult sections of this course, let's do a quick refresher of just this test that we're doing. And then we'll see in an action when we do it. In our staging test. What we did is we're picking a winner resetting the lottery and we're sending money. Basically what we're doing is we're testing that this fulfill random words thing does what we want it to do a random winner wins and they get the money. So how do we actually do that? Well, we first starte
d off by having a bunch of random people enter the lottery. Great. Sounds good. Now what we wanted to do was we want to call perform upkeep and fulfill random words, we want to pretend that the random number was drawn. And that's what this code down here does is it calls that random number but and what we could have done was we could have had all these assert and checked all the variables. After we did this, right. We could have totally done that. However, on a test net where we don't always kno
w exactly when a transaction is going to finish. We have to wait If we have to listen for an event to be fired, before, we could call the transactions that would end this whole thing, we needed to set something up to listen for that event to be fired. And we said, hey, only once this event is fired only once this transaction is called, can we do our testing now for our local network, we are mocking the VRF coordinators, we have control, we know exactly when this is going to run. But on a test ne
t, we don't. So you'll see in our staging tests, we won't have any of this here. And we'll have to rely on setting up a listener to listen for the channeling VRF and the keepers to fire their events. And that's why the staging test is going to be so important to make sure that we're doing everything correct. And that's why we set up our local tests like this, so that it mimics what we're going to be doing on our statement test what we're going to be doing on a real network here. And again, we're
setting up this listener and we're saying, Ah, once we do here, this event, then we're going to try to actually check all of the balances and check that everything is working as intended. And if we don't see it, we're going to reject. And if there's a timeout, if it takes more than 200 seconds, we're going to say okay, something went wrong, we're going to cancel it. And actually, I'm going to bump this up to 300 seconds, because I think 200 seconds is not going to be enough. And depending on ho
w quick the rink B test that is, you might have to bump this up even bigger. So just keep that in mind. But who, okay, we have just built some fantastic tests. Let's go ahead, and let's just run h h test to see if all of our tests are going to pass. And well, 14 passing, everything is passing here we are looking good. This is fantastic. Alright, so now that we have our unit tests, let's go ahead and create a staging test. Our staging test is going to look really similar to that massive test that
we just created down here. And the reason we set up our unit test to do this a weight promise thing with the raffle dot once was because this is actually how we're going to need to wait on a test net or main net for a winner to be picked. We cannot on an actual test net, pretend to be the chain link V REF, we can pretend to be the chain link keepers if we want. But we're not going to make sure that the 10 the keepers is actually working. But we are going to be doing this because we want to list
en for that event to be fired, we want to listen for the chain link VRF to respond with the winner. So let's create a staging test. And this is a test that we're going to run on an actual test net here. Okay, so we're going to create a new test called raffle dot staging dot test dot Jas and this is where we're going to put our staging test. Now we can actually code this pretty quickly because most of our staging tests is gonna look real similar to our raffle test here. So for now, let's just gra
b this whole first part, and then we'll adjust it as we need. And then we'll close it off. Because we're definitely gonna need a raffle, we're not going to need a VRF coordinator mock because again, we're not going to be using a mock. Since we're on an actual test net, we will need the raffle entrance fee, we will need Deployer, we will need a Deployer. And we might need the interval. But let's delete it for now we probably won't need the chain ID. So let's delete that as well. Awesome. Somethin
g that we want to keep in mind is that when it comes to our staging tests, we only want our steam test to run when we're on a test. Net, we don't need to run our unit tests because our unit tests aren't checking that compatibility with a test net, we want our unit tests to only run on a local network. And we want our staging tests to only run on a test network. This is where again, in our test, we're going to check to make sure what type of chain we're on. And oops, it looks like I already impor
ted the development changes here. So we're actually in our staging tests, we're going to check before we run any test what kind of network we're on. So we're gonna say, if our development chains that includes network dot name, we're gonna say if our development chains includes network to name, so if the chain we're on is in the development chains, and again, we're going to use this ternary operator where we say, if we're on a development chain, do something. And then if we're not on a developmen
t chain, do something else. If we are on a development chain, what are we going to do? Well want to skip this and we can actually skip this by putting in this describe dot skip. And this will skip this whole section here. And then we can say, if we are the development chain, go ahead and do our thing. So this is some really nice syntax that allows us to skip our staging tests if we're on a local network. And additionally, we can grab this syntax, go into our raffle dot test dot j s where we have
our unit tests and add the bang operator, which is the knot and hit Save. And now we're saying if we're not on a development chain, skip it and only run this if we aren't in development chain. So this says run this only on a test net or main net. And then this has run this only on a local network. Great. So we have a deployer which we're going to need. We are not going to need to deploy any fixtures because we're going to run our deploy script and our contracts should already be deployed. We wi
ll need a raffle we won't need a VRF coordinator mocks we can delete that We will need the entrance fee, and we probably won't need the interval. So we can go ahead and delete that too. Alright, awesome. So we have our describe, we have our before each, let's make our tests. And I'm just going to make one giant test to test kind of everything end to end. And you can add more tests later on yourself, if you want to our staging test is going to be really similar to this massive test that we made d
own here. And in fact, we're going to use most of this code here as our boilerplate. So let's create a describe. And we'll say, and we'll actually just copy this describe the four random words and paste it in here. Because again, we're going to be using a lot of the same code in our staging tests here. Great. So now we'll say it works with live chain link keepers and chain link VRF, we get a random winner, acing function. So this is going to be our test in here. So in this test, we of course, we
want to enter the raffle. And we shouldn't have to do anything else except for enter this raffle. Because the chain the keepers and the only VRF are going to be the ones to actually kick off this lottery for us, we'll do a quick grabbing of the starting timestamp to have it before all this kicks off. So we'll say const starting timestamp equals await raffle dot get last to me get latest timestamp, get latest timestamp, we're gonna grab this because later on, we're going to test to see if the ti
mestamp has indeed moved forward, we want to enter the lottery, right, we want to run the command we've been running over here all the time, we want to do you know await raffle dot enter raffle, but we don't want to call it yet. Because same as what we did over here, we want to set up our listener first. Now in here, we probably should have set up our listener before we entered the raffle. However, we controlled the blockchain. So putting it in that order was is was okay. But we want to set up t
he listener before we enter the raffle just in case the blockchain moves really fast. And we're going to set up the listener the exact same way, we did it over here. So we're gonna say await new promise. And it's going to be an async function that takes a resolve and a reject. And we're going to use a little arrow notation here. And in here, we're going to set up the listener, we're gonna say raffle dot once, once that winner is picked, we're going to do another async function using that Arrow.
Arrow function syntax, we'll say console dot log winner picked the event fired. And only once we get this winner picked, can we start doing our asserts in here, can we start making sure that there's a winner, there's a verifiably random winner, it's been picked, the money has been moved, etc. This is where we'll do our try catch. And if there's any error, we're just going to automatically reject, we're going to reject the promise. And if all goes well, of course, we're going to resolve the promi
se. So our listener has been set up here. We haven't added our asserts here. But we will, let's just go ahead and write the rest of the test. And then we'll go back and we'll update this listener so so our listener has been added. And inside here is actually where we're going to enter the raffle. So inside here, await, raffle dot enter raffle value is going to be raffle entrance fee. And really that's it. Right? So we're setting up the listener, setting up the listener, then entering the raffle.
And this code won't complete until our listener has finished listening because again, this whole SEC is in a wait. So we're gonna say okay, cool setup, the listener, wait for this to finish. And then when it gets here, it goes out okay, this is the end of the code Are we all done executing Oh, no resolve or reject hasn't been called yet. And that's because we're still waiting for the listener to finish listening. Now, once we get this winner picked event emitted in here, we're going to get that
recent winner so we'll say const recent winner equals await raffle dot get recent winner will get the raffle state we'll say const. raffle state equals await raffle dot get raffle state, we'll get the winners balance. So we'll say const. Winner balance equals await recent winner. And since we're only entering with our Deployer we should check to see the deployers balance at the end and we can't do it right with this deployer object here. So we'll have to do the player account equals await ether
s dot get signers, no wrap this actually actually will just say this is accounts here like that. And then we'll just do a count of zero because it counts as zero is going to be our Deployer. So our winner balance is going to be accounts a zero dot get balance. And then we're going to do const ending timestamp equals a weight raffle dot get latest To timestamp, and we should also get the starting balance. So we'll say winner ending balance, we should also get the starting balance right after we e
nter. So we'll say const. Winner, starting balance equals await accounts. Zero dot get balance, so that now we can do some comparisons. All right, great. Let's do the comparisons now. So we should first expect the raffle to be reset. So we can do this a few different ways. Down here. We did number of players. We can also say, await, expect raffle dot get player 0.2 dot v dot reverted, right because Get Player zero should get reverted because there's not even going to be an object at zero. So tha
t's another way we can check to see if our players array has been reset. Next, we can do assert dot equal recent winner.to string, this should equal our account zero dot address. Okay, our Deployer What else can we do? We will assert dot equal raffle state to zero. We want this email to go back to open after we're done. And then we finally want to make sure that the money has been transferred correctly. So we'll do assert dot equal, this should be a winner ending balance. That to string should b
e equal to winner starting balance, add raffle entrance fee.to string. So if we look down here, they enter the raffle we check their starting balance right after they enter. And they basically should just get that raffle entrance fee back right because they are the only ones who have entered this raffle. And then we can do one more assert, do assert that the ending timestamp is greater than the starting timestamp. And then we'll of course, say resolve. So this all goes well, we resolve. If there
's an issue with any of these asserts, we're going to catch those errors and we're going to reject and this is going to be false. And this whole test is gonna go ah, there was an issue, we now have a staging test that looks really good here. Let's try this out. Let's try our staging test out from start to finish. So now in order for us to test this staging test, from end to end, you first going to need to get our sub ID for the channeling fear F then we're going to need to deploy our contract us
ing the sub ID, we're going to need to register the contract with chain link VRF. And it's somebody we're going to then need to register it with chain link keepers. And then of course, we're going to run the staging tests. So let's do it. So first thing we're going to need to do is what? Get our sub ID for chain link VRF. Okay, great. So we're going to come over to VRF dot chain dot link. And we're going to need to create a new subscription. If we don't have enough rink B eath. Let's we want to
head over to the full blockchain solidity course, here, we're going to scroll down. And we're going to look for the recommended test and here, which is ranked v. And we're going to use the faucets link to get some Rigby link, run Fosses dot chain dot link, let's switch over from COVID to a cerium. Rigby, we know we're going to need some link and some eath. So let's just go ahead and get both. Alright, great now that our transaction has gone through, let's just double check our wallet here. And i
t looks like we do indeed have Ethereum here. And if you don't see the link, you can head over to link token contracts, Link token contracts in the chain link documentation. We'll scroll down to Rigby, we'll grab this contract address import tokens and we'll paste it in here. Add Custom tokens, import tokens. Great. Now I can see my eath and my link here, perfect. We have some eath we have some link, let's head over to V REF subscription management. And we're going to create a new subscription.
Again, we could totally do this programmatically, because the user interface here is only helping us facilitate call contracts to the registration contract that's completely decentralized and on chain. So let's go ahead and create subscription will create subscription will confirm the transaction and Metamask on the Rinkeby network will do a little bit of wading in great once it's gone through, you can go ahead and click the add funds button. I'm going to show you what it looks like if you accid
entally refresh and jump off though. So if you refresh and you go back to veer off the chain dot link, you should have a new active subscription. And you'll see this number here. If you click on it, this is your subscription ID great. So we can actually take this, come back to our code into our helper Hardhead config. And we can paste our subscription ID under subscription ID for our Rinkeby network here. Awesome. Now that we have a subscription we can see it's not funded with any link. So we do
n't have any Oracle gas here. And we don't have any consumers. Right our consumer is going to be a raffle or a lottery contract. So let's add some funds first and we don't need to add A whole lot because we're only going to be testing once. So let's go just go ahead and add to link here, this number might change depending on different costs of the test nets and how much link token there's available. So if you're actually working on a main net, be sure to head over Doc's touching that link EVM ch
ains contract addresses, you can read more about the costs some of these different chains, so you can figure out exactly how much to put in here. And if you go to the full blockchain solidity course, Jas, we can scroll down to Lesson Nine, there's a recommended link amounts or rinky saving tests for chain link VRF. For now we're going to put two for keepers, we're going to put eight, but feel free to refer to here so you know how much to put in. So let's go ahead and confirm, we're going to appr
ove adding funds here, go ahead and confirm. And we're now funding our subscription to so we can pay that Oracle gas to get our random numbers. Great. And once we're funded, we can close it, we'll do a little refresh. And we can see the balance is now to link when we don't have any consumers perfect. So we've got our sub ID, we funded it. Now let's go ahead and deploy our contract. And we already know that we should be all good for deploying our contract, we go to our Dotty and V will need to ad
d all of those same parameters from our previous projects, we'll need to shrink the RPC URL, we'll need our private key. If we want to verify we'll need our ether scan API key. And if we want to do gas output, we'll need our coin market cap API key. So let's make sure we have all that. And we'll look at our deploy script. Once again, just real quick look at our helper hardcat config just real quick, and it looks like we do indeed have everything in here. And we should just be able to deploy it i
n one command. So we should be able to do yarn, hard hat or just h h again, ploy, dash dash network Rinkeby. Let's go try this out. All right, it looks like we've compiled successfully, we've deployed it successfully. And we've even verified it, we can go and open it up on Rinku ether scan. And we can see our code here has been verified. And it's looking beautiful. We can read from it, which is great. We can see all these commands here now that it's verified. And if we look at the Git raffle sta
te, we should indeed see that it's open, right, and it's going to stay open until somebody ends the raffle and updates the amount of eath that the contract actually has. Now that we've deployed a contract using that sub ID, we need to register the contract with chain link V REF. And with chain link keepers. So we need to add this consumer does tell chinley VRF. Hey, this is the contract that you're looking for now. So we're gonna go back to V REF dot chain dot link, and we're going to grab this
contract address, and we're going to add it as a consumer, your subscription is ready, you can now add consumers we're gonna add consumer. And again, this website is just here to help facilitate us interacting with the contract. So we're going to approve that user, we'll go ahead and confirm and the transaction is going through. While we wait for this to go through, we can go to keepers dot chain dot link, and do the same thing work with the user interface to register a new upkeep. So we'll go a
head and add our email Hardhead free code camp@gmail.com. We'll call this raffle upkeep. We'll paste our upkeep address in here we have our admin address, and you can ignore this bit right here. For gas limit, this is going to be the gas limit of the PErforM upkeep function. If we did our gas estimator, we could just check to see how much that perform upkeep costs. But for now, I'm just going to put 500,000 That's probably overkill, but that's fine. Check data, we're going to keep blank because
again, our checkup keep doesn't take anything. And then starting balance, we're going to put as eight. And if you forget to put a starting balance here, you can always find it later. So let's go ahead and register, we're gonna get a Metamask pop up, we're gonna go ahead and hit Confirm. And we can go back to our VRF and see that it's indeed been added and awesome, we now have a consumer on our VRF. So now let's just wait for our keepers to go through upkeep registration requests submitted succes
sfully on domain net, you might actually have to wait a little bit for your request to go through, but I'll test that it should automatically go through. Now if we go back to keepers dot chain dot link, we should now see we now if we scroll down to my upkeeps We have a raffle upkeep here and I have to because I accidentally use the same account that I tested on, you can ignore the two you'll have one but this is the one that we just created. And we can actually see what our balances and then wha
t the minimum balance for this actually is. So it looks like eight Link was a little bit too low. So let's go back to Fosses dot chain dot link slash rinky. Now that we have some more link, we can come back to our raffle upkeep. And we go ahead and hit add funds. And we'll add just three. And we'll go ahead and confirm we first need to give permission to spend. We approved our link transfer now let's actually transfer the link to the contract and alright funds added successfully. So now let's do
a little refresh. Now we no longer see that message saying that it's underfunded and we have our balance and we can see that it's more than the minimum balance. We have See the history that we just funded this twice. Once this actually kicks off, we'll see activity type will be like perform upkeep or something got our sub ID, we've deployed the contract, we've registered with chain link V REF, we've registered it with chain link keepers. Now all we need to do is run the staging tests. Now runni
ng our staging test is essentially going to be the same as us calling this enter script, right, because all we're doing in our staging test is entering the lottery. And then we just have a whole bunch of validators that we're running to make sure that things are doing as we expect, since our contract is actually verified, what we could do on Rigby ether scan is we can actually go to this right contract section of the contract. And we could even connect our wallets to it. And once this turns from
red to green, after a little refresh, we'll now see that it's green, it's connected, we can even call functions on this contract ourself, so we could enter the raffle ourself, we would add, you know, however much eath to enter the raffle, and that would kick off the keepers in the VRF, as well. So we could call it via ether scan, we could obviously call it via our staging tests here, we could call it via our scripts, we could call it via the console, there's a ton of ways to actually do this. B
ut moment of truth here, we're gonna run our staging tests, which is going to have us enter the lottery, and set up a listener to make sure that everything works correctly. And additionally, we'll see on our raffle upkeep history, we'll see a transaction go through, and then we'll see a transaction on our chain like VRF as well. Are you ready? I sure am. Let's do this. So we'll do h h, test, dash dash network, rink B. And that should be all we need to do. In our state and tests, we probably shou
ld have added some console dot logs in here to tell us hey, to tell us what steps that we're on with each. But we forgot to. So if you follow along with the repo associated with this, we've added the console dot logs in the test there. But all right, if we go to the ether scan for this contract, we go back to the rink the ether scan for this, we paste in that address, the first step that we're doing in this test, of course, while we're setting up this listener, the first transaction is going to
be entering the raffle that's going to kick everything off. Right. So if we refresh a little bit on ether scan, we do indeed see we've entered the raffle. And we've updated the balance of the raffle. Okay, awesome. So raffle has been entered. Now then what happens? Well, if the raffle has been entered, if we go to raffle dot soul, if it's open, if enough time has passed, if there's players and it has a balance, which we just checked does, this will get kicked off by the keepers. So if we go to t
he keepers, and we do a little refresh here, after a little bit, we do indeed see checkup key passed and we see a perform upkeep having gone through great, what does perform upkeep to well perform upkeep calls the chainlink VRF. So now if we go over to chainlink, VRF, we do a refresh here, go down to history, we do indeed see one of the transactions has gone through we can see the transaction hash, the link spent, etc. And now if we go back to our tests, we do indeed see raffle unit tests for fr
iend fulfill random request winner pick event fired. And this means that we just went through this entire process of having a perfectly truly decentralized raffle work on an actual Testament with our integration tests working correctly. Absolutely massive, huge congratulations if you've made it this far. And if you just walk through the integration test with me now bounce over contract has now been reset to zero because our wallet address just won the lottery right and got the money back. Now yo
u might be wondering, Hey, I see the Create raffle function. And I see enter raffle but I don't see didn't the chain link nodes just call perform upkeep and fulfill random words, I'll come no matter how often I refresh, I don't see those transactions here. Well, those are actually going to be considered internal transactions fulfill random words, it's actually called through the VRF coordinator and the VRF coordinator contract then calls for full randomness. So we can go to internal transactions
. And one of these transactions is going to be the transaction to the VRF coordinator contract, which calls our contract. Same thing with perform upkeep. Perform upkeep, the chain link nodes actually call through the registry contract and then the registry contract calls perform upkeep. That's what we see here. And if we go through the internal transactions, we'll see him there. Now let's look at this enter raffle as well. And since we've learned about events and logs, we can actually go to the
logs section now. And we can see our log or event being emitted here we can see the name raffle, enter, we can see the topic zero which is going to identify this entire event. And then we also see this number here which is what which is index topic, one address player and then there's no data associated with this right because we only have index parameters which again show up as topics so this is absolutely phenomenal. Wow, absolutely massive and we can rerun a unit test Just by hh test in this
will only run our unit tests. And we can see that these are all passing as well, things are looking fantastic here. And we have just successfully created a verifiably random, autonomous, decentralized, raffle and or lottery deployed on the blockchain, you should be so excited right now. Now, I'm not going to show you how to push this up to GitHub. However, if you want to push this up to get up, and again, tweet at me, tweet at chainlink tweet at Free Code Camp, please feel free to do so because
you just did an amazing job getting this far. And if you're gonna want to push this up to GitHub, remember, we're going to want to put a dot Git ignore. In here, we add a ton of stuff like that VS code artifacts, cash deployments, known modules, etc. Type chain types, all this stuff, you can find a sample dot Git ignore, of course, in the GitHub repo associated with this, this is an advanced project, we did a lot of really advanced things here. And this is the section of the course, where I thin
k at this point, you've got most of the fundamentals down. And now we're going to move into more front end. And we're going to move into more industry specific and more advanced topics that are really going to supercharge you and make you one of the masters of the blockchain in the smart contract realm. So huge congratulations, one more time, definitely go celebrate, definitely go for that walk, take a quick break, let everything we just learned settling your brain and get ready for the next one
. Alright, now we're gonna go over the TypeScript edition of this lesson, we're gonna go a little bit quickly here, because we're not learning too much new stuff for this TypeScript edition. So if you want to just follow along, you can open up the repo here and use the TypeScript branch. One thing to note that is a little bit different is when we do our promise in our tests, we're doing a weight promise void, because we're not going to be returning anything with our promise here. But the rest is
going to be exactly the same. We're going to have a hard hat dot config to TypeScript that's going to use imports. Once again, everything else is pretty much the same. We're going to export the config like we did last time. In our package dot JSON. Of course, we're going to have all of our TypeScript dependencies as well. And then our deploy scripts are going to follow that same functionality that we've used before. So now our deploy scripts use a type deploy function on our variables that we e
xport at the bottom. And we also import the hard hat runtime environment type, which where we pull the deployments get named account and networks from in our tests. Of course, we're still importing the types of these contracts from type chain slash types, like you see here, like for example, raffle is going to be signed to raffle VRF coordinator V to mock is going to be signed to type VRF coordinator V to MK and if we wanted to deploy with these contract factories, we could as well. So those are
going to be the main differences with TypeScript. There's not anything really new there. But again, if you want to follow along with TypeScript, and you want to code everything in TypeScript, and example is here for you All right, welcome back. I hope your break was absolutely fantastic because now we are getting into more advanced full stack slash front end development. We've done the back end development, we've created smart contracts, we created our lottery. In our last section, we have all
this wonderful code that allows us to work with our own provably decentralized lottery. In order for regular everyday people to use our lottery, we're going to need to build a front end. Now previously, we learned to build a front end with raw HTML JavaScript, with our Funmi project, we created a front end with just pure HTML and JavaScript, just creating applications with HTML and JavaScript is great. And if that's what you want to do, you absolutely can. But doing it with those vanilla protoco
ls has some limitations. And working with a framework, like what we're going to be working with in this section is going to make our lives a lot easier, we're going to be able to develop quicker, have more functionality, and do more in less time. As you remember back to the project wasn't really a fleshed out project, if you remember, it was just a bunch of buttons. And that was really it. So working with a framework is really going to enable us to put more features and add more styling to our a
pplications really easy. Once again, the code for this entire section is located in our lesson and is located in this GitHub repository associated with the course. Now I have to put an asterisk here, as I've said many times, the front end sections of this course are not required, we're not going to learn anything new about the back end in this front end section. So if you don't care about building websites, all you want to do is learn the smart contract aspect of this course, you can skip these
sections. But if you do want to learn how to build these front end applications, if you do want to give users and non developers the abilities to interact with our smart contracts, then please continue to watch. Now I also have to put an asterix here, because if you haven't worked with some of these frameworks before, the learning curve can seem a little bit steep. And as I've said many times, this isn't going to be a front end course that would take several more hours than what we want to do fo
r this video. So if you've never done front end before, this is one of the sections where I do recommend you follow along with one of these optional sub lessons, we're not going to play them here. But if you follow along with one of these sub lessons, that will definitely be incredibly helpful. One of the videos that I have for the sub lessons is this video right here, how to connect your smart contracts to Metamask. And it shows a number of ways connecting your smart contracts and building kind
of these these front ends. It does start with a raw HTML and JavaScript edition. So you can really get some more practice in here with HTML and JavaScript. And then it moves to index js ethers and a few other next Jas based applications. Doing it a few different ways will install a new some more insight on what you should be thinking about when you're approaching these. So this is absolutely a video to watch if you're new to front end development. Additionally, for this section, like I said, we
're going to be using a framework. And in particular, we're going to be using the next Jas framework. Now. Next, Jas is a react based framework. React is a framework for building front end and full stack applications. Next, Jas is a framework on top of the React framework. So if you already know react, most of this is going to come very naturally to the reason that we're using React in next Jas is because React is easily as of right now one of the most popular frameworks and languages out there.
And it's no surprise why we've got a little article in the GitHub repo titled Why you should use React js for web development, which we'll go into a little bit more. Some of the biggest applications like Facebook and Instagram use React js and a number of other Fortune 500 companies and React js especially in the blockchain space is easily the most popular with protocols like uniswap, and Avi also using React Jas. Now the reason we're using this next Jas on top of React Jas is that next Jas, I
think makes working with react much easier. And I want us to work with the easiest and most powerful framework out there. Next, Jas is also getting a ton of steam has some really advanced but in my mind easier to use features than just raw react. Now, like I said, if you've never worked with React before, if you've never worked with next Jas before, and you want to do a little brush up, definitely watch my video six ways to connect your depth to a wallet. And if you find yourself struggling with
with this section, because the front end stuff doesn't really make sense. We also have a next Jas crash course in the GitHub repo associated with this course. It's about an hour long and it is absolutely phenomenal. Free Code Camp also has some next Jas crash courses. So if you're struggling with the front of it, go take it next Jas course, and then come back to this section or skip the front end sections all together, do the rest of the course of just the back end, and then come back and do th
ese front end sections. We're going to show you the cutting edge ways to interact and work with your front end and then also deploy them. And if you follow along correctly, by the end of this, you'll have a website deployed that you can show off and you can send a link of it to your friends. And now I know we already showed you what this looks like but I'm going to show you it one more time just so we can walk through and see exactly what we're doing. So we're going to have this decentralized lo
ttery where we can go ahead with can connect our wallet if not already connected. And we can switch, we can switch around between networks. And our app will actually recognize it and say, hey, the only supported chains that we're working with here are going to be 31337, which is localhost, or four, which is ring feed. And we'll learn how to add this validation into our application so that our app only works when we're on a chain that we want, then we can go ahead and interact with it. Normally,
we can click a button Metamask will pop up, we can go ahead and confirm we'll get a little transaction notification saying that transaction is complete. And we'll get our front end updated. And then on the back end, we'll be able to see the chain link nodes and the Chinuch V REF do their work. And once they actually pick a winner, after a refresh, we'll be able to see that the back end node was updated, we do indeed have a previous winner. Awesome. Now, not only that, we're going to show you how
to build this, but also, we're going to show you how to host it on an actual site. So you'll be able to push it up to your own blockchain. And additionally, we're gonna host it in a decentralized context. So this site that we have here is it's going to be hosted on a technology that allows us to host websites in decentralized contexts as well swore backends. And even our front ends can be hosted in decentralized context. So So I hope you're incredibly excited for this because we're going to be
showing you the cutting edge tools that many of the top blockchain projects use. And let's just jump right into it. Now, I'm currently in the Hardhead smart contract lottery project, the project that we just did, we did this hard hat smart contract lottery, which is great. What we're going to do now is we're going to create a new folder, although we are going to be coming back to this folder from time to time to make a couple of updates. So if you want to keep it open, you absolutely can. But fo
r me, I'm gonna go ahead and CD download directory to kind of my main directory for this whole course. And we're going to create a new directory called next Jas. smart contract. Lottery, FCC, then we're going to cd into next Jas smart contract lottery FCC, and go ahead and hit code period. And like I said, if you want to keep that one up and have this new folder up, you absolutely can. But basically, again, we're just opening up our VS code in this next Jas smart contract lottery folder. Now for
this front end stuff, in particular, if you want to be absolutely sure you're using the same versions as I am, what you can do is you can git clone this repo, and then copy the yarn dot lock and package dot JSON, and then run yarn, this will make sure you're always using the exact same packages that I'm using, and you'll never run into any weird issues. So if you do run into an issue, one of the first things to do, especially for these front end parts is to go back, make sure you have the exact
same yarn dot lock and package that JSON that I do in my examples here, and go from there. Now we're here in our front end project. And we're going to create a website, we're gonna create a front end for application, like I said, we're gonna be using next Jas, if you want to follow along with the next Jas documentation here, they do have a great getting started and walking through this. So for us, we're going to do yarn, create next app, and then put a little period saying we want our next app
in this directory. If you don't put this period, it'll create it in a new folder, and you'll have double folders. Okay, awesome. So and once we do this, in our little files explorer section, we now can see all the different files that come boilerplate with this. Now, let me just do a quick walkthrough of what's going on here. Again, we also go through this in those two videos that I recommended, but it doesn't hurt to go over it twice. So node modules, of course, is going to be the package in th
e installations pages is going to be the different pages on our site. Let me let me show you what I mean by this. To run this whole thing. Actually, we can just run yarn, run Dev, and we'll get started server on blah, blah, blah, blah, blah, you can command click it or copy paste it into your browser. And now you'll see on localhost 3000, we have our page up here. Now what we can do, actually, so index.js is going to be our default page, which is, you know, considered this slash here. But what w
e can do is we can create new pages. So I could do new file, you know, dog dot Jas. And then you know, just copy paste index into dog to Jas, paste it, delete everything inside the div, you don't have to follow along here and just go Hi, save this, go back here. I can now put in dog and get this. So pages is going to be all kind of these different routes to these different spots on our website. And index is going to be our default, kind of like our homepage. So I'm going to delete Dardo. And ins
ide these files is going to be something called react syntax or JSX. They come as Jas but they're basically reacts in text. Next, Jas is based on React, you'll see these pages are this weird combination of both JavaScript and HTML. We see some import stuff at this at the top, which reminds us of JavaScript and again, you'll see some important stuff at the top and then down here, you'll See, like div head main h1 P, you'll see all these like HTML tags react index js allow us to do this combinatio
n of JavaScript and HTML. And it actually makes life a lot easier. Now, you'll also notice we're doing imports in here. Remember, I told you all this earlier, imports work with our front end require does not. So that's some of the difference between node does not equal JavaScript, right? This is where the differences can start getting a little bit confusing. But the way that I usually like to think about it is I just say, no JS, excuse me, I'll just say back end. I can J S is a little different
from front end. Yes. So back end, Jas and front end Jas are a little bit different. That's kind of the way I like to think about it. app.js is going to be our entry point for everything the way react and next Jas work is everything is what's called component based in all of our files here, you're gonna see this export default function home or something along those lines. What react and next Jas do is they say, Hey, this huge clump of HTML stuff that has a hodgepodge of JavaScript inside of it is
considered a component. And so all of our pages get wrapped through this underscore app.js page. So this is a page but it's kind of like the main entry point. And they get stuck into this component section of our app that Jas so you can think of this on this graph. The GS is kind of the whole application or whole front end. And on this homepage, this component, we're sticking index dot j s right in here, we're swapping out component for index dot J. S. Now API is what we wanted to do if we want
ed to do like some HTTP, GET HTTP POST requests, but we're not going to do any of that. So we're going to pretty much ignore API for now public is just going to be some public images like a favicon or Versaille, that SVG styles is going to be the CSS for our project. CSS stands for Cascading Style Sheets. And it's basically a way to style your HTML, we're going to change the way we do styling and a little bit, but that's basically what these both do the ESLint I'm dumping this right now we have
our dot Git ignore which we know what it does. We have our next dot config dot J. S. This is a configuration file or next. Jas, of course, we have our package json, we have a readme, and we have our yarn dot lock. So most of what we're going to do is actually going to be inside this Pages folder. And we're also going to create a couple other folders that are going to be our main stuff now, because I'm me, and like I said, I love working with prettier, I'm going to automatically dump a prettier R
C, and a prettier ignore in here, just so that I can format my code a little bit nicer, you can grab your prettier RC from our last projects, you can grab your prettier ignore as well. Or you can just pause me right now copy, paste them from the GitHub repo associated with this lesson, paste them in, and then we'll do yarn, add dash dash Dev, prettier, so that we can auto format all of our code for come back over to here, we can save and boom, stuff gets auto formatted. Now, again, we're going t
o be using the multi terminal feature. So right now I have one running my front end. So if I come back to the front end, I hit refresh. It's still running. And then I have one to do, you know my scripts and stuff. We have yarn run dev running right now. And if we go to our package, JSON, running yarn, run dev just runs next Dev. And actually, let me cancel it and just do yarn dev yarn is actually smart enough that don't need to do run Dev, but it just runs next Dev. And this next command comes b
uilt in once we installed next, which we did when we did yarn create next app. So next Jas comes with these scripts already built in for us, we want to build our front end to enable people to interact with our lottery in a fair way, and connect with the smart contract that's running. Let's create some simple front end pieces for this. So first thing we're gonna do is we're gonna go to Pages, and we're going to go to index.js. All this stuff in here is cute and nice. And thank you next, Jas, but
we're going to delete it all and delete everything except for that headpiece, we're gonna leave that up, we're just going to change the name. But this way down here, we're going to change the name from Crate next app to smart contract lottery or raffle or whatever we want to do. description will be our smart contract, lottery. And then right below the head, we're going to write hello, blue, and save. And if we look at our front end, we now see that it says smart contract lottery and the top and
I'm going to move this all the way over here, smart contract lottery and the top and we see Hello, so smart contract lottery. Hello, the description here, we're not going to see this is going to be something that web scrapers and stuff we're going to find. Now one of the first things that we're going to need to do is we're going to need to create that connect button. We've done this in the past with raw JavaScript, but now we're going to do it with next js and react. The one that we made previou
sly was pretty minimalistic. In fact, we bring it back up it checked to see if there was windows that Aetherium and then went and requested and connected and said okay, cool. You're connected. Now what did didn't do was a lot of things that we would want an application to do. When we change networks, our application didn't detect that when we change users or application didn't detect that it was really stringent in the functionality that it actually had for connecting to a wallet. So we're going
to make our wallet connect button, incredibly powerful, so that you can connect with the button, you can switch networks, you can switch accounts, you can pretty much do anything in our application will know our application will be responsive. So that's gonna be one of the first things that we're going to do, we're going to create a header and connect button nav bar one a little navbar here, saying, hey, you know, you can connect with this button. So that's gonna be the first thing that we're g
oing to do. Now we can build our whole connect button in this index dot j s and stick it in here. But instead, what we're going to do is we're going to make it a what's called a component. So we're going to create a new folder called components. And we're going to create a new file in here called header.js. And you might also see a lot of people do header.js x.js and.js x do literally the exact same thing, you can do either one, I'm going to do dot JSX, just to remind me that this is a React fil
e that we're creating. This is a component that we're creating. But yeah, you can do J S JSX. If you want to learn a little bit more about components, we've got a link to learning about components. They're basically independent and reusable bits of code. They serve the same purpose as JavaScript functions, but work in isolation and return HTML. So basically, we're going to create like a little chunk of HTML that we're going to export into our index such as like what we've done in the past, this
just helps modularize and reuse this header component, you know, across our project. Now, we're only going to be using our header in one area. However, it's still nice to modularize the project regardless. And to get start, this is going to be what's called a functional base component. So we're going to create basically a function called home write really pretty much exactly like what we see in JavaScript, except it's going to return some HTML. So we can do like a little div. And my VS code auto
created the closing div here. And in here, I'm going to be like hi from header. This is going to be a real minimalistic component like this is a valid component here. Now we have this function that returns HTML. And to give other applications, the ability to use this component will do export default function home. And then in our index.js, we can import it with imports. Home actually, excuse me, I'm not going to call it home, we're going to call it header, header, excuse me, export default func
tion header, and then import header from the down directory components slash header, like so. So now we've imported our header in index such as if we go back to our front end, which is still running, we don't see it in here, right? Remember, everything goes through our app. And when we're on the slash page, that's going to go to our index.js. index js is importing our header, but it's not returning our header, right, we see. And here, we see it returns. And this is the HTML that it's returning.
And as you can see, there's clearly no header in here. So now that we've imported our header, we need to actually add our header in here. So we'll do header, and then adds the closing tag right here. If you don't add any stuff, you know, in between two tags, you can go ahead and just do this one liner here, with a backslash at the end saying, Hey, this is an open and closed tag here. Now that we've imported it, what do you think we'll see on the front end, now that we've added it to our index js
, you're right, we see hi from header, because we added our header here. And then we see Hello. So high from header, hello, boom. Now, anything that we do, obviously now in our header.js, will see reflected on our front end. So we can do hi from header, blah, blah, blah, you know, just a bunch of dribbles, and we'll see it on our front end. So this is going to be our section where we're going to make our header or a navbar or all the functionality for the Connect button. Now I'm going to tell yo
u something, and some of you are going to love this summer, you're going to hate this. I'm going to show you. I'm going to show you the hard way first, then the easy way. Why am I going to show you the hard way first? Well, because I want you to become familiar with what's actually going on behind the scenes and what's actually going on with some of these components because it is really helpful when building these front ends to understand, Okay, here's what's going on. If you don't understand wh
at's going on behind the scenes, you're gonna go to try to build more advanced applications, and you're gonna have no idea what to do because you've just learned the shortcut. I like to think of it as like calculus, like we're going to learn how to calculate a derivative first, and then we're going to learn the shortcut to quickly getting derivatives. So don't skip this part, because this is going to help you well and beyond down the line. Okay, we're going to learn this the harder way to set ev
erything up in our HTML Funmi. We just use raw ethers to kind of do everything and you absolutely can use raw ethers to do everything. However, there are some packages especially for React that make life developing a front end substantially better and in our full blockchain solidity course, Jas. We have a number of other packages that you can use will stack development and other libraries. And if you watch this six ways to connect your depth to a wallet, you'll actually understand some of the di
fferences. So if you haven't watched that video, go back, watch that video. But there's a whole bunch of libraries that we can use that are going to make our lives a lot easier. We've listed some of them here. React Morales is the one that we're going to be using today, they have some additional plugins, and they have probably my favorite thing on the planet, which I'm going to show you how to do very soon. But these are also open source, Ross also comes with some optional functionality to hook
into your own back end to give your app even more features and even more functionality. And that's the other reason that we're doing it. So and we're gonna go over that later. And if you want to use pure ethers, you absolutely still can. A lot of these packages that we're using do rely on ethers, but we're not going to use just ether. So we go to the React Morales page. And to get started, we can just do this bit right here. So we're literally going to copy this and bring it into our project. An
d if you go to our package that JSON, we actually already have react and react DOM. So we can just do yarn, add Morales, and react oralis. Now you'll notice I'm not doing these as dev dependencies, I didn't do yarn, add dash dash dev here. The reason is, because for our production builds, when we actually create the website here, you will need Morales and you will need react Morales we don't need prettier to create a website prettier is a tool that we're using as developers. So in all of our pro
jects, so far, we've been using just dev dependencies. That's because we've only been building our projects for developers, our GitHub repos, they haven't been made to build a website, they've only been to do things on the back end, for our website, we're actually going to be building a front end. So we need to put this in the dependencies section, because we need to say, Hey, these are the ones that we need to bundle up together for the front end, and you can ignore these ones. And if it's just
like a tool to make our lives better, it's gonna go in dev dependencies. So we're adding Morales and react Morales. And a lot of the syntax that we're going to do for our header is actually going to be really similar to what we've been seeing so far. So let's do this. And then actually, we're just going to change this name to manual header, manual header update imports for manual header, you can go ahead and hit yes to man you all header here, we're gonna copy manual header, make sure it's in o
ur index.js it we're gonna change header to manual header, and we're gonna change how to manual header here. And the reason we're doing this is because like I said, we're going to create a much simpler header after we create this kind of harder one. And we're going to want to create that connect button, which again, we made in HTML Funmi. By calling eath request accounts, what we can do actually with Morales is we can just do this thing called Enable Web three. So at the top, we're going to impo
rt, use mirallas. From react ralis. And if you go to the React Morales page here or to their GitHub, you'll learn how to set all this up too and learn more about the documentation. So we're going to import use Morales from react Morales, and inside our function here, but outside of our return, we're going to say const, Enable Web three equals use mirallas. Now use Morales is what's known as a hook as a React hook. And it's a way to keep track of state in our application. Now, in order to use mir
allas, our entire application needs to be wrapped around what's called a Morales provider, which is going to be a context provider for us. And I'll explain what that means in a minute. But basically, what we need to do is we need to add this Morales provider to our app.js. So in here, we're going to import oralis provider from react oralis. And we're going to wrap our entire app around this Morales provided so we're going to do some little parentheses here. New Line, we're going to paste morass
provider like this, it's going to give us the closing tag, copy it, paste it like this and save. And then in here, we're going to write in the sheet allies on Mount equals false. This initialize on Mount piece here is the optionality to hook into a server to add some more features to our website. We don't want to hook into a server for this application, we want everything just to be open source, and we don't need any of this additional functionality. So we're just going to do initialize on Mount
equals false. Now that the whole thing is wrapped in this Morales provider, we go to the front end we should be able to refresh everything looks pretty much the same. And we can start using these hooks. Now this use Morales is what's known as a hook and hooks can be a little bit confusing to understand at first glance, but they're incredibly powerful and they are the de facto way for us to build react projects. And if you're familiar with class components, we're not gonna be using class compone
nts because hooks are much better hooks allow function components to have access to state and other react feature ers state being probably one of the biggest ones and the most popular ones, we want our application to be different if we're connected to Metamask, versus if we're not, right, if we go back, if we go back to our example website here, right, if we're not connected, we want to say, Please connect to a wallet. And then when we are connected, we want to go ahead and be connected. If I ha
ve, let's say, I have some variable like, and I don't have this hook here, I have like, let connected equals false, right, or enable Web three, or is web three enabled, let's say I've led connected equals false. And then I have, you know, let's say have some button that connects us and changes connected to be true, changing connected to be true is great and all but it won't rerender our application, you see, when I disconnect and I reconnect here, our application actually changes based off of wh
ether or not we're connected. And this is what we want, we want our front end to rerender. When we're connected, if I just use a variable like this inside of our component, our front end isn't going to rerender. Or even worse, if I use it outside, our component doesn't even know anything about this changing. So hooks are a way for us to actually work with state especially and automatically rerender when something changes and enable Web three is going to be a function that we get from this use Mo
rales hook to do that. So for a lot of our components, instead of just saying like, let web three enabled equals true, like we did in normal JavaScript, we're going to be doing a lot of this, these hooks. For the most part, we usually want our website to change based off of if some variable has changed and enabled web three is a function that we get from this hook that says, Okay, go ahead and connect Enable Web three is basically the equivalent of saying try await Aetherium dot request, like th
is. Now enable Web three, the way we're going to use it here only works on Metamask. But we will show you how to get this kind of this cool little module up where we can choose between different ways to connect our app. We have our enabled web three, let's go ahead and create a button, that's going to do the same as what we did in our HTML Funmi in our return, but here, instead of hi friend header, we're going to add a new component, or we're going to add a new tag, we're gonna add the button ta
g, and for me it automatically close to, and I'm just gonna call it connect, I'm gonna go ahead and save. Now we see a little button that says connect. And obviously, it doesn't do anything, we're gonna give this some functionality, we're gonna say on click now since again, this is a JSX component. This isn't raw HTML, in raw HTML, we can't just kind of stick JavaScript wherever we want. But in JSX files, we can stick JavaScript kind of wherever we want. So inside of this, inside of this block o
f HTML, we can actually stick JavaScript in here by adding these little brackets. So adding these little brackets in our jobs can return. But here, we can add JavaScript. And what we want to do is we want to have our On Click Call Enable Web three, we're going to call an async function, we're going to use the arrow syntax here, one click, we're gonna call this async function, which is just going to be await, Enable Web three, await Enable Web three, let's add the little parentheses here. And ess
entially, with just this, we've done pretty much everything that we had back in this big connect function here. Now if we go back to our front end, do a little refresh, we can see that right now, we can see that I'm actually connected, I'm gonna go ahead and disconnect. I'm still connected from some of the last applications I was doing, we can hit Connect, and now we see metamath does indeed pop up, we'll hit Next connect, and boom. And that's all we need to do. Now, if we look at our Metamask,
it says connected. Great. Okay, cool. So now we have a way to actually connect here, let's add some functionality and make our application smart enough to have the connect button if we're connected. And if we're not connected, not have that button. So what we'll do now is use Morales comes with another hook called is web three, enabled, which is just a variable part of our hook that keeps track of whether or not our Metamask is connected. But we can actually do one better, we can actually check
to see if there's an account because maybe web three is connected. But but they didn't connect it to an account. So let's go ahead and we'll import count from us. Morales will check to see if there's an account. So what we'll do is inside of our div tags, we'll do a little JavaScript, we'll do that ternary operator again, we'll put a count here with a question mark. And we'll do that that same syntax that we've seen before, we'll say account, if account exists, do this. If there's no account, do
this. And if there's no account, we want to add this Connect button. So we'll go ahead and we'll stick this in here. If there is an account, we'll just show that account, right. So we'll do div backslash div in here, we'll just say connected, like that. Now if we go back to our front end, we see connected. If we do a little refresh, it'll go away. So we'll we'll re hit Connect, and now we're connected, which is great. Let's make it even smarter. We'll have it show our account here. So instead o
f just saying connected, we'll say connected to I'll put some JavaScript, we'll put some JavaScript inside of our JavaScript. But since this is that HTML stuff, we got to use these brackets to say JavaScript again. So we'll put JavaScript inside of the JavaScript, we'll say connected to, we can just say account. Now go back to our front end, we see connected to blah, blah, blah, blah, blah, you'll notice if you hit refresh, you'll have to reconnect, we'll get to that in a minute, what a lot of p
eople do is they'll do a count dot slice, zero, comma six. And then outside of the brackets, they'll do dot that dot, another set of brackets account, that slice, count dot length minus four, close that off like that, we have our account, when we hit Connect, now it says connected to blah, blah, blah, hello. And because of these hooks, when I switch accounts, and I connect with these new accounts, it even automatically re renders switching accounts. So these hooks are really good for re renderin
g our websites whenever some value changes. For example, if I said like, let count number equals seven, and we had a button, that updated account number, our front end wouldn't rerender unless we told it specifically to rerender, which gets really annoying. So hooks kind of help us a lot with doing that. And it allows us to keep track of states between renders. Now, here's something that right now it doesn't do, if I hit refresh, I have to re hit this connect button, even though my Metamask says
, Hey, we're connected. But if I refresh, I have to re hit this Connect button. Why is this happening. Or when I hit refresh, our website doesn't know that we've hit enable Web three already, right, because we basically go back to blank when I refresh, and then I have to hit Connect, which is really obnoxious and really annoying. So we want to add some functionality, so that automatically the instant we render, we go ahead and we check to see if we're already connected. And if we're connected to
show this. Now to do that, we can use another hook called use effect. And this is a core react hook. So we'll do import use effect from react like this. This is a core hook directly from react. And it's one of the most popular out there along with use state. And we've left some links to learning more about the effect hook in the GitHub repo associated with this course, I'm gonna give you my summary of basically what this use effect does, we basically have this function called use effect, which
takes two parameters, it takes a function as its first parameter, and then second, it optionally takes a dependency array. And what this use effect is going to do is it's going to keep checking the values in this dependency array. And if anything in this dependency rate changes, it's going to call some function, and then rerender, the front end. So for example, using Morales comes with this function called is web three enabled or this variable called is what three enabled. If we add this to our
dependency array, what we can do in our use effect is do console dot log, hi. And then we can do console dot log is web three enabled, what this use effect is going to be doing is it's going to constantly be running, this is running all the time. And it's going to be listening to see if is web three enabled changes, right? And anytime we run Enable Web three is web three enabled becomes true. So so now if we go to the front end, we do a little refresh, we see high false, high false. Now why do w
e see this twice is web three enabled only changed once? Well, this is because of how use effect works, it will automatically run on load or right or the first time it does and then it'll run checking the value. So we're basically seeing this run twice, it runs the first time we load it, and then it'll check the value and run again. So we see go twice, even though it's really just once. But if we go back here, sorry, let me just do a quick reload again. We hit Connect, we now see Hi is now true,
because it saw is what three enabled change to true because enabled web three made is what enabled return true. And it ran this again, right. So that's how that actually works. And there's a couple of different ways to think about this. Actually, we actually don't even need to give this an array. And what happens if we don't give this an array? Well, let's refresh. We'll hit Connect, and we'll see it's still ran a couple of times. So if we don't give it array, no dependency array, it'll run any
time something re renders. And you need to be careful with this. Because then you can get circular renders, if you have some use effect that changes some value. And you have another use effect that re renders when that value changes while they're both just going to keep changing back and back and forth. So no dependency array like this. It will run anytime something re renders we'll give it a blank dependency array. It'll just run once on load, just run one time. So now like we have a blank dep
endency right in here, we reload. Right? We see that it runs twice. That's actually because we're basically re rendering once in the background. So it really is just running Once but there's something else going on in the background. So it looks like it's running twice. Now if we just add is web three enabled, do a little refresh, it'll do the exact same thing, it'll run the same amount as if this was blank. But when we connect, it'll add here. If this was a blank array, when we refresh, we'll s
ee kick out twice, which should be ones. But like I said, there's something going on in the background. If we hit connect. Now, we don't see anything here, because the blank dependency array says, Hey, I'm only going to run one time on load. Now, if there's our stuff in this array, like is web three enabled, it's going to run anytime something in this array changes, right. So again, we'll refresh will connect, we see it ran again, after a hit Connect will refresh. Hi, hi connected, ran one more
time. So so that's kind of the cheat sheet here. If we give it no dependency array, it's going to run any time anything in this project re renders, if we give it a blank dependency array, it's just going to run one time, or like we saw, it ran twice. But that's because there's something else we render in the background. And if we give it dependencies in this array, it's going to run anytime something in this array changes. And this is really helpful, because oftentimes, we're going to want our f
ront ends to rerender, this use effect will say, oh, cool, some value changed, I'm going to run this function, and then I'm going to rerender, your front end. And now we're going to use this use effect thing to make sure that when we refresh, it remembers that we're actually connected. So how do we do that inside here, we are going to use this is web three enabled thing. And the first thing that we want to just do is we want to say if is what three enabled, then we'll just return. Because if we'
re already connected to web three, then we don't need to do anything. Now, if we're not connected to web three, and we don't have an account, we'll want to go ahead and call Enable Web three, right want to automatically enable Web three. So now if I go back, you'll see with just this code, I'm just always automatically calling Enable Web three. But this can get really annoying. Because if I disconnect, right, let's go disconnect everything. Now refresh, it's going to always call Enable Web three
, right, every time we refresh, it's going to automatically call enabled through without us even hitting the Connect button. So that's no good to we want to actually see if we're connected. So the way we do this, like I said, we want to use our local storage, again, application, or these little, this little thing here go to Application, we want our we want our application to remember that somebody hit this connect button, and they went and connected to us. So what we're going to do is in our lit
tle onClick function down here, we're not just going to call await Enable Web three, we're also going to store a little remembrance here saying, Hey, we actually did connect recently. So below this, we're going to run window, dot local storage, dot set item, connected, comma injected. I'm actually going to comment this out for now, because my friend is just going to keep popping up like that. So what this does is we're saying, okay, in our window, because again, if you go back to the window, you
go to console, a type window, you're actually going to see this giant window thing here, right, which we showed you before, there's always this window object in here. And we're going to do window dot local storage, which relates to if we go to this application section, this local storage section here, that set item connected to inject it. So we're going to set a new key value in here, we're doing it like this because in the future, maybe you want to do you know connect it to Wallet connect or c
onnected to Coinbase wallet or something, right, but we're just gonna say injected, meaning we're connected to that meta mask. And in some versions of next, Jas next, Jas has a hard time knowing about this window variable. So we can just do if type of window does not equal equal, undefined, then we're going to do this. So we're just making sure that window doesn't equal undefined that there is a window. So now if I go back to the front end, and I hit Connect, and we go ahead, and we connect here
, we'll see now in our application, local storage, we'll see we've added this connected injected bit here, we're storing in the browser that we are indeed connected to this. Now that we've added this into our browser, we can roll back up to our use effect here and say, Okay, if they're already connected, great, we'll be done. But before we do anything, let's check to see if they have this here. And if they already are connected, let's just run that connect bit. So we'll say if type of window doe
s not equal, undefined, right, because we want to check for that window object. Again, we'll say if window dot local storage dot get item connected, connected, so if that connected key exists, then we'll just run Enable Web three. So now We have some functionality in here, which even when we refresh, it will automatically run enable of three for us. So now if I go ahead and refresh the front end, we don't have to press that connect button anymore, because it goes, Oh, I see that locally, we stor
ed this connected key whenever you refresh. Now, it checks for this first it sees it and then runs enabled web three. Now on the other side, though, if we're in here, and now we disconnect, and then we refresh. This will show up, which is really annoying. And every time we refresh, it'll keep showing up, which we don't want. We want it to be that when we disconnect, we tell it hey, we've we've gone ahead and disconnected here. So back in our application, we can add another use effect to check to
see if we've disconnected. So let's create another use effect. That's going to costly just look for us being connected, we'll say use effect, do a little arrow bracket thing here. And we're going to do this anytime. And oh my goodness, anytime I save, it's going to keep popping up. So I'm just going to just going to comment that out for now. So in here, we want to say okay, whatever, there's a rerender we want to run if any account has changed. And Morales has some functionality for us to do th
is as well. So from user morass, we're going to import more Alice, and then down here in our use effect. Inside the little function, we're gonna say mirallas.on account, changed of account, we're gonna do some stuff. So on account changed, takes a function as an input parameter. So we'll say console dot log, account, change to account. And what we can do is we can check to see if this account is not. And we can say if account equals equals no, then if the account is null, we can assume they've d
isconnected. So we can say window dot local storage, dot remove item, connected, we'll also run a deactivate web three function. So from Ross, deactivate, web three will also run, deactivate web three, which is going to set is web three enabled to false. So we're going to disconnect the web three, and then we're going to say console dot log. No count found. So let's try this out. Now. Let's go back to our front end, we'll do a little refresh here. So right now it says we're connected. Even thoug
h in my meta mask, we're not connected, right? And to start from scratch here, you can go ahead and disconnect it. But but my browser says, Hey, we're connected, right? So now we'll connect. And we'll actually be connected right, next connect, and it and it just overrode connected, you know, with inject, let's, let's make this injected. And then we'll remove Yep, okay, injected, we'll refresh, like, connect, and now it says injected. Okay, cool. So now we're connected here. If in here, if I just
switch accounts, right, let's go to Account three, I'll connect. If we go back to our console real quick, we'll say account change to blah, blah, blah, I can change back, right, we'll go change account change to blah, blah, blah. Now, if we go back to our application, go in here. And we disconnect. Now let's disconnect both of these disconnect. And disconnect. We'll see it's now been removed from local storage. And if we go to our console, it'll say, no account, change the No, no account found
and removed it. Now if I hit refresh, nothing happens here, I can go ahead and connect. Right next connect, I can refresh. Oops, I need to go back in here and re enable this. So sorry, let's add this back in here. But now it can refresh. Let's go ahead and disconnect here. Let's connect. Let's go back to the console, we can connect thing will pop up next connect, I can refresh. It stays connected for me, I can switch accounts, I can go ahead and here, I can switch accounts, I can even disconnect
. And it will automatically update for me, which is what we want. So now we've essentially made a way more robust connect button, where it goes back and forth with when we're connected now. Now one more thing that we might want to do, or application is when we hit Connect, we want to maybe disable this button, right? We don't want it to allow it to be able to be pressed. So I'm gonna hit Cancel, we're just gonna add one more bit of functionality here, we're going to add this is web three enable
loading. And what this does is it just checks to see if Metamask has popped up. And so what our button after the on click section, we can add disabled. Equals is web three enable loading, so it'll be disabled if we're loading here. So let's go ahead and we'll disconnect disconnect. Now we'll hit Connect, and you'll see the button can be clicked. So that just makes it a little bit nice. Turn, Next connect Bada bing, bada boom, awesome, we have just made a way more robust front end than what we ha
d before this connect button is super slick. And it allows us to kind of flip back and forth. And our application is incredibly powerful and knows how to handle all these different changes. Now that we've learned how to do it the manual way, let me give you the Chiti way, in our components, we're gonna create a new file header dot j s, and what we're going to do is we're going to install this web three UI kit, it's a front end kit, and it has a whole bunch of these components already built for u
s. So we can build like a header component and a connect button component just by using this. So to install, install it, we're gonna come back here, we're gonna stop our front end. And we're just going to run yarn, add web three UI kit, like that. And again, we don't want this to be a dev dependency, because it is going to be a part of our website, and then we'll do in our header.js, we'll do import connect button from web three UI kit. And then we'll do export default function header. And then
all we'll do is return do like a div. And then inside this div, we'll do next button. With a little backslash here, we aren't going to need this for this project. But if we want to be super explicit, we'll say Morales off equals false. Just again, to reiterate, hey, we're not trying to connect to a server here just to make that super explicit. But this connect button does everything, this manual header thing that we just created, does. So back in our index.js, we can comment or delete this line
will do import header from dot dot slash components slash header. And then instead of manual header, we'll just do header. We start our app back up with yarn dev again, we go back to the page, we do a little refresh here, we now see we have this connect Wallet button. And it's even looks a lot nicer. It's got some nice styling to it as well, we can hit Connect wallet. And it'll give us this little ngModel asking us which wallet we want to connect to. So asking us which wall we want to connect to
is kind of similar in our manual header to this or set item connected, injected, right or wallet connect, it would do connected wallet Connect for trust wallet, it would it would set item as connected wallet connect, etc. So it allows us to connect in different ways. And we if we hit Metamask, we go ahead and connect like so even had some nice styling here where it gives us our wallet address here. But it also gives us our wallet balance as well. And again, if we go ahead and disconnect, we'll
see it automatically disconnect. We connect like so we can reconnect like so boom, boom. If we switch accounts, it's smart enough to know that we're switching accounts. So I know I showed you kind of the hard way. But I wanted to show you kind of what's going on. It's setting this local storage in the background so that it knows which where it's actually connected. But for headers moving forward, this is all you need. And your life will be drastically drastically easier. And let's just add a cen
tralized lottery or decentralized raffle or whatever you want to our header as well. So it says decentralized lottery, you know the button Hello. Now that we have that, what else do we need? Well, well, the main thing that this app needs to do is just have a big button that says enter the lottery. And then ideally, you know, show how many people are in the lottery and then the recent winner as well. So let's go ahead, we'll create a new component called lottery entrance. And we'll grab that comp
onent similar to like what we did with our header, we'll drop this component right here. And then our app will pretty much be done. So let's create this lottery entrance component, lottery entrance, that Jas, right and again, in the reason we're putting these in components, we could 100% Stick it all, you know all our code in here to make it more modular so that we in the future, if we want to have more pages or do other stuff, I'm going to zoom out a little bit just so that we can see all of ou
r code a little bit easier. This is our whole index j s. This is our whole header. Let's create a new lottery entrance app just for the boilerplate code here we're going to export default lottery entrance, excuse me, export default function, lottery entrance, and this is just going to be you know, another component where we're going to return some that JSX HTML stuff, right? So we're gonna do div and do like hi from lottery entrance, Excel. And now that we do that, we can go back to our index.js
. We can do import lottery entrance from dot dot slash components. Slash lottery entrance, will stick it right underneath the header like that. And if we go back to our website, we see high from lottery entrance so our lottery entrance is going to be right underneath the header would Here's what we want. And then we'll delete this line that says, Hello. So lottery entrance, what is the what is the first thing that we really need to do in here? Well, we're going to want to have a function to call
the lottery to enter the lottery. Let's go ahead and do this. Now let's go back to how we did this with HTML fund me recall that old fun function like this, but doing it like this won't rerender. And there's a whole lot of other functionality that doing it like this won't give us so we're going to use Morales to actually call some of these functions, because mirallas has in React mirallas. Again, they have hooks for us to do pretty much anything we want to do. And one of these hooks is called u
se web three contract. And what this does is it gives us a hook that will give us the data returned from a function called an error returned, a little function that we can use to call any function. And then we also have these really helpful is fetching in is loading. So if we want everyone to have our UI or our website, do something while it's fetching or while it's loading the transaction, we can use these two variables to do that. And then all we need to do is we just need to pass it the contr
act information, which similar to ethers is going to be the ABI contract address, we'll pass the function name, and then any parameters for that function. So we're going to use this syntax here to make that transaction to the blockchain. And to call these functions. So what we're going to do is we're going to import us web three contract from react mirallas. And inside our function, but before I return, of course, we're going to say const. And then we'll do kind of exactly what we see in here. F
or now, let's just get the function, let's just get this run contract function, because this is going to be the function that we can call to actually enter the lottery. So we'll say const, run contract function, and we're actually going to call this enter raffle. And we'll say equals, use web three contract, and we need to pass the ABI, we're gonna need to pass the contract address, we're gonna need to give it the function name, we'll need to give it the params, which actually we do know it's go
ing to be blank. But then finally, we will need the message value. Because if we remember back into raffle doesn't take any parameters, all it takes is this message dot value bit. So that's all we're going to need to pass. So how do we get all this stuff, and I'm going to leave this in here. But we're going to comment it out for now, because this is what we need to do. But we need to get all of this stuff into our code here. So how do we actually get all that stuff? Well, ABI is easy, right? Abi
isn't going to change at all, no matter what network or on ABI is always going to stay the same. Now if you've already deployed your smart contracts, and you know exactly what address it is, because you've deployed to a main net, or you've deployed to a test net, all this stuff isn't really going to change. And we can just hard code it all right into here. Or we can do what a lot of people do is they'll create a constants folder. And in here, they'll add like an API dot JSON, maybe they'll add
a contract addresses dot JSON. And then they'll add maybe like an index dot j s or something, we're gonna build our application in a way we can actually test locally using our own Hard Hat Network, and then compare it to what it looks like on the actual test net as well. So we're going to make it network agnostic. So the front end works exactly the same no matter what network that we're on. And we can go back, download a directory back into our CD, hard hat smart contract lottery Free Code Camp,
and spin up our node here, right with hh node or yarn hard hat node. And we'll use this as the blockchain that we're going to connect to. The thing is, if I go back here, and I'm building the front end, and I go, ah, like this would be better if we did X, Y, or Z. And maybe I changed the name of some functions, you know, blah, blah, blah, something else, I want that change to be reflected on my front end. And I want to be able to code my front end as such. So since we are the only developer rig
ht now, we kind of have the ability of where we both know, the back end code and the front end code. So something that I like to do to make my life a little bit easier is I like to create an update front end deploy script. So after we deploy stuff, we run a little script that will create this constants folder for us with a whole bunch of stuff, right? It'll give an ABI, it'll give contract addresses and anything else we might need in our front end from our back end. So what I like to do is I lik
e to come back to my original code and an update this for a new script. So I'll come in here in this deploy script, I'll create a new file, and I'll call it oh two or even like 9999, up, date, front, and dot Jas. And the reason I do 99, obviously, is because we want this to be always the last script in our deploy folder. And then we can just write a little script that's connected. We just write a little script that's connected to our front end here so that whenever we deploy contracts, no matter
what chain, we can update that constants folder on our front end. So let's go ahead and create that script right now we'll do module dot exports, equals async function. And we'll add all our stuff in here, we don't really need to deploy any contracts, because we're just updating the front end. So we can just leave the parameters of this one blank. And the other thing I like to do, because sometimes I don't care about the front end, what I'll do is I'll only update the front end if we've specifi
ed a dot env variable. So I'll create a dot env variable called up date, front end. And then I'll set this to true. And now in our script here, we can say if process dot E and V dot update, front end. And we can just say like console dot log, updating front end. And now back in here, right, if a mat if I'm in the correct directory in here, if our own hard hit Deploy, you know, get this little updating front end. And now we can update front end. So let's do it. So I'm actually going to create one
function called Update contract addresses. And this is going to be our function that we're going to use to update contract addresses, then I'm going to make one called Update API, where we just update the API's and the front end so so we're going to call this update contract addresses. So I'm going to create a new function async function, update contract addresses. And first, we're going to get that raffle contract since we're going to need to get its address. So we're gonna say const, raffle e
quals await. And we're gonna do the same thing we've been doing ethers dot get contract, raffle, and then my VS code auto imported, it doesn't const ethers equals require Hardhead, like so. So we have raffle in here. And we're gonna want to pass this raffle address to our front end, since this is going to be a variable that we might use a lot of places, we can just add it like const, front end location, addresses file, equals, and we're going to give it the relative path to where we are now, whi
ch is going to be you know, if we see the download directory to next year's smart contract lottery, FCC, I can even just copy this, paste that in here. And then it's in the constants folder, and it's going to be contract addresses dot JSON. And let's get the ABI file, we'll say const. Front and a bi file is going to equal and this is going to be nearly the same thing. So we can just copy paste that. And then we'll do slash API dot JSON. And now in our update contract addresses function, we can s
ay const, current addresses, equals and we can read again, in our front end, we can read from this file. So I'll usually start out with just two brackets. So that's like JSON compatible in both of these files. And so to read it, we're gonna say JSON dot parse, FS dot read file sync, we're gonna have to import, say const. FS equals require, I know we've used Fs extra in the past, but this one, we're just gonna use Fs, which is going to be our front and addresses file, we're going to read it in wi
th UTF eight encoding. So now this is going to be our current addresses. And we're going to update the list of current addresses with some new addresses. Because our contract addresses we want this to be chain agnostic, we would do something like for you know, and then the addresses on rink B, we could do 31337, and then the addresses on our local host, right, we want to be able to keep track of all the different addresses across all the different chains. So back in our function here, then we'll
say if if network, dot config dot chain id.to string in contract addresses that were config ideas in there, then we're just gonna go ahead and add this new contract address in there. But before we add this new address in there, let's just check to make sure it's not are already in there. So we're just gonna say if contract addresses of network dot config dot chain id.to string, this is so long, I don't want to keep writing that I'm gonna say const chain ID equals network, config that chain id.t
o string, and we're just gonna use chain ID. If chain ID and contract address then if we don't already have that includes raffle dot address. We're gonna go ahead and add this new address and then if the chain ID doesn't even exist, we're gonna go ahead and do contract addresses current addresses, equals or assuming current addresses of chain ID equals and then we'll just create a new array, raffled that out address. So we're saying if the chain ID doesn't exist in current addresses, we're just
going to add this new array in there. And then finally, now that we've updated its object, we're gonna write it back to this file, we'll say Fs dot write, file sync, front and addresses file. And then we're gonna do JSON dot string of five. So we're going to Stringify this JSON object, so we're just gonna go ahead and write it back. And then bottom module that exports that tags equals all and then front end. I cool. So we have a function to update the contract addresses, but we also need the ABI
. So we're gonna do date API, and we're gonna create another function async function, update API. And in here, we're gonna do the exact same thing on raffle equals await ethers that contract, raffle FX dot right file, sync, front and abi. It's just going to copy paste it front end, AVI file. And then to pass just the ABI, we can actually get it directly from this raffle object, we can actually just do raffle dot interface that format ethers dot utils, dot format types, dot JSON. If you look in t
he ethers, Docs, ethers has this contract dot interface thing which returns an interface which is different from a solidity interface. But it allows us basically just to get the API with this one line of code. So in our back end code here, now if you run h h deploy or H H node, we should automatically update our contract addresses in our API dot JSON. So let's go and try this. So we'll run h h node. So we'll start a node, right in this terminal over here, we'll flip back to the front end. And if
we open ABI to JSON, we do indeed, now see, we have the raffle API in this file. And if we go to contract addresses, we see on network 31337, here's our first address, right. And if we deploy to different chains, this will get populated with different network IDs, and then a list of addresses associated with them. So it helps make our front ends a lot easier to maintain, and bounce around and kind of test and work with. Now that we've done all this, we can actually close our hardhat smart contr
act lottery Free Code Camp, the hard hat project for this, and we're just going to have all of our terminals be in here. So what we're gonna do is we're gonna go down and directory CD dot dot, and we're going to cd into Oh, sorry, we're actually we're already in their CDs, hard hat, smart contract, lottery Free Code Camp. And then in this one, we're going to run hh node or yarn hardhat node. Now we'll have a local blockchain running so we can test everything that we're doing in the front end, ac
tually, I'm gonna move this up one. So now in our first area, here, we have our front end code running, then we have our blockchain running. And then in this one, we're just going to add, you know, whatever we want to add. Now, we can actually go ahead and hit this little X button here to close the panel. So that's just hiding the panel, these are all still out, they only get trashed when you actually hit the little trashcan. So we're just going to close the panel. But all those terminals are st
ill running, I promise back. So where were we? Okay, back to our function here. So we just automated the process of updating our API's and then updating our contracts as well. And now we can import these into our files. Now we can import them one at a time, it'd be like import API, from dot dot slash constants, slash API, or we could do something a little bit clever is we could export these in the same file. So if we create a new file, a new index.js, in here, we can import them and then export
them in this one file. We can say const, contract editor says equals require dot slash contract editor dot JSON, and then const API equals require dot slash API dot JSON. And then we'll do module dot exports equals API and contract addresses. So now once we export them like this back in our lottery entrance, we can import them just in one line. So we'll say import API comma contract addresses from dot dot slash constants. So we can just specify the folder instead of each individual files, becaus
e we have this index dot j s here, which basically represents this whole folder. Back in here, what do we have now? Let's uncomment this abi. Okay, great. We have the ABI we're importing it from our constants, folder, contract addresses, we have our contract addresses. And we're going to need to specify the network ID in just a second here. We have the function name here, which is going to be what enter the raffle. There are no params. So all we need to do so how do we get both the chain ID and
then Also the message dot value will change, it is something that we can get really easily with Morales, let's comment this whole section out one more time, just so I can show you something we can do import. Once again, we're going to get that use Morales book from react Morales. And what we can do is we can say const. Chain ID equals use ralis. Now, the reason morality knows about what chain we're on is because back in our header component, the header actually passes up all the information abou
t the Metamask to the Morales provider. And then the Morales provider passes it down to all the components inside those Morales provided tags concentrated equals use Morales. And I'm just gonna do a little console log chain ID because I want to show you what it looks like. So if we do a little refresh, and we're in the console here, we can ignore some of these warnings here, but we see the chain ID is actually 0x Five, well, because I'm on the rink B chain or the Grilley chain excuse me, if I sw
itch back to hard hat localhost, which you should know how to do from a SEMA fun we bet if you don't have hard hat localhost and your Metamask go back to that HTML font we bit follow that along. Okay, great. Now it's going to print this Oh x bla bla bla bla bla. So that might be a little bit confusing. But this is the hex version of our chain ID. Right. So let's switch to Etherium main net. Now we pronounce Oh x one, right? Oh, x one is the hex version of the number one. So chain ID gives us the
hex addition of the chain ID. So I don't want the hex addition, I want the actual number. So what I'm going to do is I'm going to say Okay, chain ID, your name is actually going to be chain ID hex. And we can do console dot log chain ID hex, but I want the number. So what we can do is parse a built in JavaScript parse int, CIN ID hex like that. Now if I go back, we'll do a little refresh here. Scroll away from the warning, we can see the one here. Now let's switch to hard hat, localhost. We'll
scroll down we see 31337. So use Morales chain ID returns the hex we parse it with Parson to get the actual number. Okay, great. So we can stick the chain ID into here. Now this raffle address is something that we're actually going to use a lot, we might as well have it be at the top of our code here, we aren't going to be changing the raffle address. So we don't need to put it in a hook. We are going to technically be changing the address when we change networks. But our header app takes care o
f re rendering and dealing with all that. So we can just make this a constant variable. So we can say const, raffle address equals, first let's check the chain ID hex and if there's a chain ID hex and if there's not a chain ID hex we're gonna do something else. Excuse me, we're gonna say chain ID hex in contract addresses. And actually, there's never gonna be a chain ID hex. So we'll do const chain ID equals Gen ID hex parsed, Parsons, chinati hex, and you might be thinking, hey, this, these are
both the same name. Well, what we're doing up here in use Morales is we're saying hey, pull out the chin ID object, and then rename it to chain ID hex and down here, we're saying, Hey, we're going to create a new variable called Chain ID. So we'll say contract addresses of chain ID at zero. So in here, we're saying this network ID and this address, otherwise, we'll just say no. Okay, we're getting there. Let's uncomment this, now we have the raffle address, and we can just stick it in here. All
we do now is the message dot value. If we remember back to our raffle, we actually set that fee dynamically. So we have in here we do entrance fee equals entrance fee, which is the parameter in the constructor. So we want to call this get entrance fee function. This is one of the ways we can send a transaction. And we can also send functions, one of the ways that we're going to do it right when our lottery entrance loads, we're going to run a function to read that entrance fee value. So how do
we do that? Well, we can use one of our hooks again, right use effect use effect can run right when something changes, we're only going to want to try to get that raffle entrance fee if web three is enabled. So what we can do is back up in here and use Morales will pull in that is web three enabled. And we'll have our use effect in our function, we'll just say if this is web three enabled, then we'll try to read. So we can go ahead and use this use web three, contract Wagan. Let's go ahead and j
ust copy paste this. And we'll use the same setup here. Except instead of enter raffle, of course, we're going to be doing get entrance fee. So we're going to get entrance fee. We need the API we got it raffle address got it. This is going to be the function name is going to be get entrance fee params nothing message that value, nothing. We're going to be calling this get entrance fee function. And now I finally show you how to actually call one of these in our contracts here. Use web three cont
ract, download our use effect, we're actually going to call get entrance fee. Now if we just call get entrance fee like this, and we say like, you know, const something equals get entrance fee and then console dot log something, what do you think's going to happen? And oops, I need to import, I need to import use effect from react. There we go. We look or logs, I don't see console dot log, something won't get entrance fee is going to be an async function. Once again, we need to wait we would nee
d to do a wait get into T, right? There's an issue we can't call await in our use effect. So what can we do? Well, we can actually make an async function, call it update UI. And then we can stick this inside of the async function here. And we can call update UI right outside of it like this. So now we go back to our front end, we do a little refresh. And if we scroll up, we still see nothing. Well, is web three enabled actually changes. So the first time that this runs, is web three enabled prob
ably is false. But when it turns to true, we want to we want to run this section in our little dependency array. We're going to add this in here, right? And the reason that it's false to start with is because of exactly what we showed in that manual header, right? What does it do? Well, first, we check to see after we do a refresh, if window dot local storage get item is connected, then we call Enable Web three, which will make this enabled. So in our lottery entrance, is what they're enabled st
arts off as false when we do a refresh. And then the browser checks the local storage says, oh, web three should be enabled, let's enable it and turn to true. So now if we hit save, and we do a little refresh in our console, we can now see the logged out entrance fee. So then we'll switch this to entrance fee from contract. Now, we also probably want to show this entrance fee on our UI, if we do let entrance fee, we'll say equals blank. And we'll take this and we'll update, you know, and we'll u
pdate this just saying entrance fee equals await entrance fee. Cool. Now we have this as kind of a global variable, we can add it in here. And then let's even do a weight entrance fee. But this whole thing in parentheses, and then do.to string, and we can even console dot log entrance fee. Now we're adding in a new browser. But there's still an issue here. Let's see if you can spot it, we'll do a little refresh. We don't see the entrance fee in the UI here. But we do see it good console dot log
out, right. And again, this is going to be in a way here, what is going on here will use effect is going to rerender our browser, right? And that's what we want is what three enable goes from false to true, our browser re renders watch, once we get our entrance fee, does our browser rerender? No, it does not because entrance fee is just one of these normal variables, right. So we want to actually change this from being just a normal variable to being a hook because entrance fee does get updated,
but it's not triggering a rerender. So we actually want to change this to being what's called a use state hook. So you can read some more on the documentation about the using the state hook, it's kind of the same as doing let entrance fee, you know, equals blah, blah, blah, and setting it below. But it also will trigger a rerender for us. And to do it, we actually do const entrance fee, comma, set entrance fee equals use state zero import use state from react as well. So basically, entrance fee
is going to be our value, right, so if we do console dot log entrance fee, it's going to print out the entrance fee entrance fee is going to be the variable we call to get the entrance fee, the entrance fee is going to be the function we call to update or set that entrance fee. And whatever that this entrance fee variable is set, we trigger a rerender. From the front end, we have the state or the actual variable in the function to update it. And then in the use state here, we just give it its s
tarting values we're saying entrance fee is going to start out as zero. So now that we know that, let's go back down here, and instead of saying entrance fee equals this, we can say const entrance fee from call equals away entrance fee.to string and then we can say set entrance fee to this entrance fee from call. And now when we set the use state, we're going to trigger a rerender. So entrance fee will actually be populated. Now if we go to our browser, do a little refresh here. We can see that
the entrance fee has indeed been re rendered here and we can actually see it here. We see the console dot log of zero here even though we're doing console dot log entrance fee because this set entrance to function hasn't finished running it basically. So we're just gonna get rid of that line will refresh and Bada bing bada boom, this huge number is kind of gross. We might even want to update it so that it looks a little bit nicer. So once again, we can import ethers, ethers from ethers. And down
below, we'll do a little ethers dot utils dot format units. And we'll do entrance fee from call and we'll do a comma and type in. And if we refresh on the front end, now we can see, entrance fee is 0.1. So we can even label this we'll say entrance fee, blah, blah, blah. Now if we do a little refresh on the front end, entrance fee 0.1 E. Finally, we have the entrance fee, and now uses finally on our function to enter the lottery. So let's finally uncomment this out. And for message value, we're
going to want to use this entrance fee. And I'm realizing it's actually better to store this in its raw to string format. So we're going to undo this part that we just did. We're going to add it down here. So we're going to ethers, that format units, entrance fee, comma, ether, like that. So that like that, and let's comment this back out real quick. So that at least in the UI, it shows up at 0.1. But on the back end, we're actually going to save it as its raw, and have way value. So we're sayin
g that we have this entrance fee and what we can do uncomment, this, we can just grab this entrance fee, and plop it in here. So we need to make a button that's gonna do that. Now again, we want to make our code that all this works, even if we're connected to a supported chain, though. So before we even add this, right, if we switch from hard hat to like, Aetherium main net, do a little refresh. We're getting kind of get an error here, because we're calling get entrance fee.to string on an addre
ss that doesn't exist, right? So it's gonna get really confused and be like, hey, what, what are you doing here? Let's add a little button here so that we can actually enter the raffle. Before we actually do that, let's make sure that we can only call the function so long as there actually is a raffle address. So we'll do raffle address. And we'll do this ternary operator once again. So that only if this raffle address is valid, right? And it's not, no, we'll add all this code here, right. So we
'll say if the raffle address exists, we're going to do some stuff. And for now, we can actually just copy paste this line, stick it in here. And then otherwise, we'll say div. Excellence div, close it off. We'll save reformat, great. We'll say no raffle address, detected. Now we'll just do all of our code in this section up here. So we have this little div here, which is great. Inside of this div, let's add a button. Button button, we'll save it got a little button here, we'll have it say, ente
r raffle. And we'll say on click, well, we're going to do some JavaScript. So let's do some JavaScript, we want to call an async function async function. So I know the double brackets is going to be confusing, right. But these brackets allow us to do JavaScript in our HTML, or JSX, or whatever. And these brackets represent this function, it's going to an async function. And we're gonna say, await, enter raffle. And that's it. So let's go back to the front end. Now we have a little enter raffle f
unction. If we do refresh, let's just make sure our account is reset here. So we're gonna go down to settings, advanced, reset accounts, yes. I hit ENTER raffle. metamath does indeed pop up. And we can go ahead and confirm. Awesome, okay, we can now enter our raffle. We're doing incredibly well with this. As you saw, we just got that pop up. And that was pretty much it, right? It's not very helpful for the users who are following along with this to look at this and go, Okay, did it go through? O
r we did it fail, like, what, what just happened? So what we want to do is create what's called notifications, right? We want a little pop up saying, Hey, you sent your transaction, great job, we're going to use a library. Again, we're going to use the web through UI Kit, which comes with some notifications that we can go ahead and use. So if you come to this little interactive thing, which is right in their GitHub, there's a whole bunch of stuff in here. And you can actually click around and pl
ay with different buttons and different things. And you can actually go ahead and even go to docs for each one of these. And you can go show code. And you can literally like copy paste code into your project, like whatever you want to do styling and everything for us. So back in our app dot j s, we're going to add import, no to vacations provider from web three UI kit and inside of the Morales provider, but outside of the components, we're gonna do notification provider notification provide Add
it like this. So it goes Morales provider notification provider component. So wrapping our component in this notifications thing, and that's notification provider not notifications. And this is going to allow us to actually make notifications back in our lottery entrance. Back in our lottery entrance, we're gonna scroll up to the top, we're going to import a hook those notifications called us know, to the occasion from web three UI kit. And this use notification gives us this thing back called a
dispatch. So I'm gonna say const, dispatch, equals use notification. So use notification returns this dispatch, and this dispatch is like a little pop up that will give us so down here, when we call this enter raffle, we're gonna give it a little some parameters in here, we're gonna say on success, these functions come with onsuccess, they come with onComplete, they come with an error, all this stuff. And when this function is successful, we'll do handle success, we'll create a new handle succe
ss function that will handle the success. And this is Patrick from the future coming back to show one additional point. I know I mentioned it, but it is really good to add this on error, colon error console dot log error for any run contract functions, even the reads, If any of your run contract functions break, you won't know. So definitely want to add this on error error console dot log error to all of your run contract functions. So up here, before the return, we'll create a new const handle
success. We'll say this is an async function async function that takes the transaction as input parameters. And remember, you can turn functions into constant variables. And we'll say await TX dot Wait, one, so we'll wait for that transaction to go through. And then we'll create another function called handle new notification, dx. And you'll see why I'm doing it like this in a minute. And we'll say const and Linoone notification, this is just going to be a synchronous function because we don't n
eed it to be async. And we're just going to call this dispatch, we're going to set up this notification basically. So we'll say notify, or dispatch, and then we'll add the parameters in here. So it takes an object as a parameter, we'll say type info. Message, it's going to be transaction complete, the title is going to be TX notification. Jose, Shawn, we're going to say, top are and then icon, we're going to say a little bell. And you can find all this stuff right in here, type icon position, yo
u can read all about the different parameters you can kind of set this up with so handle new notification handle success. So we're saying, enter raffle once this transaction is successful, call this handle success function, which is going to call handle new notification. Okay. And you'll see why we split this into two instead of just having handle success. Also do the dispatch. When we press our enter raffle button, we're going to call enter raffle is successful, we're going to call handle succe
ss. We're going to wait for that transaction to finish Yes, it passes a parameter to our handle success function. And then all we're going to do is we're going to call handle new notification. And we're going to dispatch we're going to launch one of these notifications. So back here, let's hit enter raffle. metamath pops up will confirm. And after it completes, we get this wonderful transaction notification transaction complete, right. So we've let the user know, great job, you've submitted a tr
ansaction. Great work. So this is great. We're giving our users some helpful pieces here. Now let's add a little bit more here so that the users know what else is going on with this lottery. But we need to display a little bit more data, right, let's display how many people are in this lottery. How many people are in this game. And we can do that. Of course, because we have a number players command. We also probably want to get the recent winner. And we can do that as well. Up here, we're going
to copy this get entrance fee, we're going to create another one called Get num players. And this is going to call go back to raffle dot soul. It's going to call get number of players actually so let's just call it call it the same thing. Get number of players and we're going to call and get number of players. And to store this value. Once again up at the top. We're going to copy this line, paste it right and we'll do non players. And then we'll do set num players. And then we'll copy this line
again. A recent winner so we'll do recent Winner. Winner will do Set, recent winner, then we'll copy this again, instead of getting number players will do get get recent winner. So we'll call it get recent winner get recent winner in our use effect, let's do more than just get the entrance fee, let's get everything. So we can say const num players, from call equals, we'll do a weight, get number of players.to string, and then we'll do set set num players do like that. So we'll do set num players
, num players from call. And then we'll also do const recent winner from call this is going to be await get recent winner. And we might need to wrap this to string but I think I don't think we need to. So we'll do set recent winner paste that in here. So now we've had a number of players, we've added a recent winner. Let's come back down here. We have an entrance fee. Let's go ahead and do number of players. And we'll add number of players or what did we call it? Oh my god, we called setting emp
loyers twice oops, it's called non players, scroll down players gonna be non players, and then we'll do recent winner. And then we'll add in the recent winner. Awesome. Okay, entrance fees 0.1 eath number of players to recent winner is nobody here. And if we go ahead and we enter the raffle metamath pops up. We'll go ahead and confirm. Once a transaction goes through, we'll get transaction complete. And if we do a refresh, we see the number of players has updated. But we had to refresh which is
kind of annoying, right, let's enter the raffle again, we'll go confirm transaction complete. But this didn't rerender. Right. So we want to set something up so that we automatically rerender. And guess what's going to do that the handle success that we were talking about before. That's right, all of this update UI stuff, we can actually pull out of the use effect. So we're going to copy it all deleted there. And we're going to have it be its own standalone function like this. And then in our ha
ndle success, whenever this successful transaction goes through, we're going to update the UI, right? So handle success handled new notification, and we're going to update the white. So now if we go back here, let's enter the lottery. Let's confirm, we see we get the five and we get transaction Notification. Now we want to test getting a recent winner here. So what we can do, actually back in our hard hat project is we want to create a new script. And I actually already created it for you, that'
s going to mock the channeling VRF. And that's going to mock being a keepers. So all this is really doing is pretty much exactly what our tests were doing. If you want to pause right now and look through this yourself, pause here and add this mock off chain, which is both keepers and VRF. Or you can just go to the GitHub repo here. Just go to the GitHub repo for Lesson Nine. It's already in scripts go down to scripts Markov chain, you can just copy paste it here. Because I want to test that that
recent winner. So in my hard hat, smart contract lottery, so we'll do yarn, hardhats run scripts, slash mock off chain dash test network local host, we're going to mock you know, basically picking a winner from an upkeep with Request ID one, we're on a local network. Okay, let's pretend the recent winner was so and so. And what we can do is we can do a little refresh here, we can see we have a winner updated. Boom. Now we're gonna clean up the UI. But I want to talk about a couple of things. Be
fore we do that, because we're almost done with this section. Something I want to make really clear because it confused me a little bit is that this onsuccess isn't checking that the transaction has a block confirmation, it's just checking to see that the transaction was successfully sent to Metamask. So onsuccess checks to see a transaction is successfully sent the Metamask. And that's why up in that other function, we do TX dot wait one because that's the piece that actually waits for the tran
saction to be confirmed. Right now we're using Morales to make once we call that mocking script, I had to refresh the browser to see the winner here, right and number of players obviously got reset to zero, which is great. That's not ideal. Ideally, we want our UI to just automatically update when some event gets fired. In our raffle contract, we get this event emitted. Instead of in our code doing this await success here. What we could do is we could set up a portion to listen for that event be
ing emitted and update the front end accordingly. With that knowledge we can also listen for the winner event being emitted. We could update our front end instead of having to refresh it's your cue Yes, and you want to see if you can add to this right now, I highly recommend you do. So we've pretty much finished all the functionality. And wow, you've learned a ton in this little bit, right? We've learned about use effects use Morales, all these hooks, all this stuff, and we've got a front end th
at very nicely handles interacting with our smart contract. The only thing is, is it looks really ugly. This is kind of gross. So let's make this look at least a little bit nicer. There's two things to think about when it comes to building these front ends. There's component libraries, like web three UI Kit, which we're using, which gives us kind of like components that give us, you know, blocks of code, like this connect button that are already formatted for us. And then there's CSS libraries t
hat actually will help us format the rest of our stuff here. So we're using one of these component libraries. We're also going to use one of these formatting libraries, and the library that we're going to use is tailwind. And the reason that we're going to use tailwind CSS is because it's really popular. If you want to learn CSS, there's some wonderful resources that you can use to learn CSS web three schools is one that I've used a ton. So there's going to be a link to that in the GitHub repo a
ssociated with this course so that you can make your websites look pretty when formatting stuff but we are actually going to work with tailwind because it's going to make us doing CSS stuff a lot easier. Since we're using tailwind with next Jas. There's actually a wonderful little guide here for installing tailwind with next Jas. And we're gonna go basically go ahead and follow along with this. This link is available in the GitHub repo associated with this course with this lesson. So we've alrea
dy created our project we've seeded into our project. Now we're gonna go ahead and install tailwind npm install dash D instead, since we're using yarn, we're going to do yarn or pop this open, green new yarn, add dash dash Dev, paste those three in tailwind CSS, post CSS and then autoprefixer and it's the three of these that are going to basically make up tailwind with next Jas. Once we have those we're going to basically init tailwind and make a config file for tailwind. So we're gonna do yarn
tailwind CSS and it does p yarn tailwind CSS init dash P will run that. This is going to give us this post CSS dot config dot j s and this tailwind dot config dot j s and what we're going to want to do is literally just hit this copy button, and we're going to update our tailwind.config.js tailwind Jas so that it says okay, all of this stuff, anything in Pages anything with.js.ts dot JSX or TSX. And anything in these components, anything in those two folders is going to be considered tailwind do
uble. We want to use tailwind on these two folders. Then we're going to add the tailwind directives to our global CSS files. So if we go back, we're going to styles Global's we're going to overwrite everything in here with ADD tailwind base and add tailwind components at tailwind utilities. And this makes it so that our global CSS file uses tailwind. Now, you'll see like unknown rule at tailwind, what we can do is we can go to components, what we can do is we can look up this post CSS language s
upport extension, paste that in here, boom, let's go ahead and install this. And now we get those little underscores to go away, which is really nice. Now, per usual, we can just do NPM, run Dev and start adding tailwind to our divs. Now what tailwind does is allows us in our divs to set everything as a class name, and then just set some real minimalistic text in these class names here. So let's look at our smart contract lottery here. We've just tailwind did it. So it already has been updated a
little bit. Let's update our header here. Well, let's see. We want to give our header a border from the tailwind. We'll do a quick search. Look a border we can see all this border stuff like border width border this border that say we want a border on the bottom, we can see we can get a border on the bottom with something like this. Let's do border on the bottom with a width of two pixels. We just do border b two. So I'm going to copy border B to do border b two, I'm going to save it and what w
e need to do for our CSS and everything to take effect. Go ahead and kill the front end. And then we'll rerun it with yarn Dev. Go back to our front end now. Give it a little refresh and Okay, cool. Now we have a little border here. So we're starting to add some stuff and it's just not a whole lot yet. Oh, and then we can also add tailwind to me go to Extensions. We can also look up tailwind. There's a tailwind extension here. So I'm just going to add a whole bunch of stuff in here. We're gonna
do flex, flex row. We're gonna make our decentralized lottery and h one which stands for like header one. Do class name equals, we'll do the y dash force. We'll give it padding the top of form the X padding on the x axis of four. We'll make it bold font and we'll make the text three XL size. So we'll make everything bigger. Cool. Then we'll do one more, we'll wrap our Connect button in a div. So we'll say div class name equals, and we'll give it a an automatic left margin. We'll do py too. So so
me y padding, some x padding. See what we have done. Okay. Now if we zoom out a little bit, we can see, if we close this too, we can see now our Connect button is on the side here. And they're kind of separated like that. And I think that looks nice. So we're going to keep that now we're going to go back to our lottery entrance, we're going to change this up just a hair, we'll say div class name equals P. Five, we'll make our button look really nice. We'll say class name equals background blue 5
00. When we hover over, it will say, background blue 700. So now if I just say that, and when we hover over it, it looks a little different, that's really nice. We'll say text is white, we'll say the font is bold, we'll give it some white padding, I'll give it some x padding, we'll have the bunbee rounded, and we'll give it a margin left auto, now looks a lot better, right? That's a lot prettier. We're just going to be doing some basic CSS here just to make it look a little bit nicer, right, but
just that by itself already made this lottery button look a lot cooler. Now some functionality that we didn't add here. So we need to add a disabled, kind of like what we did before. And in our enter a raffle it comes with, like I said, is loading and it is fetching. None of our transaction is loading or fetching, we'll just make this disabled. So we'll say is loading or is fetching this will be disabled. Right? Now, if we go back to the front, we hit enter raffle, go ahead and hit confirm, we
can add a CSS for it. But when a transaction is loading, they will not be able to click that button anymore, which that's something else pretty that we want to do speaking of is loading and is fetching. When it's loading or fetching, we probably want it to have that like little spinny thing right when we hit it right now. And mash is pops up. And we can confirm but it would be cool if it had like a little spinny thing here, right. So you can usually just Google like how to add spinny thing or st
uff like that, and you'll get something. But you can again, you can just copy paste this from my code, I'm going to show you what I ended up doing for this section. And we're gonna say is, if is loading or is fetching. And we're going to use that ternary operator all the time, then in here, we're going to do a little div. And otherwise, we're going to do a different div for loading or for fetching, we're going to add like a little spinny thing in here. So we're going to add class name equals. If
we're loading, we're going to add this little spinny thing, which I'll show you what it looks like in a second. And if we're not loading, we're just gonna do enter, raffle like that. So we'll come back to the front end, see answer raffle, we'll click the button. Now we get this cute little spinny thing, confirm transaction goes through. So anything goes away. Nice. Well, let's put these on different lines. So we'll just do so those will be on different lines. Now boom, entrance fee, number play
ers recent winner, once a lottery now will confirm transaction complete number of players has gone up and we have done it. Now this looks a lot nicer. It's clearly not perfect, but it's much easier to read than kind of that lump that we had before. And the reason I wanted to show you this was really just kind of giving you your footholds for making these look a little bit nicer. This definitely isn't a CSS course. Oh, wow. Okay, this is phenomenal. We have an app that we really like. And we're l
ike, you know what, we want to deploy this bad, Larry, let's talk about how we can deploy this, this section is going to be optional, okay, because I'm going to deploy something to rank B and deploying to test sets can take a long time. So we're going to deploy our contracts to rink B. And then we're going to deploy our website to a hosting provider. So first, let's talk about hosting providers for a quick second, if we want to host our beautiful website that we just created, there are ways to d
eploy it using things like for cell or Google Cloud, or AWS. Nettle. Phi is another really popular one there, all these different places that we can deploy our application. Now, the thing about these though, is that these are all centralized deployment places, having a centralized deployment application can still be incredibly important, right? If we look at ether scan for a second ether scan is a centralized application right at the end of the day, but it's still one that we've been using a lot
. However, if we want to have a front end that's decentralized. Well, that's a little bit harder. The more important thing for us is that our back end, our smart contracts are decentralized, right? That's the most important thing because that will give users the ability to interact with our logic in a decentralized way. But maybe we also want our front ends decentralized. Now at some point we will still use a centralized service Like VSL to deploy an application, and I'll show you why when we ge
t there, there's some features that right now, they're really just hard to do without like a really solid centralized back end. What's important to keep in mind is that our back end, the logic of our contract is on a decentralized blockchain. So even if we host the front end on a centralized hosting provider, using some type of centralized database to make the front end easier to work with, the logic of the application is decentralized. And that's the most important piece. So I'm going to give y
ou some tools later on, and how to introduce more of these feature richness. If you choose to do so doing so will add a centralized component on your front end. And it's something to keep in mind, depending on how you want your architecture. So when doing that just be absolutely sure that the smart contracts on the back end are deployed are decentralized on one of these blockchains. Now, we'll learn about some of those centralized ways to do that in a later section. For now, let's learn how to d
eploy this front end in a more decentralized way. And the tool that we're going to use is a tool called IPFS. 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 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 and the GitHu
b repo associated with this course. But we give you my basic take on it. So we have our code, 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, so you can get 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 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 a
nd 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 asked the network, hey, I want to get this hash. 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's the file associated with it. Now, you mi
ght 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 decentrali
zed 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 the can't do smart contract, 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 hash, it's kind of central
ized 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 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 Manuel Wait, 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 using something like brave or I think Firefox to some this IPFS router is automatically built it. But if 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 gonna do is we're gonna have you install the IPFS desktop, so you're gonna 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 regular desktop app. Well, once you install it, you might see I
PFS is running, you can restart stop, you can do all this stuff, we're gonna go to the file section, and we're gonna get a little pop up 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 dot config dot j s, right? It doesn't matter, just import something. And now in here, we have this next dot config
dot j s or whatever file you import it. 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 dot dot slash slash, and we paste it in, we hit enter, we can give our browser access to actually rendering IPFS URLs. If 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 get IPFS companion, there's a Firefox install for Chrome brave, blah, blah, blah. So I'm gonna 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 on a little browser companion, we can see like import, we can see stuff about our node, if we click our node, we will see a very similar setup. But now that we have the companion in our browser, we can copy that Cid that hash. Now brave, we can just do use brave local IPFS node, and will automatically get dropped into the file. Now, if IP
FS 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 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 we'll do HTTPS, slash IPFS, slash 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. So we're going to deploy our website to IPFS. So that anybody else who wants to pin this can, and we will now have the ability to have an incorruptible, in unputdownable website, which is just awesome. We're going to learn how to do this the wrong way first, and then we're going to use a tool that's going to make it a lot easier for us. Okay, so first, let's go t
o our website here. And, and if you want to deploy to rink B, go ahead and feel free. Just remember to make sure that your contract addresses file updates accordingly. Okay. Now, next, Jas has the ability to create static websites. And that's going to be an important term to know we're going to make a static website. At the moment, we don't want our website to be tangled with any server stuff. And the reason we we don't want it to be tangled with any server stuff is because if our website runs w
ith server stuff, and we deploy it to IPFS, will IPFS doesn't have the ability to run any code, it just hosts code. If our front end has any server stuff, it won't work. Now, in its current state IPFS can't come to our project and know what to do, right, it doesn't know how to do yarn dev can't do yarn Dev. So we need to put all of our code into its static equivalents. So to do that, we're gonna do yarn build. And if again, if we look at our package dot JSON, it comes with this build, which just
runs next build. And running this build command is going to build our code, what's called like a production build, creating an optimized production build here. And we'll get something that looks like this. And we can see this point down here. Static, automatically rendered as static HTML uses no initial props. There's some server based applications that next Jas comes with that if we use them. Our static build won't work. And actually, you'll see when we run yarn, next export, it'll fail if you
have any that non static stuff. So let's Go ahead and try yarn next export. And let's see if it fails, it didn't fail, we now have a new folder called out. And this is our folder, that's just pure static code and that we can use on IPFS. In a later section, I'll show you what it looks like when you don't use some of those static things. Both Morales and next Jas have the optionality to not have static code. So we'll just want to keep that in mind. So now that we have this out folder, we can go
back to IPFS. And we can import a folder, we're going to import that whole folder in here. So hit that hit that import button and go to the folder. Where that is mine is in next year smart contract lottery out. So now we're going to upload this to our IPFS node. Once it's done, we'll get this little checkmark. And we can go through IPFS files and see our output here. What we can do, let's go ahead and pin this to our node, we'll pin it to our local node here. And now once it's up, we can copy th
e CID and go back to brave or chrome or whatever. You type in IPFS colon slash slash, paste that in there. And we immediately get dropped into our smart contract lottery in a browser. And we see hi from lottery, no raffle address detected, because right now the way I set mine up Was it only works with, you know, our local hard hats, let's connect our Metamask we'll hit the connect button, connect, and voila, we are right back where we were. But with our data stored in IPFS, we can enter raffle a
s long as our node is running a confirm. And we see exactly what we get in our local browsers. So this is phenomenal. Now that I've shown you how to do this, this is the manual way of adding our code to IPFS. Let me show you the easier way of adding your code to IPFS we're gonna go to this site called fleek HQ. Go to fleek.co. And to get to it, I'm going to turn my my IPFS companion note off because of some of the oddities with working with brave but now we're here@flickr.co fleek.co makes it ea
sy to to deploy websites and apps to the new open web permissionless, trustless, censorship resistant, etc. I like to think about it as kind of like an auto deployment for our websites. And additionally, it does some things to help out with that problem. I was talking about how we want to get other nodes to pin our data. So it helps us out with that. So let me show you what it does. So let's go ahead, we'll sign up. And why don't you know, you can sign in with GitHub. So if you have your GitHub,
definitely want to sign in with GitHub here. Because we're going to use GitHub to actually help us automatically deploy. So we'll authorize fleet to work with our GitHub. You've authorized your GitHub, let's go ahead and add a new site or add new site. Now we can use fleet to just automatically deploy websites, once we push them to our GitHub. So we can come to our GitHub once again. And click the little plus button, we'll do a new repository. We'll call this next Jas smart contract, lottery Fr
ee Code Camp. We'll make it public create the repository. Let's push all this code to GitHub. We did it once before, let's do it again. We'll do git add, we'll do a little dot, then we'll do git commit minus m, say like initial commit or whatever. We'll do git remote, add origin, and then we'll grab that URL, paste it right here. And then we'll just do git push origin, main. Now we go back to our application we see it in here we can do is back in our fleek. We can connect with GitHub, we're goin
g to say only select repositories, we're only going to do this next js application, this next JS get we're going to install an Authorize. Authorize Great. So now we're going to pick a repo we've picked a repo, we're going to choose this application. And we're going to use IPFS as our hosting service. And now we're going to add our information in here. So we're going to use the main branch. Here's the repo. There's gonna be our framework is gonna be next Jas. So we're do fleek next. Jas, we're us
ing yarn. So we're gonna do yarn install, and yarn, run build, and then yarn run export. If you want you could also just do yarn, yarn build and yarn run export, those are gonna be the same thing. Publish directory is going to be out and then we just hit Deploy site, yarn, next export as the last command, not yarn, run, export. The accident did the wrong one, you go over deploys. Click on this, go to deploy settings and then Edit Settings and then just change it to yarn. Next, export save. Then
we'll go back to deploys and trigger deploy, if you did the wrong one that was just a learning opportunity for you to learn where the settings are after you deploy. And what this is going to do is we're going to do to deploy, it's going to run those three commands yarn build, yarn export, it's going to run everything. And then it's going to deploy a site for us both on IPFS. And it's going to give a regular URL that we can use for normies, if you will. And while this deploys, you'll actually see
down here we have this thing called file coin di D in deal proposal, Cid IPFS. Like I said, we need other people to host our node. File coin is actually a blockchain that helps you pin your data and uses decentralized storage to do so. And fleek helps you create those deals and helps you pin your data with this filecoin Blockchain filecoin is one definitely to take a look at. And then after a while, you might have to wait a little bit. And once it's done, get a little deployed website, we go ba
ck to hosting, we click on our thing we can see we have like a little website here. And if we click it, we get a normal URL for connecting and interacting with our website, you might even see this little IPFS thing which will connect to your IPFS node. And additionally, we scroll down in here we can see current IPFS hash, so we can just stick that in, um, and Bada bing, we have an IP Fs deployed application. Now what's cool is let's say I make some changes, you know, I'll go to lottery entrance.
And I'll do, I'll scroll on the bottom to recent winner, I'll make a new div. What a close the div off, we'll save git add dot Git commit minus m, add a dot git push origin mean. In our GitHub, we'll do a little refresh, add a.as, the most recently added one, go back over to fleek. Go back to hosting click on the section that we just made go to deploys, and you'll see there's a new deploy going through. So it automatically deploys your new site, it'll automatically create a new IPFS hash for yo
ur new data. However, it'll still be on this holy bird, you know, or whatever your URL is here. And this is kind of just a router for IPSs. So that people without IPFS connected can also connect to this still. And now that my application is done, pushing automatically, with fleek, we can see what's up being post in my application here. Now, like I said, filecoin isn't going to be a technology, we're gonna go too deep into introduce ourselves. But like I was just saying IPFS does have this limita
tion. It doesn't have data persistence, you have to have people pin your data, in order for it to stay distributed, and stay decentralized. File coin is a blockchain dedicated to keeping this data, both decentralized and persistent. And to give us a better understanding of filecoin. We actually have Ali here to give us an overview. Take it away, Ali. Hello, I'm Ali, and I'm a developer advocate here at the filecoin Foundation, which works closely with protocol labs and IPFS. Just a quick note, p
rotocol Labs is our r&d arm. So it works on creating tooling and technology for a truly open and democratic internet and web. And it's building out some of the foundational tooling like IPFS, and filecoin, which are two separate projects to enable that. And hopefully, today, because you're here to build, I want to impart on you the knowledge and tools you need to get started with both of those projects. So as anyone that's kind of played around in this ecosystem, or tech, in general would know,
data is an absolutely essential part of our daily lives. And not surprisingly, it's also a super fast growing field in web three, and one, that's fundamental one, and it's one of the fundamental necessities of the decentralized web stack as well. So the current model of centralization that's grown up, and basically out of a lack of an identity layer on the internet, is one where only a few big companies offer storage, and only a few entities hold our data for authorization purposes. And this is
an obvious problem, both in terms of being an attack vector for data mining, so without data, getting leaked through insecure service to third parties, and also creating a data resilience problem. So whole services go down every time one of these companies servers does and we've definitely seen that. So it really leads to the question, why aren't we designing the web for the autonomy and resilience we need in the first place? And how do we store data in a way that aligns with both the original v
ision of the internet as an open place for knowledge sharing and collaboration, and, and, and in a way that agrees with the web three mission as well. So these are the core problems we're solving with IPFS and file coin. Firstly, IPFS is a distributed system for storing and accessing files, folders, websites, applications and data. And it's designed to be able to work even when the networks between planets, so it's a distributed by design, it has no central authority servers, and it's designed t
o be offline first for resilience. And it's not just a fancy name for another peer to peer network either. Because the nice thing about the IPFS protocol is the standard it uses for addressing content on the network. IPFS is unique because rather than using traditional methods we might be with familiar with from the web, like those are location parts that point to a particular HTTP address where your content may or may not be available and stored. IPFS uses content addressing so content addressi
ng means that each piece of data, each meme or even full file system has its own unique cryptographically verifiable fingerprint, you might call it. So if you change even one pixel of your main image, for example, then the content ID or Cid associated with it also changes. So importantly, this hash function is also upgradeable. So let's say quantum computing breaks out current secure hash algorithms, we can upgrade the standard we use. And it means you will always get the same content returned b
y an IPFS. Cid as what you expect. So this is fundamentally important, because when you don't have to care where the data comes from, you open up the web to massively distributed storage systems. Hello, decentralization. So now we have a really important and valuable protocol that enables distribution at scale. And it provides verifiability of data to serve and retrieve content on the web. And not just for web three, either, but also for all web, or tech use cases. The problem is, and it's one t
hat the early internet also faced, who's going to ensure the persistence and permanence of all this data on the network. So unless you're running your own nodes 24/7, or your content is really popular or other nodes decide to altruistically store your data. Because I think it's important, then this data can become unreliable because they're no longer actively hosted on any nodes on the network's. So to avoid this, you could also turn to a pinning service that you pay to keep a copy of your conte
nt around. Unfortunately, the problem with this though, is that we're heading back towards centralization of data. And we're creating new data silos with this solution and losing the trust lessness and resilience we're looking for. And these one a bad solution prior to file coin, and it's why they sprung up initially, but we want a better solution. So this is where file coin comes in. So far coins architecture, then designed to leverage a crypto economic incentive model together with cryptograph
ic proofs in order to ensure data is stored persistently, highly reliably and verifiably. It uses these cryptographic proofs to also enable smart contract based permanence. And that means that it's designed to be as permanent as you, the data owner want it to be. It's your data, so it's your choice. It's also designed to enable internet scale capacity. It's currently the largest distributed storage network in the world with over 18 million terabytes of capacity available, which is apparently abo
ut 135 copies of the European Union's nuclear program, CERN's data which, which is kind of a fun fact. It's also file coins also designed to be and stay hyper competitive on pricing due to its market economics. And this comes down to storage deals. So to make this network feasible, filecoin uses storage deals. And these include two main consensus mechanisms that ensure both rewards for good actors in the system, and penalties for bad actors. So when you make a deal with one or more storage provi
ders to store your important data, the provider generates a proof of replication. So this proves that the storage provider is storing a unique copy of your original data over time to make sure that this data is persisted. These storage providers must prove that they still have random subsets of this client data and they create proof of space times. And these proof this proof of space time is something that is stored on the blockchain. So anyone at any time can also check that this is true. And i
t also makes up the mechanism by which miners are rewarded or penalized because you have to stake Phil on the network in order to become a storage provider. So when a storage deal comes to an end, or user can you can opt to let it expire or renew the deal. If you opt for renewal, then the providers again bid to host this content. So this creates an efficient market for pricing a continual efficient market for pricing as well. It can even go negative. So the storage provider can even pay you to s
tore your data if it's an important data set due to some of the block rewards that are being offered by the filecoin Foundation as well. So these mechanisms are what built in not just data permanence, but data timeframes, sovereignty, too so it's your data, it's your choice. You can decide you want to store your data for five minutes or 500 years. It's also your choice over how much resilience you want to have that data so or how many copies of that data you want to have and with what store to p
roviders. So this allows you to comply with regulations like GDPR. And there's a growing number of tools in the ecosystem like murmurations bit screen that are allowing for you to do this filtering. But it also gives you some guarantees that your data, you know, if one storage provided goes down, you know, surely not 10 of them are going to go down. So that's a guarantee for your resilience there as well. And this is why IPFS and filecoin are great complements of each other. So IPF s gives you t
hat benefit of content addressing file coin gives you persistent guarantees that even if your computer or your favorite IPFS pinning service where to go away, the content persists. Just as a quick final note on these concepts as well, IPFS and file coin is separate projects, as I mentioned. So IPFS is a protocol much like HTTP, whereas file coin is a blockchain. So IPFS is also storage layer agnostic, you can combine it with the storage layer of your choice. And while file coin was specifically
designed to complement it, and we think is a great choice, you can also store your IPFS data in the cloud or an other storage solutions as well. So hopefully, you've got a good baseline for why you'd want to use IPFS, and filecoin. And for those engineers out there that like a challenge, and are interested in working on the base protocols and code of IPFS, and file coin, which isn't always easy for the average user, I'd encourage you to go and take a look at the project docs and get hubs and som
e of the associated grants available for extensions to these open source projects. And this is a great site here if you want to get more information into the nitty gritty and really dig into the code behind IPFS and filecoin. And extend some of that. For those of you that just want to build out of the box though. And this is definitely a camp that I often fall into. I want to talk about some of the dev tooling and storage helpers that make it easy for you to get started. So firstly, Flake Flake
is one of my favorite IPFS dev tools. And projects Flake is a CI CD tool that you can use to deploy your apps for free as simply as easy as you would with some of the web tools you might web to tools you might be familiar with like Netlify oversell. The big difference, though, is fleek uses IPFS to host your site or app. And it even offers an AES domain routing on their platform. So if you're deploying a front end app, I would encourage you to use fleek to make it more distributed instead of som
e of the traditional web two tools. It's just as easy, I promise. So another one of my favorite tools is NFT storage, storing your NFT metadata immutably and persistently, as you already probably know, is integral to keeping the main value proposition of NF Ts, then on fungibility. So if you're not storing this data on chain, which obviously can become pretty financially unviable for large files, then this is exactly where NF T storage comes in. So it was specifically created as a public good to
archive and persist NF T data. So it's free. And it takes care of the complexity around firstly creating an IPFS Cid for this metadata, and then making automatic deals with filecoin storage providers. So it does this with at least eight storage providers. So eight times redundancy and it does it with a multigenerational timeframe. So it automatically renews those deals. Because it's a public good, it's all free as well. And it's also super easy to use, because you just need because it's a JavaS
cript service. So you just need to say import that as an NPM package or JavaScript library and then call the API and NFT dot storage takes care of the rest. For data that isn't NF T metadata as well, we built web three dot storage, web three storage is designed to give you those same web two benefits. So similar to NF T dot storage, make it super easy for you to use. And it's got JavaScript and go client libraries. While giving you you know the power of IPFS and filecoin of decentralized storage
and IPFS content addressing so it's got one terabyte after terabyte, one terabyte of free storage with that. So try that out if you're not just like trying to store and obtain metadata. The next tool is a bit more advanced. It's called textil Palghat gate, and it's for you know, more advanced developers or those looking for more flexibility to interact with IPFS live peer to peer and filecoin. It's a Docker container wrapped around filecoin and IPFS nodes. And it gives you a lot of options to c
onfigure it's a minor selections and extend functionality. It also offers some bridges to several layer ones which might be of interest to developers out there. Another one here and I'll preface this by saying you need an invite to this is ESRI tech. So it's for people looking to store really meaningful public data. It's currently in alpha mode and like I said, it requires an invite because it's been built as a public goods specifically to store important information. If you are I do have Use ca
se around this slide, please feel free to reach out to us on this project. Other final tool I'll mention is orbit dB. So many people coming to the web three space from web two are often looking for the same sort of relational databases that we're so used to in traditional computing except in a decentralized or distributed format. And this isn't an easy problem. So Oba to me is currently in active development. And because this isn't an easy problem to solve, this isn't an ideal solution for those
of you looking for an out of the box experience. But if you are looking for something like that, try out orbit dB. And there's also several other tools in the ecosystem leveraging IPFS and filecoin, including ceramic, which is similar to textil power gate, except it uses decentralized identities. Lighthouse is file drive, and there's even Morales has an IPFS API, so check those out as well. So storage is really a fundamental component on one technology system. So and there's so many use cases y
ou could dive into here. And so hopefully, I've provided you with some of the knowledge and tools you need to get started with IPFS and file Goyt. Coin and really make powerful distributed applications. And there's just one more tool that's also in active development now. So if you look closely at this diagram, you'll notice probably unfamiliar logo right at the end of the logic layer. And that's the logo for the filecoin virtual machine. So FBM will be launching at the end of this year. And we'
re super excited about it. And it's going to allow smart contracts, contract use combined with like colocation of storage data, loads, so computing capabilities with storage capabilities, and will also be EVM compatible. So as I said, we're super excited for the kinds of use cases that we're going to see come out of this project as well. And you can follow along here on the website here as well. So hopefully, I've given you all the tools you need to get started with IPFS. And file coin. If you d
o need more resources or want to get involved, we have proto School, which is interactive tutorials on decentralized web protocols. There's also NFT, school dot Dev, or join a hackathon, check out our hackathons.filecoin.io page for all the latest hackathons we're involved in. And if you do really want to dig deep and build tooling in IPFS, and file coin or build a cool project, check out our grants options as well for that, in the meantime, all please learn long build and prosper. So we've lear
ned a ton in this section. And that is it. So let's do a summary of all the amazing things that we've learned. And then we'll go into the TypeScript edition of this because the TypeScript edition is definitely a little bit different. So let's talk. Alright, so first, we learned more about next Jas. And we learned we can have an application using next Jas. And it's a framework that's gonna allow us to build really powerful front ends and full stack applications really easily. We learned about the
layout of our next JS project, we add components in a components folder, which are basically minimalistic blocks of JavaScript and HTML that we can use to modularize and create our website out of these components. Constants is a folder that we can put constant variables, Node modules is node modules. And out folders. What happens when we export all of our code to a static example, pages are going to be basically the routes or the different pages of our website, everything goes through app.js. P
ublic is just some public stuff styles is for any CSS or styling of our application. And then we have our basic files here. In our pages section, we have our app, which is surrounded by both this notification provider and our Morales provider, all of our components run through this app on all of our pages run through this app. So this is kind of considered the entry point for our entire application. Having this Morales provider wrapped around our notifications in component means that we don't ha
ve to pass parameters between our components. And our lottery will just know what chain ID that we're on, because our header is going to pass it up to Morales provider and the Morales provider is going to pass it back down to our lottery entrance. And we saw with our manual header, the way that that connect button works behind the scenes. So it's doing some local storage, where we're storing whether or not we're actually connected, we learned about use effect, and you state and these different h
ooks in our front ends were one of the main reasons we want hooks is we want we want our websites to rerender. When stuff changes, we want our components to be able to talk about the state of the blockchain with each other. And they're incredibly powerful for building our React applications. Use effect is one of the most popular ones where if we don't have a dependency array, our function inside of our use effect will run anytime something re renders a blank dependency array means it'll just run
once on load. And if there are dependencies in the array, it'll run any time any of the variables in those change. We also learned about the use state hook, which is really similar to saying like, let variable equals x. But it also comes with the RE rendering ability. And it comes with some other nice abilities that we didn't really discuss here, we learned how to call different contract functions with mirallas. Not only sending transactions, but also calling data. Morales is smart enough to kn
ow that when it sees get entrance fee that this is going to be a view function. And this is going to be a transaction, it can tell the difference between the two. So this one's going to populate Metamask to pop up. And this one just going to return kind of normally like a view function, what we can actually use the same syntax between sending transactions and then calling view functions on our contract, we added a button, calling one of these Morales pieces and then had an onsuccess section wher
e when our transaction completed, we update the UI and we add a little pop up for notifications, we learned how to deploy our code directly to IPFS. And use that IPFS hash to interact and see our code, we also learned about fleek and how fleek automatically deploys to IPFS. Whenever we do a git push to our GitHub repository, and it makes continuously updating our websites much easier. It also gives us a regular canonical URL as well. And then finally, we learned about IPFS and decentralized data
base storage. Now you might be asking, Okay, well, why don't we just store all the data for this website on Aetherium, or polygon or avalanche, etc? And the answer to that is that can get incredibly expensive storing data, storing a ton of data on the blockchain costs a ton of gas, whereas this is a much cheaper alternative. Aetherium avalanche and the smart contract platforms aren't really meant to be data storage layers, they're meant to be logic layers, right? Decentralized logic, decentraliz
ed smart contracts, oftentimes, yes, we're gonna have to store data in them. But when it's a ton of data, there are better solutions. And there are different solutions out there for storing our data, like IPFS and filecoin, you should be incredibly proud of yourself, if you've made it this far, because you've just made a really solid app, a really solid front end application. And you've learned how to really easily add functionality for interacting with your smart contracts. So give yourself a p
at on the back, maybe even tweet this out, share this really cool application with your friends and family. Take a break. And I'll see you in the next lesson. All right, welcome to one of the fastest lessons that we're going to have here. And in this lesson, we're going to talk about the hardhat starter kit. Really quickly, I'm going to walk you through it and show you how to use it. Now we've learned a lot about projects, we've learned a lot about different repos, learnt the basics of smart con
tracts. And we've learned a lot about front end as well and building front ends for applications. So this smart contract kit repo comes packed with a ton of starter kits that you can use to start deploying your projects right away. And as you can see, that hard hat starter kit is easily one of the most popular ones with the most stars the most forks out there. The smart contract kit repo actually comes with a ton of frameworks, like if you want to work with SWANA, if you want to work with Python
and Brownie, if you want to work with foundry, truffle, really any other framework out there, you can get started, clone one of these repos, work with one of these repos and build your project and get started right away, we're going to show you how to use the hard hat starter kit. So you can just grab the repo and go and already have some boilerplate code and a boilerplate really good looking repo to start your projects with, we come to the smart contract kit, hard hat starter kit repo here. An
d if you're working with GitHub, you can just go ahead and use this template and it will automatically generate you a new GitHub repo with the hardest starter kit. So let's go ahead, we'll click use this template, we come up with our own name here, we'll call it make it public create repository from Template. it'll generate our repository. And now we automatically have it in our own repo here. And we can get started working with it. And we can get started working with it. If you don't want to cl
ick the use that template button, we can also just copy the URL. And in our code editor, we can just do git clone and paste that in there. So for now, I am going to get clone, but I'm going to get clone with this repo that we just created. Come back in with the git clone, hard hat play FCC or hard hat starter kit. We're going to cd into our head play FCC, and then open that up in a new code editor. And awesome. Now you'll see in this repo, it comes packed with a ton of contracts, deployments, sc
ripts, tasks, test, everything, you name it to really get started in a professional environment. We look in the contract section, we can see we have a couple of sample contracts. We have a contract for making an API call to a chain link node, working with keepers working with price feeds, and then working with chain link Vir Fe two. We've got some test contracts and we additionally have this fuzzing folder, which we'll talk talk about in a much later section of this course, we have deployed scri
pts where we start with deploying mocks, then we deploy each one of those contracts, we have a sample script to read the price from one of these contracts. And we have a whole bunch of sample tasks. Now at the time of recording, instead of scripts, this repo uses tasks. But again, they're a little bit interchangeable. And of course, we have some unit tests and some staging tests as well, that you can go through and take a look at, once we're in this repo, we can run some familiar commands here,
we'll do yarn, of course, to install our all of our packages. And then everything that we're going to do, if you get lost, you can always come back to this repo. And you can follow along with getting started and the Quickstart. So we just did the git clone. Now we're doing the yarn, and then we're gonna go ahead and run yarn hard hat test. This hard hat starter kit repo is very consistently up to date, we did the last push being just a few days ago, and will constantly have some best practices f
or building our smart contracts and having a really professional coding environment. And it's got this really cute logo. Once we've installed all the dependencies, we can run yarn, art hath test, we can run all of the tests in the test folder, which also will show us how to interact and how to use all these different contracts in here. And they each have some console dot log, so you can see more about what's actually going on when these tests actually run. If we look in the Hardhead config.js, i
t's got some really familiar code in here, we have all our imports at the top, we grab a whole bunch of environment variables, we've got the ether scan plugin, we've got the gas reporter, the contract sizer, which is a plugin that tells you how big your contracts are. So named accounts, different solidity versions, and then mocha timeout as well. We can of course, do yarn hard hat node, which will run through our deploy scripts, and then spin up a new note for us, which has mock chainlink tokens
, mock Oracle's mock aggregators, and mock up VRF for us to go ahead and interact with once that's up, we can then of course, to hard hat, console, dash dash network localhost, and begin interacting with contracts on localhost. So we can kind of follow along with price feed, for example, and do const price consumer B three equals await ethers dot get contract, price, consumer V three. And then we can do await price consumer B three dot get latest price. Let's wrap that in a to string. And we can
see a mock latest price from a contract that uses channeling price feeds. And we can interact with any of our contracts and work with any of the mocks as well in here. If we want to deploy this to an actual test net like Rinckey, or main net will just pop in our dot env file, we'll close our node terminal, and we can run yarn hardhat or just hh deploy. And then we'll add whatever tags we want to do here. So let's just deploy our price feed contract. If we go to the price feed deploy, we scroll
down, we'll get the tags. Okay, great, we'll use the feed tag, dash tags feeds dash to or feed dash dash network brings beam. And while we're waiting for this to deploy, we can go back to the actual repo. And just make sure to follow along with the documentation here and the Quickstart in all the usage and everything so that you make sure that you're working with the most up to date version. There's even documentation on running a local network using a test net or live network working with Aethe
rium. Rigby adding your private keys and dotting envies all this stuff that you already know, forking, which we'll learn a little bit later, auto funding your contracts for working with chain link API running tests, you can additionally run your tests in parallel by adding the dash dash parallel flag to our tests. We can interact with our deployed contracts with those different tasks that we've created linting code formatting, estimated gas code coverage fuzzing, we'll talk about later. And then
contributions. PRs issues are always welcome here. And once it's outputted, and even verified, if you have verification turned on, you'll get a little task that we can run to just go ahead and read the price feed or interact with the contract. So we can copy that task out. Yarn hardhat. Read price feed since it's a task here, contract the contract data which we just deployed network Rigby. And we'll get reading data price feed from consumer contract on network, Rigby price is here, which of cou
rse, we're saying the price of Aetherium is $3,033, because it has eight decimal places. So if you're ever looking to start a new project, and you want some boilerplate code, this hard hat Starter Kit is a great place to get started. And of course, you can open it and get pod if you want to just test it out and try it and get pot in a Cloud Shell. So that's it for this lesson. Wasn't that fast. This was the fastest lesson ever. So if you want to do a little extra learnings here, I would fork thi
s I would clone this I would use this template, try to play around with the repo a little bit yourself and see what you recognize, see what you don't recognize and keep that prepped in your mind for later so Questions in the course. And then for everyone here who is TypeScript, there is, of course, a TypeScript version of this as well that you can get cloned. And it has a nice blue logo here to show that it's a little bit different. So, that being said, use the repo, have fun. Let's get to lesso
n 12. Alright, now we're moving on to the hard hat ERC. 20s are the section where we're going to learn how to create our own ERC 20 or EIP 20 Or B E P 20 or AEP 20 any of these tokens on the blockchain before we can understand what an ERC 20 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 Aetherium, and avalanche and finance and polygon. All these blockchains have what's called improvement proposals. And for Aetherium, they're
called Aetherium improvement proposals, or E IPs. And what people would do is they come up with these ideas to improve Aetherium or improve these layer ones like polygon, Matic avalanche, etc. And on some GitHub or some open source repository, they'll add these new EIP is they'll add these new improvement ideas to make 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 f
or the entire community to adopt. Once an EIP gets enough insight, they also create an E RC, which stands for Aetherium request for comments. So EIP a theory and improvement proposals ERC a theory and request for comments. And again, these can be like BP, Pep, you know, etc. For all these different blockchains. Both the improvement proposals and the Request 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 s
lash EIP, the ERC is and the EFPs share that same number. And there are websites like EIP is that aetherium.org That keep track of all of these new Aetherium improvement proposals, and you can actually see them real time go through the process of being adopted by the community. Now, one of these e IPs or ERC is, is going to be the ERC 20 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 sub 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 ERC 20s So ERC 20s are tokens that are deployed on a chain using what's called the ERC 20 token standard, you can read more about it in the year 20 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 or the smart contract. It's both it's really cool tether chainlink unique token and dye are all examples of ERC 20s Technically, chain link is in the ERC. 677 as there are upgrades to the ERC 20 that some tokens take that are still backwards compatible with ERC. 20s And so basically, you can think of them as ERC 20s with a little additional functionality. Now why would I even care to want to make an ERC 20 Well, you can do a lot of really cool stuff with it. Yo
u can make governance token, you can secure an underlying network, you can create some type of synthetic acid, or really anything else. In any case, how do we build one of these ERC? 20s 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 that has a name function, 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 ERC 20 compatible, like the ERC 677 or the ERC 777. Definitely go check those out and build one of those instead. All right, awesome. Now that we know what one of these ERC 20s is, we can go ahead and create our own per usual in the GitHub repo associated with this course. We have all the code available here. If you want to just get clone. This is going to be again another o
ne of our quicker lessons here. So we're in our terminal. We're in our VS code here. We're going to make a new directory. I'm going to call it hard hat ERC 20 FCC will cd into hard hat, your C 20 sec. And we're going to create a new hard hat project the exact same way we've been doing it yarn add dash dash dev or tab. Let's actually open it in its own VS code will do code.or file open this folder. And okay, we're in our project now. Let's create a new hard hat project. We'll do yarn, art hats. W
e'll do create an empty hard hat dot config dot j s here and great. We've now got an empty hard hat dot config dot j s. If you want to copy paste your hard hat dot config from a previous projects you want to copy paste your heart Have dot config or your dot EMV file, because you know we're going to need those feel free to do so now, I'm just going to update this to 8.7. I'll add the rest of my stuff later. So as we've heard this EIP 20, or this ERC 20. All it needs is to have these functions in
its token standard so that we can transfer tokens, we can do all the stuff in the ERC 20 contract itself, it really is just keeping track of how much of each token people have. So the smart contract, kind of in a weird way it keeps track of itself. To get started, we're going to do this kind of the manual way. First, we're going to create our own manual token here, or a really minimalistic one anyways, so let's create a new folder. contracts will create a new file called manual token dot soul. Y
es, I'm going to show you kind of the hard way to make it and then I'll show you a much easier way to make it. So to get started here are usual we can do pragma, solidity to carrot zero, point 8.7. And then we'll even do spdx, license identifier, MIT do contract, manual token, and boom, let's get started. The main reason this token smart contract works is that there's some balances mapping. So we have a mapping of addresses to you in 256. And it's usually public called balance of and all this do
es is this mapping is obviously the key is going to be every single address on the planet, and then how much they have. And basically, when we transfer tokens, transfer tokens, we're basically just subtract from address, amount, and add to to address. So a really minimalistic way to implement this would be to create this transfer function first. So we'll create this function, I'm going to call it underscore transfer, we can do an address from address to you into fifth sixth mount. And now we'd p
robably put some requirements, we probably omit some events, and let's make this public as well. And really, at the end of the day, is we're gonna say balance of from minus equals value, which is the same as saying bounce of from equals bounce from minus value, or excuse me, amount, and then we're gonna say balance of two, excuse me, plus equals, which is the same as saying, you know, balance of two plus. And technically, that's really all we need, right, we probably want to do some asserts ins
here, some requires to make sure all of our numbers make sense. But really, at the end of the day, this is all that this function is doing. Transfer works when the caller is sending money directly into another address. But what happens if we want to allow some smart contract to work with our token, or we want to allow somebody else to work with our token, you know, maybe to deposit it into a protocol, or do some more functionality with it, there will be some approved function that will approve t
hat contract to do that. And then we'll have a function transfer from and this function will, you know, it'll just implement taking funds from user and this will be public as well. And then at the top will be some type of allowances mapping that will tell who's allowed which address to take how much token, which sounds a little confusing, but let me just add the mapping. So it'll be a mapping of addresses to a mapping of addresses to an amount to a unit tivity sex and this will be public allowan
ce, we're gonna say address, Patrick is going to allow address of Patrick's brother to use 25 tokens. And that's how this allowance works. And in our transfer from transfer from will check this allowance mapping and save Hmm. Did Patrick give you authorization to borrow those tokens? Oh, yes, you did. Okay, we'll let you transfer from. And I'm just, I'm just going to copy paste an implementation of it, you can check out the GitHub repo as well. And it would look something like this is we check t
he allowed amounts, update the allowance, and then transfer the tokens. So those are some of the main functions. So we need an approved function, obviously, to update the allowances here. And usually, you'll have like a un 256 initial supply. And this will be like how many tokens there are starting with how many tokens there are total, sometimes you'll add a mint function to add more functions. But you can basically start to see this contract ramping up. One thing we could do is we could go ahea
d go through this spec and just line by line, you know, build our token ourself. And after we do that, it might look something like this. So I'm just copy pasted the code from the GitHub repo. If you go to contracts, manual token, I just copy paste this code in here. This is what a contract a token contract might look like. Okay. So we have all these functions, we have all these arrays. We have all this stuff. And you can see in the constructor, we're taking initial supply, and then a token name
and a token symbol. The name, you know, might be something like dy token. And then the symbol might be something like dy, just so that it's easily recognizable just by its name and its token. coding it all from scratch, like that is definitely something that we can do. But as engineers, we know that that's probably really annoying. And we don't actually want to do that. So what can we do instead? Well, we can use an open source library, like open Zeppelin, to actually get some boilerplate code
work with open Zeppelin is almost considered kind of the standard library of solidity. They have a list of open source contracts that anybody can use and import into their contracts that have a ton of boilerplate, so that you don't have to manually write everything out, we can see all their code in their GitHub repository, open Zeppelin slash open Zeppelin contracts, and we're going to be using them a lot moving forward. So for example, you can see kind of on the left side of their documentation
, they have this tokens section, and they have an ERC 20, which is one of those tokens standards. If you scroll on here, they even have some minimalistic examples of how to create your own ERC 20 token. And that's what we're going to be using to build our token. Because you see how much smaller this is how much less code this is to maintain. Let's go ahead and let's use open Zeppelin for us to create our token. So let's create a new file. We'll call our token dot soul. I'm going to create our ow
n token here. So let's do spdx. License identifier, MIT, we'll do pragma, solidity carrot zero, point 8.7, we'll do contract our token. Now, what we're going to do, we're going to import openzeppelin contracts into our hard hat project. And we're going to do it the same way we did with chain link and any other packages in the future. So we'll do yarn, add dash dash Dev, at open Zeppelin slash contracts. And this is going to add the open Zeppelin slash contracts NPM package to our project. And on
e of the code pieces that they have is this ERC 20 contract that we can use and we can have our token inherit all the functions. So we'll go ahead and import it with import at openzeppelin. Slash contracts slash tokens slash ERC 20 slash ERC 20 ditzel. And just by importing it like this, all we have to do is have our token inherited now. So we'll say contract. Our token is ERC 20. Boom. And just like that our token is almost done. Now you might get this little wiggle this little red line here sa
ying our token should be marked abstract. And that's because if we look into the ERC 20 dot soul of openzeppelin We'll see that it has a constructor. So in order for us to inherit your C 20 token, we have to use the ERC 20 constructor and we just need to give our token a name and a symbol. But we can say in our constructor, we can leave it blank. And then right next to our constructor, we'll add the ERC 20 constructor and our name will be our token. And then our symbol will just be OT and then t
his ERC. 20 token also comes with something called a mint functionality, which is essentially a function that allows us to create tokens, right because right now we actually get initialized with zero tokens, right. So nobody's actually allowed to have any tokens. So we want to mint the initial amount of tokens and then who owns all those tokens to start with. So usually what you'll see is you'll see a mint function like this, it'll be passed in message that sender, so whoever deploys this contra
ct will own all the tokens to start. And then we'll give it like an in their soul supply. And then we could do like, you went to 56 initial supply equals like seven, or whatever. But instead, a common practice is just to add it to the constructor. So you and 256 initial supply like that, as we know about solidity decimals don't work so great. So if I say my initial supply is 50, that 50 is going to be like 50 way, and there's all these ERC 20s come with a decimals and decimals function, which te
lls us how many decimals we should expect with our ERC 20. The default is 18. And we can override this function if we want a different amount of decimals. And if we know the default is 18. And we want to deploy 50, we might want to do our initial supply of 50 e 18. Or you can also say like 50 times 10, raise the 18th or whatever you want there. And in our code when we deploy this now, this is actually where we're going to finish the project. Because everything else that we would do here, we've a
lready done, all we need to do is make a deploy script and write some tests. That's really it. Because right now you have all the skills that you need to write a deploy script and then optionally write some tests for this project. So I highly encourage you to pause the video here and try to write your own deploy script. And even if you want to write your own tests, you can always refer back To the GitHub repo associated with this lesson, as we do have a deploy script in here, we also have a Type
Script edition in here as well that we're additionally not going to go over. And of course, if you get totally lost, there's a ton of instructions in here to help you learn more and help you work with this specific repository. So let's do a quick review of what we just learned. So ERC 20 tokens, or EIP 20 tokens or or b p or p p, or any of these dash 20. Improvement proposals are what's known as the token standard. And the token standard, these tokens on chain actually just tokens that are smart
contracts. Now, these tokens are obviously different than the layer one tokens like Aetherium, or polygon or Avalanche or arbitration, those are not going to be smart contracts, those are going to be blockchain native tokens, and you'll hear me refer to it as blockchain native tokens a lot. versus these tokens, these ERC 20, these smart contract tokens, which are just smart contracts. And they're just kind of a combination of these functions that represent how many tokens each address has, we c
an create our own token with all the specifications added. Or we can just use openzeppelin to import a token in now another popular repo like open Zeppelin is going to be this one from Rory capital called soulmate. And they're both aimed to be standard libraries for solidity. And one of the important things to keep in mind is that these tokens have this allowance mapping. And you can allow other addresses to have access to your tokens and move your tokens around. This is important, especially wh
en we get to later on when working with defy when we want to give some smart contract access to our tokens so that they can input it into their defy protocol. It's also a little bit tricky. And you want to make sure you're not allowing malicious contracts to interact with your tokens. And we'll also see that when we start to interact with these tokens more before any contract can interact with our tokens, we need to approve them to interact with our tokens. And that's it. Now you're a token wiza
rd, and you can deploy your own tokens. Take a break, get that coffee, and I'll see you in the next one. All right, welcome to the next session, we are going to be learning about defy in this session and going to be programmatic, and going to be programmatically interacting with the defy protocol. I am incredibly excited for you for this session, because defi is one of the best use cases for smart contracts. And one of the use cases that I am specifically most excited for now, as I've mentioned,
the past defy stands for decentralized finance, we've left some links in the GitHub repository for you to learn more about Defy. One of the main reasons we're so excited about defy is because we move away from this area of traditional agreement. And that's what smart contracts are all about. They're about removing this centralized entity, from our financial world, and especially from these financial institutions that have a conflict of interest. They're in business to make money not to keep our
money safe not to make us money. And we want to work with a system where everything is transparent, especially when it comes to our financial services. So we want to move to this world of smart contracts, especially when it comes to our money. And in my mind, defi is going to be the industry that affects the masses, the quickest because of how much fair how much better decentralized finance is than centralized finance. And at the moment, the rates and the yields and the interest that you gain i
n defy is much better than centralized finance, because remember, will go away from these centralized protocols, saying, hey, trust us, we'll give you access to the markets or hate trust us put your money in us will keep your money safe to this cryptographic math base guarantees instead of having to trust these companies and these entities, which is what we want. And additionally, the more our Oracle networks get better, and the more Oracle's networks work with these smart contract platforms lik
e Aetherium, like polygon, like arbitrage them, the more data and the more complex financial products that we can do. Now, one of the other reasons I'm so crazy excited about defy is if you look at this little chart right here, it shows the different markets by size. Now this this image is a little bit outdated, but it still shows you the relative sizes of all these different industries defy right now is a $200 billion market, there's about $200 billion locked in the defy industry. And I'll show
you that in a minute. Cryptocurrency actually, at the time of recording isn't 360 billion. It's actually like 1.8 trillion. So it's a lot more than this. But still, it's a massive subset of all these other areas like gold is a $10 trillion market. The stock market is almost $100 trillion global real estate, almost $300 trillion derivatives as quadrillion dollars. So the FBI is a super tiny, tiny, tiny, tiny subset right now and in my mind, all of these areas can be re landscaped with Defy. So w
e're ramping up, we're getting there. So it's gonna be up to us to make some of these protocols and make it Much easier for people to get into the space where their finances are going to be more fair, more accountable and more transparent. And with better yield rates, we can actually see a pretty good summary of what's going on in defy this site called defy llama. It shows total value locked in all these different decentralized protocols. And we can see a lot of these are across multiple chains,
right. And a lot of these are EVM compatible chains, Aetherium, Biden, smart chain, avalanche, Fanta, drawn polygon, all these are EVM, compatible blockchains, where we can see exactly how much money independent users have put into these protocols. The time of recording Ave is the number one protocol for total value locked. So there's $22 billion locked in Ave, which is the protocol that we're going to be going over today. So what is Ave So are they is a borrowing and lending protocol, it allow
s us to borrow and lend cryptocurrencies. So we can actually put down a token as collateral, it's kind of similar to like putting money in a bank, and earn yields on other people borrowing that collateral from us almost exactly what a bank does, except for the fact it's what's called noncustodial. To the Ave team never touches our money. Nobody ever touches the money. It's all just a smart contract. It's all just this programmatic code. So we can be rest assured, no one's going to run off with o
ur money, no one's going to do anything bad. And we also gain these higher yields. borrowing and lending is a critical piece for creating really any interesting financial applications. If you want to short sell something, if you want to leverage up on some asset if you want to. If you want to do more complex financial products, you need borrowing and lending. Now a lot of the typical FinTech or financial technology or finance terms do apply here. And this course isn't going to be a deep dive int
o exactly how these financial products work. And it's also not going to be a course on finance. If you want to learn more about finance, we'll leave a number of links in our GitHub repo associated with this course. So you can learn more about finance and become what I like to call a defy quant, quantitative defy engineer. And I am so excited for more defi quants to get into this space. Alright, so here we are in the Ave application. It's at testament dot Ave dot markets, we are in the testament
of Avi now, everything that we're going to do here is going to work on Main net as well, but we're going to use it on their test net. Now this is actually obvious older UI, and they have a new website that looks even better than this. But we're going to be going through a lot of the basic functionality depositing taking out a loan, potentially even shorting an asset, if we want, I don't recommend going to the site because it might not work and COVID the way you'd expect it to. So for this, just
sit back, relax and watch. In order for us to actually short sell or margin trade. The first thing that we're going to need to do is actually deposit some collateral, we need to deposit some collateral in order to borrow this way. If we never repay back the loan that we took out or the the amount that we borrowed, Ave, we'll just go ahead and take the collateral that we put in here, we'll do what's called a liquidation call. And that's why this is actually a little bit safer than short selling i
n traditional markets. Because if your collateral is less than how much you have borrowed, you'll just immediately get liquidated, but you still lose a bunch of money so like don't get liquidated. So what we want to do now is we're gonna scroll to Aetherium, we're going to connect our wallet here, we're going to move to COVID test network browser here. And we're gonna go to this deposit piece. So it already shows our balance here we have point two COVID eath. Let's deposit 0.1. We're gonna hit d
eposit Metamask can pop up, confirm. But once this goes through, this means that we've have it deposited and we go to our dashboard, we can see we have some eath here, point one eath got some API, this is kind of like that percentage return that we're gonna get back for, for depositing into Ave. And yes, we can use it as collateral here, we have this, this marked as yes here. So that's exactly what we're going to do. And it says nothing borrowed. Yep, we can go ahead and hit this borrow now butt
on. And we're gonna get brought to the borrower screen, and we're going to choose which asset we want to borrow. Now, whenever we borrow one of these, there are these API's, right? This is the percentage that over the course of a year that we're gonna have to pay, in order to actually borrow this asset. The stable one means it'll always be for or variable means it actually changes depending on kind of how much liquidity the protocol has, you can kind of pick which one you want to do stable is yo
u're always gonna be a 4% variable is going to be a little bit riskier, but you might get a lower fee. So we're actually going to borrow some dye right, because dye is a stable coin. It's worth $1. In a way, you could call this taking out on margin because we're taking out dye to borrow and another way we could say we're shorting dye which is kind of funny to think about, but you get to choose how much you want to borrow here and you'll see this this thing called Health factor I'm going to zoom
in a little bit this thing called Health factor here as we as we scroll this thing. So this health factor is how close to being liquidated you are remember how I said you can get liquidated this health factor represents how close we are to getting liquidated. This means means how close we are to always saying, You know what fu we're taking your funds. If it goes below one at any time, somebody can liquidate you and take a lot of that deposit that we put in, there's some math behind actually what
the health factor actually is, you can head over to the Ave documentation, which I will leave a link in the description to kind of read more about the health factor. So we're going to borrow 29 die we're buying, we're borrowing basically 30 bucks. Gonna hit continue, I'm gonna do a variable, zoom back out, continue, we're gonna borrow metamath pops up, confirm transaction that's pending. And we're gonna go to the dashboard. And now we can see kind of our new balance here, right, we can see the
point one eath, deposited and 29 die. And we can see our health factor up here, you can even click this little button, saying, hey, it represents how close you are to being liquidated, we can see the value here, our eath is worth like $200, or die is worth 30 bucks. So we're good. We're pretty healthy here. In order for Avi to understand and under to price the underlying collateral, so it knows how much it can lend out. Obviously another one of these protocols that uses changing price feeds to p
rice, the underlying collateral, many of these billion dollar defy protocols use chain link on the back end to do all their pricing mechanisms. And that's essentially it, we could then repay our debts, we could borrow more assets, we could swap assets around. And the interest return, we get onto pausing our assets is amazing. So now that we learned a little bit about how to use their UI, which is hosted on IPFS, by the way, let's go ahead and let's learn how to do all this and do even more progr
ammatically so we can become defy quanta engineers. Now, like I said, we're going to be working with the Ave v two protocol, if you want to try out the v3, you absolutely can, if you can go there and play with it right now, it still has more money locked in it, which is great. But the v3 protocol is obviously the latest addition. So we're gonna be flipping back and forth between the documentation and our code base. So I recommend that you have the documentation up as well. And per usual, all of
the code that we're going to be working with is in this hard hat defi Free Code Camp repository. So let's jump in. I'm in by VS code, I'm in my folder with this course, we're going to make a new folder, we're going to call it hard hat, defy FCC, we're going to cd into it. And then we're going to open it up with code period. Or you can also do per usual, File Open and then open that folder. Now we're in a new project, we're going to do yarn, add dash dash Dev, aren't hat. And we're going to add h
ard hat and start up our minimalistic hard hat project. Once again, for starting up your minimalistic hard hat projects, I usually just copy paste from another folder, or I just used that hard hat starter kit that we saw in the smart contract code repo. But whatever works best for you to get your project started, you can use now that we've got this, we can run yarn hardhat. And we'll just create an empty hardhat.config.js. Now to save us some boilerplate time, I am going to copy paste my hard ha
t.config.js from a past project into this one, just to make it so we don't have to go through that boilerplate setup again. And I'm also going to copy paste this line from our heart at smart contract lottery. Again, if you want to use your package JSON or your yarn dot lock to install dependencies, you absolutely can. But I'm just going to paste that in here and run it. And then I'm going to copy paste over my prettier files, so that all my JavaScript can be formatted the way I want it to be. Ok
ay, great. Now we have a minimalistic project spun up, let's go ahead and get started learning how to interact with the AVI protocol here. So let's make a quick readme and talk about what we want to be able to do. So first, we're going to want to be able to learn how to programmatically deposit collateral. And if we stopped right there, that might be enough, we'd be able to programmatically deposit collateral, and in doing so we earn yield, we'd earn that percentage return just on our deposited
collateral. So accomplishing this by itself is already a feat. But let's say we want to go one step further, we want to get into these more interesting financial products. So after we deposit some collateral, we're going to learn how to programmatically borrow and other asset, the deposited collateral is going to be eath, slash wrapped eath, which we'll talk about in a little bit, we're going to borrow another asset, which for this demo is going to be dye. And the reason that we're using dye is
because dye is what's known as a stable coin. So dye is actually a token on the blockchain created by this maker Dow where the price of the dye token is always pegged to $1. So we're putting down eath as collateral and we're borrowing cryptocurrency, US dollars, sort of, we're borrowing this token, which represents a US dollar and then we'll just repay that I will repay almost everything back and you'll see why we don't repay everything back in a minute. One other protocol that I want to talk ab
out quickly is the uniswap protocol. And the uniswap protocol has become this haven for trading. It's a decentralized application that allows us to trade assets and tokens with each other on something called an automated market maker. It ends basically a decentralized Stock Exchange, but with tokens and again, tokens aren't exactly stocks, they're very different. So when looking to get some of these assets It's like wrapped Aetherium or dye or link token. On a main net, oftentimes, you're going
to use one of these decentralized exchanges. And obviously, these decentralized exchanges are much fairer, because everything that happens on them is transparent, much fairer than centralized finance, everything that happens on them is transparent. You can see everything that's going on on chain, which is absolutely phenomenal. So let's go ahead and get started here. And let's just create our scripts folder. Because in this project, we're actually not going to create any contracts ourselves, we'
re just going to learn how to interact with these protocols. If you do want to learn how to build some of these protocols, at the end of this session, we will give you a ton of links. And we'll have a special guest explain a few different ways to learn how to build more of these decentralized protocols. Although we've already built one with our decentralized lottery, which is fantastic. Let's create some scripts here. And for all of these things, deposit collateral, borrow and repay. We'll just
put this all in a new script called Ave borrow dot Jas. So we're gonna do everything in here. And since this is a script, it's going to have the same setup, as we've seen before, right, so we're gonna have this main thing around an async function. Main, and then we'll have our imports, of course at the top. Now something that's important to note, go to avi, we go to the protocol, we kind of read through the docs, and eventually we would find out the protocol treats everything as an ERC 20 token.
And but we know that Aetherium or the native blockchain token that you're using, isn't an ERC 20 token. And the reason that treats everything like an ERC 20 token is that it's just much easier, right? If everything's using this ERC 20 token standard, it's much easier to send in and interact with stuff. On a lot of these protocols, when we go to deposit Aetherium, or polygon, or arbitrary marks cetera, what actually happens is they send your Aetherium through like what's called a web gateway, an
d swaps it for weath, which stands for rapt ether. And it's basically Aetherium. But in an ERC 20 token contract, so what we want to do is going to do that same thing, we're gonna skip kind of using this web gateway. And we'll just get the Web Token ourselves, and we'll use that as collateral. So in our script tag, I'm going to make another file called Get weath.js. And in here, we're actually going to go ahead, and we're going to build a script that will deposit our token for web token. Okay, s
o let's create the script. And there's a link to the web token on ether scan, and on Main net in the GitHub repo. And the way it works, is you actually deposit Aetherium. And in return, it'll give you the web token on Rigby right now, by deposit 0.05. Go ahead and write I'm connected to ether scan, I'll go ahead and write this transaction, I'm gonna drink pee. So I don't really care if it's if it's the actual contract or not, because it's not real money. But I'm going to deposit 0.05 eath. And a
fter our transaction goes through, we copy the contract address, we add this token to our Metamask the same way we added link will import tokens, paste the address in here, add custom token, import tokens will now see we have some wet token in here, I deposited 0.1 before so 0.1 plus 0.05, which is why it shows 0.15 Because I did it twice, well, while I wasn't recording. So um, but this is how you can get this wet token into your contract. And then anytime you want, you can call this withdrawal
function. And you can withdraw your Aetherium out of this and do what's called Burn your wet token. So when you swap back from weath to Aetherium, you hit this withdraw and boom, you basically swap them back because this contract itself right now is holding your Aetherium token. Pretty cool, right? So in our get wet function, we're not going to add this main thing here, we're going to create get West here just as kind of a module and we're going to import it into our Ave borrow. So we're not goi
ng to do this this main thing that you see here. Instead, we're going to create an async function called Get Wes. And then below, we're going to export it. So we'll do module dot exports equals get weath. And we're going to export it so our Avi borrow can use this get West script that we're creating right now, let's add let's go ahead and do this. Well, in order to interact with a contract, we're going to need an account. So we can do const deployer equals await get named accounts, per usual. We
'll do const get name accounts equals require hardhat. My VS code automatically imported that thank you VS code now. And now we want to call the deposit function on the west contract. How do we call this deposit function on the west contract? Well, how do you call any contract? Well, what do you need? You need the ABI and then you need the contract address. Drill this in. You're always going to be the API and the contract address to interact with the contract. We know that if we give we know tha
t if we give our project the whole contract, it'll get the API but we also know If we just do the interface, that's just as good, it won't give us all the functionality, but it will tell it will give us the API, it will tell our ethers, what functions it can use. So we're going to create a new folder, create our contracts folder. And in here, we're going to create a new folder inside of that called interfaces. And this is where we're going to create our web interface. Now a web interface is goin
g to be really similar to an ERC 20 interface. So if you want to go ahead and try to add it yourself, feel free to do so. Or what you can just do is you can come to the GitHub repo associated with this lesson, come to iOS and just copy paste, right, you'll see the functions in here are exactly the same as an ERC 20, allowance approved balance of decimals named blah, blah, with these additional deposit and withdrawal functions. So I'm going to copy all this, move back over to my hard hat project,
we'll create a new file, we'll call I left dot soul. And just to note, oftentimes, a good best practice is to have interfaces, start with eyes so that you know what to interface and then we'll paste it in here. Now in order for this to compile, we'll need to use 0.4 point 19 version of solidity. So what we can do is we can come over to our, our head.config.js. We have solidity compilers, version 0.07, or whatever versions that you have in here, we can add or just replace. So I'm going to put a
comma here, version 0.4 point 19. Save. And now in order to make sure we can get that API, do yarn, hardhats compile, or hh compiled, and great, we compile this interface. So now we have the ABI to interact with. Now that we have the ABI, a little check mark here, let's go ahead and get the contract address. But for reasons that we're going to learn about very soon, we're actually going to work just with main net set of getting the Rinkeby test and address, I'm going to look up with main net, we
're going to find the web token on Main net. So I'm going to copy the address of main net. And again, you can just grab this address from the GitHub repo associated with this lesson as well. And for now, we're gonna say check a little check mark here, and paste the address there. So now we're have the ABI compiled from an interface, and we have the contract address for main net. But let's go ahead and create this contract now. So we can say const, iOS equals await ethers dot and then we'll need
to import ethers from Hardhead as well. Ethers dot get contract at this is another one of these functions on ethers, it allows us to get a contract at a specific address, we'll say get contract app, we use the iOS ABI for now, we'll just hard code this address in here. And then we'll connect it to the Deployer. So we're saying let's get this web contract with the ABI of iOS at this address connected to Deployer. So we could go ahead and run await AI with dot deposit. And we'll set value which wi
ll be some amounts. Let's go ahead and at the top, we'll say const amount equals let's do ethers dot utils dot parse, ether, and then we'll do 0.0 0.02. So we'll deposit 0.02 will say const TX equals that will do await TX dot wait one wait for one block to go through. And then we'll just get the balance will say const. With balance equals await I with that balance of employer. So we're going to call the balance of function on our iWeb ERC 20 token. And then we'll just do console dot log got West
balance.to string. So we're using the main net address in here. And we're gonna say okay, we're going to deposit some amount, we're going to wait. And then we're gonna go ahead and get the balance right, so we're just depositing our Aetherium so that we can get that ERC 20 version of Aetherium, that West token here. Now, you might be thinking, Okay, why are you putting the main address in here? Let's Patrick, slow down. Let's go ahead and let's create a mock Web Token contract address. Let's de
ploy the mocks first, and then we'll go ahead and use that same setup that we've been doing this whole time, why you why you directly hard coding this in here. Well, I've been alluding to this for some time. But there's another way that we can run tests in our smart contracts. And this is with something called main net forking, we can actually do something where we fork the main net, and run a local hard hat node. That's pretending to be a main net node. And all we have to do is update our hard
head config to do so. So let's talk about forking for a minute. So on the left here, we have a blockchain an example of blockchain it's going to be something similar to a test net or main net like Rinkeby, eath, main net polygon etc. This is going to be a blockchain that we deploy to. Now there are a whole bunch of blocks in here, right? We have this huge chain that we can work with. And all this information on the blockchain is public information, like this block is going to have transaction tr
ansaction transaction, each one of these blocks is going to have a whole bunch of transactions. And all this information is on this public blockchain. In addition to all these transactions, it's going to have things like price feed contracts, it's going to have things like Ave contract, the Web token, contract, etc. All this contract information is public. So hypothetically, if it's already there, we should be basically able to copy this to our local environment and do some simulations ourselves
. And that's exactly what forking does. A fork blockchain literally takes a copy of an existing blockchain like on the left here and brings it on our local computer. We actually have control over our blockchain that's running locally, because it's gonna run on a local computer, similar to hard hat. Now, everything we do on this local forked blockchain is not going to affect main them, because it's a simulated blockchain. It's just running in our local environment. So we can actually interact wit
h this forking this kind of local blockchain that resembles that mimics the actual blockchain. And here's what forking doesn't do, it doesn't download the entire blockchain into our local setup. Anytime we reference an address. Anytime we reference, hey, there's something at a specific address, we make an API call to our Aetherium node, which again, we're using alchemy and say, hey, oh, what's at this address, and it'll return just that specific contract for us. This way, we don't have to downlo
ad the whole blockchain. And it's a lot quicker. And we can also do this forking to run our tests to run our scripts to do everything. And now you might be thinking, wow, Patrick, this sounds awesome. Well, why don't we just do this for everything? Well, there's some trade offs. The pros are that it's quick, it's easy, and a test will resemble what's on Main net. Now the cons are that we need an API, and we can't do everything locally. Some contracts, some contracts are complex to work with, and
mocks might just be better. But using a forked network might be a good way to run your tests, it might be a good alternate to just using mocks. So it really depends on what's right for you and right for your project. But it is a fantastic tool, especially for something like Avi, where we want to quickly test some things. Now the hard forking also will give us a bunch of fake accounts. So we'll still get a bunch of fake accounts on Main net that will be given a theorem. So we'll get fake main ne
t accounts for this forking. So for the rest of this, we're going to be using this forking to run our scripts and run our tests. If you want to go back after this and try this all out on COVID. We've got a whole bunch of different addresses for the COVID network so that you can run these scripts directly on COVID. And you can see the transactions yourself. Just note that when using COVID, you'll want to make sure that you're using the same addresses, as are in the AVI docs for the COVID network,
because they do change sometimes. Great, let's go ahead, we'll go to our RT head dot config dot j s. And now we'll go to our networks, which right now, I don't have anything, I only have ranking. And we'll add hard hat in here, we'll add a little comma down here. And we'll say, you know, the chain ID of course is going to be 31337. We'll add this forking keyword. And in here, we'll say the URL for a Forking is going to be our main net RPC URL. And this is another reason why we're using alchemy.
Alchemy is fantastic at these forked blockchains, and has really good pieces here. So what we can do is we can come back to our alchemy dashboard, we'll create a new app. This one will be for Aetherium main net, and we'll say forking chain. We'll say for forking, we'll go ahead and create this on a theory and main net. Now that we have this forking chain, we can do the same thing. We'll grab our API key, we'll come back to our project, create this new file, we'll create our dot env. And we'll d
o main net RPC URL equals and paste that in there. In our Hardhead config, we are now going to be forking from mainnet RPC URL whenever we work with the heart at blockchain. So now that we have this in here, let's go ahead and try to run this get wet function. Because since we're forking the blockchain, we should be able to go ahead and simulate this. So backing off a borrow, we'll go ahead we'll do const, get weath equals require and then we'll pull this script that dot dot scripts slash get we
ath. And then, in our main function, we'll just run await yet. So to run our script here, we'll do yarn hard hat, run scripts avevamo.js. And our default network is hard hat. So we could either do dash dash network hard hat or just run it. And remember, since in our config, we're saying, hey, when we run the hard hat chain, use this forking, we're going to be forking, so let's go ahead Run this ran to air main. Net RPC URL is undefined. Well, that makes sense. Let's go ahead and add this consumm
ated RPC rel equals process study and v dot made it RPC URL. Let's try this again. And we now see we got, you know, this much weath, which, again, that much wealth is gonna be 1-234-567-8910 1234567 0.02 wealth, which is exactly what we want. So now we have a way to interact with main net locally, which sounds kind of crazy. But he's incredibly powerful for exactly what we're doing right here. So we have a way to fork main that eath and run our scripts and kind of test to see and simulate what i
t would be like to actually run these transactions. So we're gonna do like that, our get with function looks good. And obviously, we would still modularize this, we put this in our helper Hardhead config, but we're going to skip doing that for now. So let's go head back to the AVI borrow. And let's go ahead and flesh the rest of this out. Now, let's go ahead and set up the rest of the boilerplate here. So we'll do const Deployer, because we need an account, obviously equals await, get named acco
unts. And then we'll do const get named accounts equals require. Now we want to start interacting with the ABI protocol, well, what do we need, we're gonna need the ABI and the address, nothing changes, we're gonna need these two. So what we can do is we can go to the Ave docs. And again, we're going to be on V two. And we can go ahead and find the contract address in here. Now the way it works is they actually have a contract, which will point us to the correct contract. The contract that we're
going to be doing all the lending with is this lending pool. And there's actually a contract to get that contract address. And to get the lending pool address, we have to go to the lending pool address provider. It's this contract that will tell us what the address of the lending pullets. And we can actually see the deployed contract section, we can see the address of this contract. And we can see the address of all the main ones and the COVID. Once again, if you want to play with this on COVID
. But we can see lending pool address provider is going to be located right here, we can copy this address. And we'll just take notes of this. And that lending pool, we're going to get from the lending pelagics provider. So let's actually create a function that will get us the lending pool address from the lending pool address provider. So down here, we'll create async function, get lending pool. Now in order to interact with this lending pool address provider. Same thing, we're going to need it
s address and its API, we have its address. So let's go ahead and get its API, you can go ahead to the GitHub repo associated with this lesson. And just copy paste it from the interfaces section. You could also look directly on the blockchain to see what this contract looks I can create your own interface. Or we can go ahead and use the interface right in the documentation. So we have islanding Palach. Provider, I'm just going to copy this from the ABI docs. But again, you've got a number of opt
ions. And so in our contracts in our interfaces, let's let's stick iwth in interfaces here. Let's create a new file. And we'll call it I lending pool address provider, dot soul. And we'll paste it in here, we just see we're using 0.6 point 12. So be sure to in our Hardhead config to make sure we have that we don't so we're just create a new one 0.6 point 12 And then we'll compile yarn Hardhead compile and compiles so awesome. We now have the ABI here, we'll get this contract by saying const lend
ing pool address provider equals await ethers dot get contract at will say I lending pool address oops address as I lending pool addresses excuse me, I'm going to update the name I Lenny pull addresses provider islanding pool addresses provider, we're going to pass in that contract address that we got from the Ovid docs here. Paste that in. And then we're going to connect it to our Deployer. So we're going to have our get lending pool, get past that account variable and then we'll just use the a
ccount here to connect it and the account that we're going to pass is of course going to be our Deployer. In our lending pool address provider. There's a function called Get lending pool which returns the address of the lining pool and this is going to be the function that we're going to call so we're gonna say const lending pool address equals a weight lending pool address says probes address any pool address says provider dot get lending pool and that's it we'll have the lending pool address a
nd then we'll have this contract give us the lending pool contract by doing const lending pool equals await ethers dot get contract Add. And we need to do the same thing, the interface, the interface, the address, and then the account. So back in the docs, we can grab the I lending pool by copying this like this. We'll go back to our contracts interfaces, new file, I lending pool, that's all. And we'll paste it in. Now with this one, if we scroll to the top, we noticed that we're importing from
some local places that we actually don't have in our contracts area, we can once again go ahead and add the AVI protocol v2 from NPM. And just use this as our imports. So we'll do yarn, add dash dash dev apt have a slash proto call hyphen V two. And now that we have the Add Ave protocol in our node modules, we can update these imports to point to our node modules instead of our local files. So I'm just gonna go ahead and tell you that the islanding pledge provider is that Ave slash protocol hyph
en V to slash contracts slash interfaces. And then data types dot soul is gonna be at of a protocol hyphen v2 slash contracts slash, proto call slash libraries, slash types, data types, that's all again to make sure this is right, yarn, Hardhead compile or hh, compile. And Cool. Looks like I did that right? Lending pool equals await ethers dot get contract at, we're going to be using lending pool, I lend the pool here, we're going to use this lending pool address got from the addresses provider.
And then the account, which is going to be our Deployer. And now we can do return lending pool. And if we want, and now that we have this function get lending pool backup in our main function, we can say const lending pool equals a weight, get lending pool and then pass the Deployer. And then we can even do a little console dot log, lending pool address and then do lending pool dot address. And since we're making it forking, we can kind of just keep running this right. So we'll do yarn hardhat
run scripts. Ave Baroda Jas, there are multiple artifacts for contract II lending pool addresses provider. And this is because in our node modules, import all this stuff from contracts and in here, and there's already in islanding, pool addresses provider in those add ons slash contracts. So actually, we don't even need this, I lending pool added service provider, we can go ahead and delete it. Our time right now is getting confused. It's saying Oh, are you referring to the one that you download
ed from NPM or the one that you made, which which one do you want to use. So we'll just make it easier for hardhat. And we'll say okay, well, we'll delete the one that we created, we'll use the one that we've downloaded here. And now we should be good to run this again. Because now there's only one for to pick from, which is the one we downloaded from NPM. And perfect, we get our get weath printout here, and then we get lending pool address is here. And this is going to be the actual lending poo
l address on ether Aetherium main net. So if we go back to ether scan, copy that address and paste it and ether scan, we can see it's even labeled Ave v two, and we can see a ton of transactions going through all the time. And ether scan is having a hard time keeping up with all the transactions. So we've got the lending pool address, we've got some web token, what do we need to do? Now we want a deposit of what do we need in order to deposit the token? Well, if we look at the deposit function i
n the avec GitHub, we can scroll in here and we see it eventually we'll call this safe transfer from which is basically going to be this transfer from function, since we're calling transfer from it's going to be this contract, that's actually going to pull the money out of our wallet. So in order to give the Ave contract, the ability to pull the money out of our wallet, we need to do what we're going to need to approve the contract. So first, before we can even deposit we're gonna need to approv
e it to get our web token, we're gonna have to get the Web Token first. So let's get the Web Token address we'll say const Web Token address, equals and this is where we marginalize it and get it from our hard head helper config. But for now, we can just hard code it, the Web Token contract address is going to be the exact same thing as what's in get web and then want to approve. So let's write an approved function because we're going to use this a couple times. So we'll make an async function a
nd approve ERC 20 And we'll take a contract address a spender address, which is going to be the contract that we're going to give the approval to to spend our token and amount to spend so exactly how much we want to prove it. And then an account to do all this on. So in here we'll say const ERC 20 token equals await ethers dot get contract at. And we could say I WEF but maybe we just want like a simple ERC 20 token interface. And we're going to grab that by cheating a little bit coin to our hard
head defy FCC. We're going to go to interfaces and grab this interface from here. So we're going to copy this, paste it in here New File IO ERC 20 dot som paste and now we have an ABI for ERC. 20s So we'll do get contract that ERC 20 Actually let's change this name to ERC. 20 address so we're going to get the contract with the ABI of IRC ERC 20 at contract address ERC 20 address and then we'll connect it to our account here. So and once we have the ERC 20 We can do const TX, we're going to do t
hat approve transaction we'll do a weight ERC 20 token dot approve spender address, and then amount amount to spend. We'll do we'll do a wait TX dot wait for one block. And we'll do a little console dot log saying approved. Now if you don't run this function before you try to deposit you'll just get an error saying hey, token is not approved, which is a pretty common error. So if you ever see that just know, I forgot to approve my token. So backup in our main script, we'll go ahead and run this
function. We'll say await approve ERC 20 with the Web Token address lending pool dot address because we want to give the len pool the approval to pull our web token from our account. And then we'll give it some amount to actually will import a mount from get weath as well. Mount we gotta go back to get with an export it so we can actually import it. So get with exporting that amount that 0.02. So we'll prove the amount and then we'll connect we'll have our Deployer do it obviously because we're
doing everything with the Deployer. So we'll approve the ERC 20. And then once we approve, we can go ahead and deposit it. So we'll say console dot log, depositing that. And then we'll run await lending pool dot deposit. If we look at the deposit function, we can see all the parameters that the deposit function takes. We can also see it in the Ave v2 documentation and we just look forward the posit. And we can see it takes the address of the asset that we're going to deposit how much of that ass
et we're going to deposit address on behalf of we're going to do it on behalf of ourself and then a referral code, which right now is just always going to be zero because the referral code has been discontinued. So we're going to deposit the wet token address, we're going to deposit our web token, we're going to posit 0.02 of that web token. And then we're going to use a deployer ash and then referral code is going to be zero. And then we'll do a little console dot log the positive. So let's try
this script. Let's see if it works. I'm just going to hit up to go ahead and rerun this script to rerun this command I just ran into doing a little compiling that ERC 20. That song was compiled one solidity file, got a bunch of wrapped Aetherium lending pool address. We approved it, we deposit we were depositing it and then we deposited it. So if we're looking at our little readme here, we get a little checkmark. We've done step one, we've deposited our collateral. Awesome. So now we have some
collateral to use to borrow other assets. Great. So now we've deposited let's go ahead and learn how to borrow now through a couple of new lines, and we'll say borrowed time. So in order for us to borrow, we probably want to know how much we can borrow. And we want to know more about our account, right? We want to know how much we have borrowed, how much we have in collateral and how much we can borrow. So there's a function that Avi comes with called Get User account data, which will return the
user's account data across all reserves, how much collateral we have down the total value it in its eath price, we have the available borrows and eath current liquidation threshold, loan to value etc. Now these are really important metrics. If we have one, eath and collateral that doesn't mean we can borrow one eath of assets. Each one of these tokens have some different values like loan to value. For example, if you have one eath you can only borrow zero point 75 for the dye token, this is to
reduce risk of the collateral and reduce risk of people not having enough collateral down as prices fluctuate. There's a liquidation threshold of 80% if you have one eath as collateral and point 81 eath borrowed, you'll get what's called liquidated. So what is liquidation? When you put down collateral and you borrow, if the amount that you have borrowed past this liquidation threshold is passed that 80% Or, or depending on different assets, it's different people can do what's called liquidate yo
u. This is when they pay back some of your loan that you took out. And they also get to buy some of your collateral at a cheaper price. This keeps the Ave platform solvent, and it makes it so that there's never more borrows than there are collateral in order to borrow assets, we still need that collateral down. So basically, if you borrowed more money than you've put up, other users can can take the money that you've put up in return for them paying for your loans. So we obviously don't want thi
s to happen. And the audit protocol programmatically doesn't want to have not enough money to do this. So they incentivize users to liquidate, in case of these failures is the protocols come with this thing called a health factor, which if this health factor is below one, you go ahead and you get liquidated, the actual function to liquidate somebody is called liquidation call. So you can actually build a bot and you can liquidate users who go insolvent and you can make a fee, you can make a rewa
rd for actually doing this. These protocols need to stay solvent, they need to have enough money to lend out. And they programmatically enforced this, which is why it's so great. You can learn more about liquidations in the liquidation documentation. So this get us account data will tell us how much we have collateral, how much we have in debt, and how much we have available to borrow based on how much collateral we have. We can see the current liquidation threshold we can see the loan to value
and then we can see our health factor, which is obviously really important. If our health factor ever falls below one, we get liquidated. So we never want this hell factor to fall below one when we're borrowing assets. So let's create a function that can grab that first. So let's create a new function called async. Function get it borrow user data, and we'll pass in the lending pool contract, we'll pass in the lending pool contract and the account that we want to get the data for. So we can say
const. And actually, we can pull out just the values that we want, we could pull out the total collateral eath total debt eath and the available to borrow. Let's just pull out the total collateral eath the total debt if and the available, borrows. So this equals await, lending pool dot get user account data of account. And now we'll even just kind of logged us out we'll say console dot log you have total collateral eath worth of eath the positive console. Log you have total debt eath worth of ea
th borrowed and then console dot log you can borrow available borrows eath worth of eath. And then we'll just return available to borrow will turn available borrows eath. And we'll return or total debt, we don't really need to return total collateral we could if we want we really just want to print it out here. So now back in our function, we can do in our main function, we can run let, I'm going to do that because we're going to be calling this a few times available borrows eath. And total debt
eath equals await, get borrow user data of lending pool and Deployer. And if we run this, we'll see how much we can actually borrow yarn hard hat or just h h run scripts on a borrowed.js and work on our forked blockchain here. And remember, it is going to be a little bit slower. And this is kind of one of the disadvantages too because it does have to make API calls whenever we want to interact with these chains. And then we got total collateral eath is not defined. And that's because I spelt to
tal wrong. So let's spell total correctly. And we'll run this again. But okay, great. So you have this month's worth of eath deposited, you have zero worth of eath borrowed because we haven't borrowed anything, and you can borrow this much worth of eath. Remember, the amount that we can borrow is always going to be less than the total amount that we have as deposited. That's why we see this lower number here. So cool. So that's how much we can borrow. Let's use that to go and borrow some time. S
o we have this total amount we can borrow an eighth and we're gonna get to borrow time. I promise we're gonna get to borrow time, but we need to figure out What's the conversion rate of diets? We're gonna get how much we can borrow in eath. But we want to borrow dye. So how much of dye can we borrow based off of the value of eath? And to do that, we're gonna have to get the dye price. And how are we going to do that? Well, you guessed it, we're going to use chain link price feeds. If you look in
the AVI documentation, you can find price Oracle, which is a contract that you could actually use right directly from Avi. But the first thing it does is check from a chain link aggregator, which we already know how to do. So we're gonna go ahead and just call directly from the chain link aggregator. So let's create a new function function, we'll call it get dye price is first we're going to need to get that interface, same thing. So you can either go right to Hardhead defy and just grab the in
terface right from here, we could swap this out with just an import from chainlink NPM, as well. But I'm just going to go ahead and copy paste a new file, this is going to be the Ag reg gate, Tor v3 interface. Dot saw that we've worked with so many times. Now that we have this interface, this will compile, we're obviously looking for latest round data, which will give us this answer here, which is going to be the price. So let's go ahead and grab that. So we'll say const di eath price feed equal
s await ethers dot get contract at and we'll use the air, Greg a Tor v3 interface will get the dye eath price feed right from the chain link Docs. So we go to docs dot chain dot link UVM chains will go to contract addresses on Aetherium. Or look for di eath on Main net. And we see di eath is right here. So we'll grab this and again, we're just hard coding it in the GitHub repo associated with it. With this, we put it in a little config file, but we can just go ahead and hard coded in. And for th
is one, we don't need to connect this to the deployer account. Since we're not going to be sending any transactions, we're just going to be reading from this contract, right. So reading don't need a signer sending me to signer. Now we can say const price equals a weight dye eath price feed dot latest round data. Now latest round data, as we know is going to return us this huge thing. And we only want the answer at the first index. So another way we could do this, we could just wrap this whole th
ing up. And then once this returns, we're gonna say okay, just grab that first index here, which will be that price. And then we could do a little console dot log, the dy eath. Price is in price dot two, like that, and then return price. So we can go ahead and run this as well test this out, just by hitting up and then enter. Depositing we deposited this is how much we can deposit. Nothing Oh, and I forgot to call it oh, excuse me, let's go up. This, let's say const dye price equals await get dy
e price. And tada. The dye youth price is this big number, which of course we know is going to be $3,289 which is which of course is gonna be 3289 di per eath. Now that we have the dye price, we can figure out how much dye we want to borrow. So great, we have the price. Now let's figure out the amount that we can borrow in dye, we have the amount we can borrow eath, we need to convert it to die. So we'll say const amount die to borrow equals available, be the available borrows in eath.to string.
And then in JavaScript, we can do this.to string but still do math. So times 0.95 times and then we'll do the reciprocal of that die. So one divided by die price.to number. So this will give us the amount of die that we can borrow. And then we'll want to get this in way. So if we print this out right now, console dot log, you can borrow. Run this now, you can borrow amount die to borrow. Not in way units, which we need in way units, but you can borrow 48 Die, which based off the price looks abo
ut right. So to get the correct units, we'll say const amount, di to borrow way. That's going to equal ethers dot utils dot parse ether, MT di to borrow.to string. This is just purely the amount of dye to borrow right so we get 48.79 die. But again, we want that in way the die token has 18 decimal places similar to Aetherium. So we need that amount in way and then we can go ahead and start actually borrowing now. So we'll create a new function called borrow die async function, borrow die will ta
ke the die address. Take the lending pool, take the amount die to borrow and weigh in Then of course, we'll take the account. And all we'll do is we'll do const. Borrow TX is going to be a weight, lending pool dot borrow, die address, amount die to borrow. And again, we can go right to the documentation, if we want, it takes the address of the asset, the amount, we want to borrow the interest rate mode, which is going to be variable or stable, the referral code and then address on behalf of, we'
re going to say one for the interest rate mode, where one is going to be stable. And then we're going to do zero or this referral code because that's debunked now, and then we'll do a count, then we'll do a wait, borrow TX dot Wait, wait one transaction, and then we'll do console dot log you've borrowed. Well, and that's it. So we now have this borrowed I function. So back up in our main function, right, now, we can finally do the borrow time. So we'll do a wait, borrow die. And we'll pass those
parameters in here. So we're going to do const, die token address, equals and we're just going to hard code this from main net. So we can look up die token address, main net, we'll grab this address here, this looks like this is indeed the DI token, we check right on the object get up, we could check right on the ABI of actual code, since we're just testing, we're just gonna go ahead and grab from ether scan here. So for borrow dye, we're gonna need the dye token address, we're gonna need the l
ending pool contract the amount of dye to borrow in way, and then our Deployer. And then we'll await borrow dye. And then we will run this get bar user data again, just print out the information about where we are after we do that. So when we can run this, again, we should see the amount that we have borrowed, updated, our first call to that function is gonna say, Hey, you have this much eat the positive Do you have nothing borrowed, you can borrow this much eath, we get the price, we get how mu
ch we borrowed, we borrow. And now it says you have this much where the eath deposited and you have this much worth of eath borrowed and you can borrow this much eat. So we actually now have bought a bunch of this dye actually borrowed. And the reason we're doing times zero point 95, we don't want to hit that cap of the maximum amount that we can borrow. So we're saying hey, let's get 95% of the amount that we actually can borrow. So we're not going to borrow everything, we're just gonna borrow
95%. And you can see that the amount of eath we have deposited is actually higher. This is because we're actually gaining interest just by having this eath deposited. And now that we have some dye borrowed, we borrowed 48 dye, which is equivalent to this much Aetherium. And then we still have a little bit more we can borrow because we only borrowed 95%, which is great. Awesome, we've taken out a borrow programmatically, let's repay at least some of it here. So we're gonna have to create a new fu
nction that's going to use the repay function in the contract. So we're gonna do async function repay, and this is going to take the amount that we want to repay the dye address that we're going to repay the lending pool and then the account now to repay once again, we're going to have to approve sending our dye back to Ave So in here, the first thing we need to do is we actually need to call wait prove ERC 20 with the dye address, lending pool dot address, mount and then accounts, right because
approve ERC 20. That's the input parameters it takes, and we need to approve sending the dye back to the contract. So we borrowed it, and we're gonna send it back. Now we're actually going to send it back. So let's say const, repay TX equals await, lending, cool that repay the address, amount, one account. And then we'll say await repay TX dot Wait, that will do console dot log repaid up in our main function, we're going to do a weight repay, and we're going to give it the amount dye to borrow
in way. We're gonna give it the dye token address, give it lending pool, and then we'll give it deployer get you borrow user data one more time just so we can print out the final amounts. Now, you'll notice something though, we're going to give back all of the dye that we borrowed. However, we're still going to have a dye balance, you'll see that when I run this that we're still have a little bit of Aetherium borrowed, basically, we'll still have a dye balance because we'll still have a little b
it of die borrow and try to figure out why before I answer it actually. So we have this tiny, tiny tiny amount of eath borrowed here and we have a much larger amount of eath deposited so Why do we still have this tiny, tiny amount of eath borrowed? Well, the reason is because as we borrow dye, we actually accrued interest. So we still owe dye back. Now what we can do is we can do something like uniswap, to actually swap our Aetherium, for dye to repay the rest of our debt here. And that's how we
could actually finish repaying all the debt is to get a little bit more dye to pay off that interest that we had accrued. And if you want, you can go back and you can do the exact same thing we did here to grab the uniswap code, place it in here to programmatically repay your debt as well. But at this point, you have just gone through the entire lifecycle here. And that is absolutely massive, huge congratulations. You've just deposited borrowed and repaid tokens from the AVI protocol. Now I'm g
oing to go briefly show you what some of these transactions are going to look like on an actual test net, on an ether scan, you'll see that when we deposit our collateral, we actually get back what's called an A token, or an interest bearing token, these tokens keep track of how much collateral or in our case how much web token we have deposited in the AVI protocol. And when we want to withdraw our wealth back, we burn these eight tokens, we remove these eight tokens, you can see that our first
transaction is going to be deposit and I wanted to show you what it looks like when you actually deposit one of these tokens, this transaction associated with this lending pool, that deposit right here, if you look at tokens transfer down here, you can see we actually we deposited, you can see that we actually sent rapt ether to the ARB a contract. Now you'll also see this a weath stuff here. So what is this a with stuff. So to keep track of how much you've actually deposited into Ave, Ave will
give you your own a wealth token or a token to keep track. And this is this interest bearing token, you actually can see up here a little bit of interest already for actually depositing these tokens into the protocol. And it's this token, that will keep going up, the more people borrow and the more people use the protocol. So you can actually grab this token address, interest bearing token this a token, I can import it into my meta mask. And I can see that I have 0.1, which represents my initial
deposit 00517 dot that dot A with and if you keep this up long enough, this number will slowly go up as you get more and more. Because the interest keep out and you can see just went went up right there, the interest will keep changing and keep going up. Obviously, we have so little deposited that the interest isn't gonna go up very quickly, but it will go up, the more people use the protocol. And since I'm using a test net, the actual usage of the protocol isn't very high, but you get the pict
ure. Awesome, you've done phenomenal to get this far. Let's do a quick recap of everything that we've learned. And then we'll head on to the next section. So first, we learned about the web token or the wrapped Aetherium token, it's a way to tokenize our Aetherium or layer one blockchain native token. Then we learned a little bit about the AVI protocol, and how it's this defy primitive for borrowing and lending assets. And we can actually gain interest by depositing our tokens and our assets int
o Ave we learned a little bit of also about uniswap, which is another incredibly important defy protocol, which allows us to swap tokens between each other in the decentralized context, then we learned that we can actually deposit some of our tokens into the AVI protocol, which is a decentralized borrowing and lending platform and similar to a bank will actually gain interest on our deposited tokens. But first, we have to approve them. Because anytime you want a contract to interact with your to
kens, you need to approve the contract to do so. And then we go ahead and deposit once we deposited we got the dye price. And then we learned that we can actually borrow dye we can borrow an asset based off of how much collateral we put down. And then we learned how to repay it back. We learned about forking a blockchain as opposed to using our own main blockchain. Another thing to know if you are using an RPC URL like something from alchemy so awesome you've learned a ton about defy now defi is
an absolutely massive powerhouse when it comes to the blockchain. And it is one of the most important things blockchains can do. If you want to learn more about defy and read more on Defy. I've got some more links in the GitHub here so that you can learn more about defy and one of them in particular that I want to show you is this one called speed run Etherium. Not only does it give you a ton of defy examples, but it gives you a whole bunch of other examples as well. And this will be a good tes
t of everything that you've learned after you pass this course. Or even right now if you want to or whenever you want and to talk about it a little bit more, we actually have Austin Griffiths here to talk a little bit more about speed run Aetherium himself, I'll pass it over to Austin. Hey, what's up, I'm Austin Griffith, I want to show you speed run Aetherium. speed run Aetherium is a great way to get started in Aetherium. If you are a developer, it's targeted at web two developers becoming web
three developers speed run a theory. m.com is the website. It takes you through both getting started and kind of getting getting an idea for the language and the syntax. But that's just the start. Just understanding the language is just the start, you feel like you're you can do anything. And you're on the top of the world when you finally get the syntax of solidity together, and you can jam through a smart contract. But really getting context with the space and figuring out what works and what
doesn't, that's a whole nother battle. And that's where speed run aetherium.com comes in. So let's speed run the speed run. First, you will get scaffold e down speedrun Aetherium kind of revolves around scaffold eath and uses scaffold eath as a base, you'll want to tinker around with some ideas within solidity. And let me show you what I mean by that. So with scaffold eath, you have a front end and you have your smart contract. So scaffold eath comes with hard hat out of the box. And you will u
se the combination of hard hat and react to build a DAP where you'll deploy both the smart contract and the front end. And this, this ability to edit your smart contract and have your front end auto adapt to it is kind of the key to scaffold ease. I just added some extra extra exclamation points. But we'll see that show up over here. Once this contract deploys, there we go, there's that. So just real quick, again, if I create like a un 256 public counter, and we set that equal to five, and then
I build a function called increment, that's public that does counter public, there we go, that does counter plus, plus, you can imagine what's going to happen here. So you, you edit a little bit of solidity, you deploy your contract, and then your front end auto adjust to that. And it gives you the ability as a developer to call those functions tinker with your smart contract to play around, you can even have a console log in there, where it you know, sets says the count now is there we go somet
hing like this. And let's go ahead and deploy that. Notice I'm doing these quick iterations, I'm making small changes in solidity, and I'm seeing those changes show up in the front end. And I'm tinkering with those in the front end and testing my assumptions. Here, if we go look at our hard hat node, when I make this increment call, we should see that nice console log there, you know, this address, set the count to eight, right? Very, very cool. So this is scaffold eath. This is what speed run A
etherium is built on top of, you'll get in here, you'll edit your smart contract, then you'll edit your front end, you'll point your front end at some particular network, you'll deploy your smart contract, you'll deploy your app, it just gives you the ability to have a front end along with your smart contract. And you'll have that as you're building your smart, smart contract. So to have this front end, to tinker with your smart contract is going to help you kind of figure out how you want to wr
ite your solidity, like, is this going to be a mapping? Is this going to be an array? How am I going to track this struct, you can kind of do this in an iterative process by just throwing it in here into your smart contract and tinkering with it on the front end and trying it out and seeing what you need to build. So that's scaffold eath. And that's the base that you'll need to get started with speed run Ethereum. Once you've you're able to have this all installed, you'll you'll have your kind o
f react front end here with yarn start, you'll have yarn chain, which will run your your hard hat node, then you'll do yarn deploy. Once you have that setup locally, you're ready to go with speed run Aetherium. And you can also do this right here and challenge zero. So challenge zero, gotta go zero index, right, we got to be nerdy challenge zero sets you up with just getting the environment setup, you'll you'll quest on building a simple NFT example. It's going to come with an NFT smart contract
. And it's going to come with an NFT front end a little kind of like minting view, it'll come with all of this stuff to do that. And it'll walk you through basically challenge the row is going to hold your hand, it's going to take you through every step you'll have to get get you have to have a certain version of node E, L some some correct range of node and yarn installed. Watch out yarn has an executable on Linux, make sure you have the yarn, the package manager. But after you have get your no
de and yarn, you'll run through cloning down each challenge. You'll do an install, you'll fire up the chain and you'll fire up your front end. And you'll have a working app that lets you interface with your NFT smart contract. You'll go through here and you'll learn about wallets. Then you'll start minting NF Ts and you'll send those NF T's are Round. And that's challenge zero, it's just getting you started. Here even in challenge zero, you'll deploy this NFT to Rinkeby. And you'll also deploy a
n app and allow your friends to go to your app and mint in FTS on Rinkeby. So that's the first challenge, it looks like we even like dive into open see and play around with some of those mechanics. The second challenge challenge number one challenge one of speed runner theory is like where it all really starts. This really shows off the superpower of Aetherium. It sets it up. So you need to build an app where a bunch of people that don't necessarily trust each other, can coordinate and stake int
o a smart contract. And this is like, this is the superpower of Aetherium. The ability for you, the developer to write a few simple rules to allow jerks to coordinate financially, and not greet each other and steal each other's money, right? You're we're building these financial systems, there's, you know, game theory and economics and so many other things going on here. But you as the developer, you're writing simple rules, and you're building a system that allows people to coordinate. So chall
enge one, we'll take you through how to get set up with your steak or docile, smart contract, you'll install everything exactly the same way, you'll fire everything up. And then it's just going to walk you through the kinds of things that you will need in your smart contract. But you'll have to write the solidity yourself. So this is this is not going to be a handheld tutorial, hell thing, you're going to have to write the smart contract yourself. And there's some guidelines and some rails that
kind of help you out, but it's not going to do it for you. Okay, so that's, that's Quest One is or that's challenge. One is building a decentralized staking app. Then challenge two is building a token vendor this so in challenge one, you'll learn things like how to send money into a contract, how to have a contract, keep track of mappings. In challenge two, you're going to learn contract to contract interaction, you're going to learn about ERC 20s, you're going to learn about specifically the ap
proved pattern, which is kind of a jerk, it's, it's hard, it's a hard thing to deal with is the approved pattern, you need to go to your token contract and approve the vendor to take some money, then in a second transaction, you need to go to the vendor and have the vendor grab the money from the token contract and do something else. So that's that's challenge two is learning about tokens and vendors, and is starting to really like get you kind of exposed to the idea of this like massive multipl
ayer game that is Aetherium. And also kind of like how to build these vending machines that anybody can get to, then you'll build a Dex. Now once you've once you're done with 01. And two, you're really kind of you have a license to learn at this point, you're you're ready to really like go do some damage and build some cool things, maybe go build a couple other things, but come back and come come hit challenge three, challenge three is going to be a little bit more open ended, there's going to b
e a cohort of other people that are also building this. And you have to get through the first three challenges to even get to challenge three to even get to this chat room. But there's a chat room where other developers that are also building their own decks are all there together, and you can kind of learn with them and chat with them. But you're going to build an exchange. And you're going to build an exchange that works in a smart contract in a decentralized way with no centralized breaking p
oints. And what that's going to mean is you're going to have to have reserves of both eath and tokens and you're gonna have to have a pricing function and LP tokens and all sorts of other things that you'll have to learn about as you get to it. Then challenge five is a multi SIG wallet. Such a fundamental important thing about how to store your eath safely is going to be in a multi SIG wallet and how you can have multiple identities even even like the the base of like what a Dow is, is sort of l
ike starting with a multi SIG wallet. And you'll need to build one of those you'll need to understand call data call data is super weird and complex. And everything's a transaction even when you're just poking a contract. It's a transaction, and you have to craft that call data correctly to say, I would like to call this specific function on this specific contract. So that's multisig wallets and then it kind of ends up we've got more challenges in the pipeline, but it kind of ends on build an SV
G NFT so much fun to build an NF t that crafts the actual drawing in the smart contract and renders it. So that's the speed run, go speed run Aetherium checkout scaffold, eat start building, build something awesome on Aetherium. hearts, hearts, hearts, go get them. Austin Griffith is one of the OGS when it comes to helping engineers get caught up and up to speed in the blockchain world so massive thank you to Austin for all he's done so far. All right now we're gonna get into NF T's. Let's do th
is. Now, I've already made a number of videos on what NF T's are and how to start working with NF T's. So we're going to watch a portion of the previous Python edition of this course where I explain and a piece from a high level and then of course, we're gonna get into the ultimate NFT tutorial. So let's learn about NF T's look, NF T's are hot right now. Nf T's also known as ERC 720 ones are a token standard that was created on the Ethereum platform. Nf T stands for non fungible token is a token
standard similar to the ERC 20. Again, ERC 20 is like link of a maker, all those goodies that are found on the Etherium chain. An NF T or a non fungible token is a token that is non 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 ERC 20s one
link is always going to be equivalent to one other link, by contrast is going to be NF T's those of you nerds out there, we know like a Pokemon would be a good example of an NFT you're one Pokemon is going to have different stats, different moves, sets, and isn't interchangeable with any other Pokemon, or maybe a more relatable one. It's like a trading card, or unique piece of art or the like. So that's what these NF T's are there non fungible, 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 whose own them who's deployed them, etc. Now, like I said, NF T's 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 a
bout it is by calling them ah, ah, ah it's odd, or some type of collectible or just anything that's unique. Now, they've been getting a ton of buzz recently, because we've been seeing more and more of these being sold at insane prices, like we saw x infinity sell nine plots of their land nine plots of their unique land for $1.5 million. We also saw the original creator of the Nyan Cat, you know, this cat sold for like 300 eath. So apparently people really value these things. 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 open sea or wearable. 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're helping give a good user interface. Now, like many of you out there, my initial thought to NF T's 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, and they never get attribution for what they make. 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 movi
es, those are pieces of art that I digest. And I really like and I think it's fair for them to get comped appropriately because they are providing value to my life. I think NF T's are a great way to solve this issue as kind of having these decentralized audit trails and, and royalty trails 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 ERC 721 standard are 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 the ERC 20 and ERC. 20 is they have a really simple mapping between an address and how much that address holds. 720 ones 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. Ea
ch 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 needed a way to define what that art looks like. If it's some type of character in a game, we need to wait define that character stats in the NFT. This is where metadata and token URI has come in. So if you know anything about Aetherium, you know that sometimes gas price
s getting 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 these are pieces on chain? And the answer is sometimes back when they were coming up with NF T's and artists were deploying stuff, the eath devs and the artists were like yeah, art, let's do that art. I'm just gonna deploy This one megabyte image onto the Etherium chain. And Oh god, it's so much gas expens
ive, delete button. Otherwise, it's not, it's not good. And they realized that if they put all this art on chain, it's 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 the token are, you can use something like a centralized API, or IPFS. To actually get that token URI. Typical token URI has to return som
ething 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 on chain metadata versus off chain metadata. Because it is so much easier and cheaper to store all your metadata off chain, 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 y
ou lose your image, you lose everything associated with your NFT. Because of this most NFT marketplaces actually can't and won't read off on chain attributes or on chain metadata, because they're so used to looking for the token URI. Obviously, if you do off chain metadata, you can't do anything really cool or really interesting or have any gains with your NF T's. For example, if you wanted to create an on chain Pokemon game, all your attributes would need to be on chain in order for your Pokemo
n to interact with each other. Because if it was off chain, then that becomes a lot harder to cryptographically prove. So if you're new with NF T's 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, I'm 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 DND article does a great job of walking you through thi
s 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 on chain attributes. Again, having your attributes on chain is really going to allow you to build really creative NF T's 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. Alright, so now th
at we know the basics of approximately what an NF t is, and similar to the ERC 20 You can see the E IP 721 or the ERC 721 non fungible token standard on the Aetherium, ie IPs. And once again, if you scroll down, you can see all the different events and the different functions that come with creating this token. And now everything that we're going to do is going to be available at this GitHub repo. This hard hat NFT FCC, we're going to actually go through all the code down to deploying and creati
ng our own customized NFT. And I've labeled this the ultimate NFT repo as part of this course, because we're going to go through a lot here, we're gonna go through a basic NFT, a real minimalistic NFT and then an IPFS hosted NFT. That is dynamic. And it uses randomness to generate unique NF T's so that we can have provably rare and appease or provably rare cards or provably rare tokens or stats or whatever you want. And then we're going to do what's called an SVG NFT. These are entities that are
100 percent hosted on chain, so you don't need an off chain. So you don't need IPFS, you don't need an off chain database. And this one's also going to be dynamic, where it's going to use price feeds in order to fluctuate what the image of the entity actually looks like based off the price of some asset. And here are the images that we're going to be using. And we obviously have these three adorable doggies here. If you want to follow along with the Quickstart, you absolutely can. And I'm going
to do a quick overview of just running the code to show you what it's going to look like at the end. Basically, what we're going to do is we're going to have our code, we're going to run hardhat deploy dash dash network, rink B, dash dash tags main. And this is going to deploy all of our contracts and everything. And then finally, if we go to test nets dot open c.io And we grab the address of one of these NF T's we should be able to put it in here see our actual NFT as a collection with an item
. Or Additionally, we can just go right to the contract. We can read the contract, we can get the token URI, and then we can copy this token here, I paste it into our browser or any IPFS is into our browser, and then grab the image attribute and see what this actually looks like on chain. So with all that being said, let's learn how to build this ultimate NFT repo and build all of these different customizable NF T's let's jump in. So once again, we're in our terminal I'm going to create a new di
rectory. We're gonna call it hard hat and a T for FCC. We're gonna cd into that. And if T FCC and we're going to open that up with code.or, you can hit File, Open Folder At this point, you'll have gotten pretty familiar with the setup of our code bases here, feel free to copy over or do whatever you want to do for our setup, we'll do yarn, add dash dash dev hard hat. And then while that's loading, I'm going to copy over my prettier files. Because I want to use prettier, I'm going to copy over my
hard hat.config.js. And I'm also going to grab my package that Jason copied over here, I'm going to delete this old package dot JSON. And I'm just going to hit Enter on this and rename the one I just copied over from package copy to package json. And the reason I'm doing this is so that I can just go ahead and run yarn and install all this stuff for me. Or we can just come back over here and just grab this lesson nine hard hat, smart contract lottery, all that stuff, again, just run that massiv
e piece as well. Or you can copy over your package json, and then just run yarn that will do the same thing. Now we don't have to keep doing this boilerplate over and over and over again. And then while that's loading, I'm also going to grab my Dotty and v file that we've been using on a past couple of projects, the readme.md. And we'll just do what we're gonna be doing here. So we're going to make three different contracts. One is going to be a basic NFT, using that ERC 721 standard, then we're
gonna do a random IPFS hosted NF t. And then finally, we're going to do a dynamic S V G NFT. So our random NF T is going to be random at creation time, this is going to give some true scarcity and some true randomness to our NF T. And it's gonna be hosted on IPFS. Our dynamic SVG NFT is going to be hosted 100 percent on chain, and the image of it's going to change based off of some parameters. That's what makes it a dynamic SVG NFT. Let's go ahead and we'll create a new folder, we'll create our
contracts folder, and we will create our first NF t this is going to be our basic NFT. And I'm going to go a little bit quick here, because most of what we're going to be doing is actually things that we're already familiar with. So we'll do basic NF T dot soul in a new file. And let's go ahead and let's do it. Let's go ahead and we'll do spdx license identifier, it's gonna be MIT. We'll do pragma, solidity, carrot zero, point 8.7 pragma, solidity, and then we'll do contract, basic NF t. Let me
just basic, get a t.so, like that. And we'll say contract basic NF t. And then we'll just run hard at compile or yarn hard, hit compile, and it looks like we're doing well here so far. Okay, perfect. Based off of that NFT token standard, we go back that EIP, we're going to need a whole bunch of different functions here, we're going to need transfer events, we're going to need owner events bounce up, we're going to all these different functions. And we could 100 percent implement these and trans
fer them exactly like the ERC 20 did, or once again, so we can use, you guessed it, we're gonna be using open Zeppelin contracts for this as well. So we come back over to open Zeppelin, we go over to contracts. And we're gonna go ahead and add this with yarn, add dash dash Dev. So yarn, add dash dash dev at opens up on contracts, like so. And while that's going through, we can look at the ERC 721 of this and we can see what creating a minimalist ERC 721 looks like. Now there's a number of extens
ions that come with its ERC. 721 In this example that they give us. They're using ERC 721 Uri storage, which we'll talk about in a little bit. So we've added it in here. And now we can actually import that ERC 21 from opens up when in our contract. So we'll do import at open Zeppelin slash contracts slash token slash your C 721 slash ERC. 721 does so they use a different one in the demo, but don't worry about that. And same as the ERC. 20 we're gonna say our basic NFT is ERC 721. So we're doing
this inheritance, you find the constructor, we can see this has a constructor, where it takes a name and a symbol. So we're gonna want to use this constructor and our contract. So we're gonna say, construct door. And our constructor is just going to be blank. But we'll do the ERC 721 constructor and we'll call this a doggie. And the symbol will be dog just like that. Our basic NFT we're just going to have it be this doggy here, right so it's going to be an NF T of just a purely this dog here. Th
e name is going to be doggy and the symbol is going to be dog. Now in order to create new dogs. What we're going to do is openzeppelin code comes with something called a mint function exactly the same as the ERC 20 So we're going to create a function called mint NFT this will be a public file function that's going to return you activity six. And we'll use the safe mint function of this ERC 20 or underscore safe mint message dot sender will mint the token to whoever calls this mint function. And
then we need to also give this a token ID, if we're looking back at the code for the ERC 721. And again, you can see this on GitHub as well, we're gonna look at this safe mint function, it takes an address to who is going to own the NFT. And then a token ID, what is the ID of the token based off of this address. So if you have a collection of tokens on the same smart contract, each one of them needs their own unique token ID. So what we're gonna do is we're gonna create a un 256, private variabl
e called S underscore token counter, and it's gonna get initialized in our constructor to zero, but we'll just be explicit and say es token counter equals zero. And then in here, we'll just have the token ID of this new NF t be that token counter. And then of course, we'll say s token counter equals s token counter plus one. So every time we meant a new NFT, we up the token counter, and then we'll just return, we'll just return the new tab counter. Right. And then obviously, at the bottom, we co
uld do like function, get token counter, this would be a public view returns you in 256. And I'm gonna go a little quick here, because you've seen this before, return s underscore token counter, right, since it's a private variable up here, the public function down here to get that token counter. So this technically, is it. This is technically an NF T. But what does this look like? Well, right now, this NF T isn't going to look like anything at all, in this EIP token standard. It has this thing
called a token URI. And this is the important function that tells us exactly what this token is going to look like. Like what we said in the mini lesson here. This token URI returns some type of URL or universal resource identifier that returns some JSON that looks like this. And in this JSON, we're going to have this image part. And this image is going to be a URL that's going to point to what this image actually looks like. Now this URL can be hosted on chain, it can be hosted on IPFS, it can
be hosted really wherever. But ideally, we're not going to use a centralized server to host it. If this is hosted on a Google Cloud or a centralized server or whatever, and our centralized server goes down. Well guess what this MC is gonna look like, it's not gonna look like anything. So we want to use some type of decentralized storage, to get a URL, or URI to store what this looks like. To make this section a little bit easier for you, I've actually already gone ahead and hosted an image to IP
FS. For you, it's going to be at IPFS dot dot slash slash, it's going to look like this, this is going to be the image that we're going to use for our dog here. If you create just this image, though, as the token URI, that's not going to work, we need a URI that returns this, with the image inside of it. Now for this first section, have already gone ahead and done that for you as well. And that's going to be located here. This is what our token URI function needs to return. So it's going to have
the name, the description, the image URI, which then points to the dog, and then some attributes, etc, etc. Now, you'll notice that the image here is pointing to HTTPS, dot dot slash slash ipfs.io. The reason I did this was again, just in case you didn't have the IPFS gateway, but this would be a lot better if this was in its IPFS form. Because if the centralized server ipfs.io, goes ever goes down, this NFT will show what it'll show nothing. So it would be much better. If it was instead of ipf
s.io. It was IPFS, colon slash slash, like that, instead of ipfs.io. But for now, this is what we're going to be using. And you can just go to the GitHub for this, just to grab this for this section. Right? Just go to contracts, basic NFT, you can just grab this, this, this top part, just copy it like that. So we're going to paste that the token URI up, up, up at the top, like so. Oh, it should be returns, return. There we go. Okay, cool. So we're just going to copy paste that in here like this.
Like I said, even though the token URI here is pointing directly to IPFS, which is good. If you actually go to this file, the file is actually pointing to http.ipfs.io. Again, for your NF T's don't do that for this NFT. I just did that just in case, but for your NF T's don't do that. And we're going to make this a public constant variable. Why? Well, because this token you write is never going to change. We're going to make this NFT so that everybody who meets one will have this exact same ador
able little puck here. And the way we do That now is we need to identify the actual token URI function. So I'm going to do it above get token counter, we're going to say function, token URI. And these always take a UNT 256 token ID, we're going to make this a public view, override returns string memory. And this needs to return the token URI. Now, this is going to be the most basic way to create this, right. And if we wanted to make this function a little nicer, we'd comment out token ID as well
, since we're actually not using token ID. But we're overriding in our in the ERC 721 that we're importing. This has a token ID function or a token URI function. And we're overriding this, right, we're not using this at all, we're saying, Hey, we're just going to use our own here. And that's all we need for this to work. And now if you were to deploy this to rink B, if you were to jump over to open C test net, and you would deploy this, this dog, this adorable little pop would be what shows up f
or all the minutes. So let's go ahead, and let's create a little deploy function for this. So we'll do a new folder, deploy a new file, we'll call this a one deploy basic NF T dot j s. And this is going to look real similar to everything that we've done before. So I'm going to move a little bit quicker here. const network equals require hard hats, const development chains, equals require dot dot slash helper, hard hats config. And I don't think I added that. So I'm going to copy paste my helper
Hardhead config from our last project. And if you get confused, you can always just come to the GitHub here, and just go to the helper Hardhead config and grab it from here, we have that const development chains, or say const verify equals require dot dot slash utils. Slash verify. We're also going to grab our utils, I'm going to copy paste so utils folder from alas project, once again, you can copy paste from your last project, or you can just go straight to the repo, grab the verified dot j s,
we're going to go over these two functions a little bit later, but at least grab the verified for now. And then we're gonna start the function. So we'll do module that exports equals async function. We're gonna get get named accounts, and deployments. And we're gonna say const. Deploy, log equals deployments against deployer equals await, get named accounts. So we'll do a little log here just to get started to do our basic NFT doesn't take any constructor parameters. So we'll say const args equ
als a little blank here. Then we'll do const basic NFT equals await, deploy basic NF T, exactly what we've seen before a number of times at this point, we'll say from Deployer. args is going to be args. And then log, it's going to be true. And then we'll also do weight confirmations. It's going to be network dot config dot block, confirmations, or one. Then if we want to verify this, we're going to once again do if it's not development chains, dot includes network dot name, and process that EMV
dot ether scan API key will say log verifying dot the dot await, verify basic NF T dot address arguments which are going to be blank, grab this little log here, stick it right underneath. And then actually in our basic NF T. This should be args not arguments. Now we have a deploy script. Now we have a basic NFT here in test data deploy script, or any hh deploy or yarn Hardhead deploy. And oops, let's go back to the basic kind of tea or mint and have tea needs to return a UNT 256. Try again. Get
token counter also needs to return a UNT forget you into anywhere else. Nope. Okay, looking good. And looks like we're compiling well compiled, deploying Well, now if you want to deploy this to rink B, you can. I recommend holding off though, because we're going to do that at the end. Now that we've written a deploy script. We've written the contract, you already know what's coming next. Yes, neat. What's next is the tests now because we're not actually learning too much more here. I'm not going
to walk you through writing this test. I'm going to challenge you now. How to pause the video and write the test out yourself and see how far in this test you can actually get. Remember, to test it, you're going to want to run yarn, hard hat test, right, let's see if you can actually write the test yourself, then come back to the video, see if your tests were just as good or not as good as what we did here. And of course, you can always go to the GitHub repo test sections. And if you get lost,
you can look at the basic nft.test.js To follow along. All right, welcome back. Hopefully, you wrote some awesome tests, taking the time to actually do some of those exercises is really going to make you a much better engineer. Following along with me, it's awesome. But tinkering yourself and trying to do everything yourself is really what's gonna make this stick. So I hope you did pause the video. And hope you did go ahead and try to write the test for this yourself, you've technically just cre
ated a really minimalistic NFT. Great job. Let's kick things up a notch. Let's move now to a random IPFS hosted NFT where we're going to do everything pretty much programmatically. So let's jump in. In our contracts, we're going to create a new file random IPFS, NFT, dot soul. Same thing. spdx license identifier, gonna be MIT pragma, solidity carrot zero, point 8.7, or whatever version you want to use, will do contract random IPFS NF? T, like so. So what is this one going to do? So instead of ju
st minting any NFT, when we meant an NF t, we will trigger a chainlink VRF call to get us a random number. Using that number, we will get get a random NF t that we're going to decide on. And the random n of t that we're going to use, it's going to be either a pug a Shiva in you, or a St. Bernard. So whenever anybody mints NF T, they're gonna get one of these random three dogs. And we're going to make this so that each one of these dogs have a different rarity, we're going to make these dogs rare
by different amounts, say we want the pug to be super rare, the Shiva to be sort of rare, and then the St. Bernard to be pretty common. So probably it's gonna be super rare Shiva in us is gonna be sort of rare, St. Bernard is going to be pretty common, right? Or the most common, if you will. So let's go ahead and start building this, we're probably gonna have to make a function called like request NF t, because we're going to know that we're gonna need to kick off a channeling VRF request, we'r
e probably gonna have to make a function fulfill random words, that's going to take a un 256 Request ID and a un 256. Array, memory random words, as we've seen before, we've done fulfill random words in the past. And let's let's even go one step further, we'll make it so that users have to pay to mint an NF t. So this is going to be they have to pay a certain amount of eath to get the NFT and then the owner of the contract and withdraw the eath. So we're basically paying the artists here, we're
paying the artists to create these NF T's. And then they can be the ones actually actually withdraw the payment for all these NF T's. And we're also going to need, of course, a function, token URI, which takes a un 256. And this is once again, same as our basic NFT gonna be what this token actually looks like. So let's go ahead and get started creating this. Now, because these red lines are going to draw me crazy. We're going to add some visibility here, we'll make this request NFT public fulfil
l random words, we actually know from the past is going to be internal token URI is going to be public. Let's build this request NFT. And again, to request a random number, go back to EVM. Chains, we go to using randomness, we can follow along with the Dr. chain link again, to figure out how to get this random number. So since we know we're going to be working with chain link, we want to add at chain link slash contracts. So back in in our code base, we'll add that in yarn add dash dash dev at c
hain link slash contracts, like so which was perfect. And we can go ahead, and we're going to import that VRF consumer base V two and the VRF coordinator interface into our code because we know we're going to use both of these. If you want to just copy paste from the docs, you absolutely can go to pause here. And since we're going to be using this view of consumer base, we want to inherit it. We're going to say random IPFS and f t is V RF consumer base V two and this little, little wiggly line w
ill show up here saying This seems to be override. So I'm just gonna go ahead and add override here. And this little wiggly line is gonna stay there for a little bit until we implement the rest of the functions. So let's go ahead and implement the rest of those functions. Request NFT, of course, is going to be public here. And in order for us to request an NF T, we're going to need to call the coordinator dot request random words where we pass all this stuff in. Right, so let's go ahead and get
all this stuff for our V REF coordinator in our constructor, so let's create a new constructor. struct door. And we're going to use the VRF consumer base, the two constructor to use to create our constructor, the VRF consumer base V two needs an address in here for the VRF consumer base. So we'll go ahead and we'll do address VRF. Or did Nate Torre b two. And then we'll pass this to the VRF consumer base constructor here, just by adding that that red squiggly line has gone away from me perfect.
And we want to save that address to a global variable. So we can call request random words on it. So we're gonna go ahead up here, we're going to say I underscore var F chord. To me, Tor, we're going to make this immutable VRF coordinator. And we're going to do it by saying VRF v2 interface, it's gonna be private, immutable, you have coordinator and then in our constructor here, we're gonna say IVF coordinator equals VRF, coordinator v2 interface wrapped around this like so. So we know we're goi
ng to need this, we know we're actually gonna need a ton of these. So let's just add all these variables in here, we're gonna need the coordinator, we're gonna need a UNT 64 private, immutable, I underscore subscription ID, we're gonna need a bytes 32, private, immutable, I underscore gas lane, we're gonna need a you int 32 private, mutable, I underscore callback gas limit, we're gonna need a UNT 16 Private constants, request confirmations, we're gonna say it's gonna be three, and then a un 32.
Private constant equals num words, which is going to be one, and we'll get this red squiggly line saying it's mad at our our constructor here. So let's go ahead and add all of our immutable variables in our constructor. So we'll get the VRF coordinator v2 from our constructor will get the UNT 64 subscription ID, we'll get the bytes 32 Gas lane, aka the key hash, we'll get the un 256. We'll do a UNT 32 callback gas limit, then we'll go ahead and do I subscription ID equals subscription ID will do
I gas Lane equals gas lane will do I call back gas limit equals call back. Yes limit. Okay, a lot of variables set up. But those are the variables that we're going to need for the chainlink VRF. Now we have all these variables down in our request. And if t we can request a random number to get for our random n of t, we're going to say and our returns a yuan tivity six Request ID. So in here, we'll say request, Id this request ID that we just initialized I underscore VRF. Core didn't a Tor dot r
equest. random words. And this should look pretty familiar to what we did in our lottery. I underscore gas Lane comma, I underscore subscription ID, comma, request, con for nations. I underscore callback gas limit. And then of course num words and we can just literally copy paste this from the documentation or from our last project, whatever you want to do. So we are requesting this random NFT here. Now here's the thing, though, we want whoever called this request function it to be there and hav
e tea, right. And if we saw in our basic NFT, when we minted the NFT, we call this safe mint which needed the owner and the token counter. When we request a random number four are NFT. It's going to happen in two transactions, right? We're going to request and then later on we're going to fulfill and it's going to be the chain link node that's calling fulfill random words. So if it In the fulfill function, we just do this safe meant message that sender, the owner of this NFT is actually going to
be the chain link node that fulfilled our random words. So we don't want that, what we want to do is we want to create a mapping between request IDs. And whoever called this so that when we call fulfill random words, which returns with that exact same request, ID, we can say, Ah, okay, your request ID X, you belong to the person who called this request and of team, we're going to create a mapping between people who call this and their request IDs so that when we fulfill random words, we can pro
perly assign the dogs to them. So up at the top, right underneath here, I'm going to call them VRF helpers, we're going to create a mapping of un 256. To an address, we'll make this public which we should make it private, but we'll just make it public s underscore Request ID to sender. And then when we call this request, and F T, will set the request ID to sender of Request ID equals to message dot sender. Now, when the chain link node responds with fulfill random words, what we can do is we can
say address dog owner or the NFT dog owner is going to be equal to s Request ID to sender of Request ID. This way, it's not going to be the chain link nodes that are going to own the dog, but it's gonna be whoever actually called requests. NFT. Okay, cool. So we have a way to request a random number for our random NF t. Now, let's go ahead and mint this random dog, this random NF T for this for this user. So we have the user now using this mapping, what else do we need? Well, we're gonna need t
he token counter here. Let's go ahead and we'll create a token counter variable. So we'll scroll up and make a new section. And we'll say, un 256. And then again, we'll just make a lot of these public just to make it easier, but you might want to make this private and use that same syntax we were doing before do s underscore since this is a stored variable, token counter. And we'll grab this token counter. And we'll say you went to 56. New token ID equals as token counter, now that we have the d
og owner, and the token ID, we can go ahead and mint this MFT. So we'll do safe mint. Owner, new token, ID and then safe man is going to be squiggly because our code is gonna say, what is this? What is the safe mint function? Where did you get this from? Well, we're gonna need to get it from open Zeppelin again. So we're going to go ahead and do import at open Zeppelin slash contracts slash token slash ERC. 721 slash ERC. 720 one.so We'll say a random IPFS empty is Vera of consumer base, and als
o ERC 721 In our constructor, right after our V RF consumer base, we're going to put the ERC 721. And same thing, we need to give it a name and a symbol. So we'll call this random IPFS NF T. Comma, we'll just do Rin for random IPFS NF team. Now safe mint actually works and then it's gonna be mad at me for this. So I'm gonna do override just let it stop getting mad at me. public view override turns string memory. Just that squiggly line goes way. Okay, cool. So great. So now we can safe mint to t
he dog owner this new token ID Are we done with this? Absolutely not. Why not? Well, we don't know what this token looks like. And what we set above is we want to actually make these dogs different rarities. So how do we actually create these dogs with different rarities, all we could do is we create a chance array an array to show the different chances of these different dogs here. So down below, we're going to create a function and it's going to be a public pure function called get chance arra
y. And this is going to return you went to 46 of size three in memory. And this chance array is going to represent the different chances of the different dogs. So we're gonna say return 10 3100 Or we're gonna say Max chance value. And up at the top under empty variables. We're gonna say you went to 56 internal constant, Max chance value equals 100. So by making this array, we're saying index Zero has a 10 percent chance of happening. We're saying index one has a 20 percent chance of happening be
cause it's going to be 30 minus 10. And then we're saying index two is going to have a 60 percent chance of happening, because it's going to be 10 plus 30. minus this 100. This array that identified the percentages of the different dogs. We're saying the pug is going to have a 10 percent chance, Shiva in you a 20 percent chance and the St. Bernard a 70 percent chance, we're going to use it to give this token ID that we just minted its dog breed. So we're gonna create a new function called Get br
eed from modded RNG. And the reason we're calling a get breed from modded RNG is exactly the same way. In our lottery. We got a random number, we're gonna say you went to 56 modded RNG equals random words of zero mod Max chance value, we're going to mod any number we get by 100. Doing it like this, we're always going to get a number between zero and 99. If random words zero mod Max Chin's value is going to be seven. That means we're gonna get a pug. If we get 88. That means we're gonna get a St.
Bernard, if we get a 45. We're gonna get a what? That's right, a St. Bernard, if we got a 12 We're getting a Shiva in you. If the mod ID number that we get by modeling this random word is between zero and 10. It's going to be pug between 10 and 30. shiba inu between 30 and 100 St. Bernard and that's how we get these randomness values. So now that we have this modded RNG, we have this mod ID number that's going to be between zero and 99. Okay, this function called Get breed from modded RNG. And
this is going to take the UN 256 mod ID RNG will make this a public pure function, and it's going to return the breed of the dog. Now the breed of the dog is going to be an email similar to raffle state that we did before. We're going to do this right at the top since this is going to be what a type declaration or say enum. Read, we're going to say the zero with number is going to the pug. The ones number is going to be the Shiva in you. And then the second one is going to be the St. Bernard. So
we have the pug which is zero to 10. Shiva in you 10 to 30 St Bernard 30 to 100. So get breed from modded RNG public pure returns breed. So we're gonna loop through this we're gonna say you intuitive six cumulative sum equals zero, we'll say you went to 56. size three memory chance array equals yet chance array. So we're getting that chance array. So we're going to create a little for loop we're gonna say for you went to 56 i It's gonna start with zero is going to be less than the chance array
dot length. i plus plus ran through that for loop here. And we're going to say if modded RNG is greater than or equal to this cumulative sum and modded RNG is less than the cumulative sum plus chance array plus wherever we are on the chance array, then return breed of AI. And then outside of this, we're gonna say cume cumulative sum plus equals chance array of I, let's say moderate orangey equals 25. And if it's 25, it should be a Shiva in you, because that's between 10 and 30. So we're saying i
f mod RNG, which is 25 is greater than or equal to cumulative sum, which right now is zero, and it's less than n, the Moto G is less than the cumulative sum plus the chance array of I which is going to be 10 Return breed of I cumulative sum is currently zero plus chance of I which is 10 is going to be 10. And this is not true because Morarji is 25. So since this is not true, we're going to move to the second step which is just cumulative sum, plus equals chance right? So cumulative sum will now
be equal to 10. And then we reached the end of the for loop. So we'll restart i is now one, so let's try this again mod RNG is greater than or equal to cumulative sum Okay, that is true cumulative sum is 10. Mod RNG is 25. And mod RNG is less than cumulative sum plus chance re of AI, which is 30. So we're saying 25 is less than 10 plus 30, which is 40. Return breed of AI, this is true. So breed of AI would be true and AI at the moment is one. And if we scroll up, that's indeed the Shiva in you.
So that's how this function is going to work, it's going to get us the breed from that modeling bit. And then if for some reason, some really wacky stuff happens here, we want to just go ahead and add a revert, right, because we should be returning a breed. But if we don't return a breed, we should just revert. So we're going to create a new error at the top, random IPFS NFT underscore underscore range out of bounds. The down below, we're just going to say if for some reason you don't return any
thing, just do a revert random IPFS NFT range out of bounds. And now we have this function. Okay, so now we can get the brief from a modded RNG. So pack in our fulfill random words function. Let's go ahead, and we'll say, we'll uncomment this will say breed, dog breed, equals get breed for modded RNG pass the modded RNG here, and let's move this safe mint down below us getting the dog breeder so we can mint and add the dog breed at the same time. So we're gonna go ahead and safe mint here. Now w
e can do a few things to set this dog breed here, we create a mapping between the dog breed and the token URI, and then have that reflected in this token URI function. Or what we could do is we could just call a function called Set token URI and the openzeppelin ERC 721 You have to set this token your eye function yourself. However, there is an extension in the open Zeppelin code called ERC. 721 Uri storage and this version of the ERC. 721 comes with a function called Set token URI where we can
just call set token URI. And this will automatically update that tokens token URI to whatever you set it as. So we're going to use this extension this set token URI in our contract. And the way that we do this is instead of doing token ERC 721 Year C 721 that soul will do token ERC 721 slash extensions slash your C 721 Your arise storage. That's all. And we'll say random IPFS is ERC 721 your rice storage. Now what's cool is that our constructor will still just use ERC. 721 Because ERC 721 Uri st
orage is extending ERC 721. And then this contract just comes with some additional functions like set token URI. So right after safe meant, we're actually going to call set token URI with this new item ID. And then we're going to give it that breeds token URI, we're gonna give it a string here that relates to whatever breed that we just got based off the dog breed here. Now, to do this, what we could do is right at the top and our NFT variables, we could create a string array, internal, Alt S do
g token, your eyes, we're gonna make this constant where it would just be this array of all these strings that we created. But maybe in our code, we want to make this a little bit more variable. And we want to parameterize this. And that's exactly what we're going to do. So we're going to create this string array, internal s underscore dog token, your eyes, which is just going to be a list of these URLs are these URLs that point to stuff like this, we're going to do that in our code so that when
we upload any image that we want to IPFS we can then upload this s dog token you arise accordingly. In our constructor, we're actually going to take in another parameter called a a string of size three, memory dog token you our eyes, we're going to pass as a constructor parameter, these different dog token you arise. So we're going to pass it this list of dog token arise. Of course zero is going to be the token URI of the pug. One is going to be the Shiva in you and two, of course is going to b
e the St. Bernard. So we're going to pass it this list of dog token your eyes, and then down in set token your eye from that, that list that we created. We're going to set the token URI of this token based off of that array of the UN 256 version of that breed are casting this dog breed back into you and 256 to get its index. With that we now have a way to actually, programmatically get a provably random NFT with different randomness for different one of these NF T's. Now, let's go back up to our
little, our little comments we made here, limited NFT, we trigger a chain link or a VRF. To call random number, we got the rarities down, we got the minting down. Awesome. Okay, we don't have this part, though. Users have to pay to Minton NF T and the owner of the contract can withdraw the eath. Okay, this is stuff we've already done before, this should be pretty familiar here. So back in our request NF t function, we'll make this a public payable. And all we'll need to do is we'll just say if
message dot value is less than some mint fee, and actually let's go back to our constructor, we'll create a mint fee, you int 256 Mint fee. And then we'll do you in 256 internal I underscore mint fee, we'll make this immutable. And then we'll just say I'm intervene equals mint fee. If message of value is less than mint fee, you already know we're going to do a revert, need more eath sent, we'll create a new air called need more eath sent and actually we'll do air random IPFS and ft underscore un
derscore need more II sent like that, copy this, paste it here and boom. So now just by adding this line, this is now a payable function. And people have to pay some mint fee to mint their randomized NF t. Now we're also going to want a way for owner to withdraw. So we'll scroll down a little bit. We'll scroll down to here, CREATE FUNCTION withdraw, this will be public. And we only want the owner to do this. So we could create our modifier, you know, a modifier again only owner, or what we could
do is use openzeppelin. Again, openzeppelin also comes with some access code, or one of them's this ownable code, and in here, it already has the only owner modifier for us, we're just gonna go ahead and import that as well. We'll do import at openzeppelin slash contracts slash access slash ownable dot som, and we'll say contract random IPFS. And if t is this, this come ownable. And then we'll make our withdrawal function only owner. And so whoever deployed this contract is going to be set to b
eing the owner, which is what we want. And when here, same as what we've done, we'll do u and 256. amount equals address this dot balance. And then we'll do bull success comma equals payable, message dot sender, but call value is going to be a mount and then we're going to call nothing. And then we're going to say if not success. And we're going to revert with transfer failed, then on top, we're going to do error transfer failed. I'm just going to copy this a little quicker, like so and then com
e back down to transfer failed paste it here. So we're gonna revert random IPFS. And if T transfer failed, perfect, so now we have a withdrawal function and a way for people to pay for art here. Now we don't need this token URI anymore, because when we call set token URI, this is going to set the token URI for us because in the back ERC 721 Uri storage already has that function laid out. So our contract will already have the token URI function and we don't have to explicitly set it ourselves. Bu
t we do have to explicitly set some other ones. We are going to need function get meant fee will be a public view turns you went to 36 turn I meant fee will need function get dog token your eyes, you went to 36 index, this will be a public view which will returns the string memory return s underscore dog token your eyes index will need function get token counter. This will be a public view turns you into 56 Return s underscore token counter. Alright, so we just wrote a ton of code here. And of c
ourse as we taught you before, we also are going to need some events. So when we request an NF T, we're going to emit an event. So we'll omit NF T requested and then we'll pass it the request. ID in the message dot sender. So up at the top will say event NF T requested. So pet, take a un 256 index Request ID, and then an address requester. And then we're also going to make an event for NF T minted for when it's finally minted. And it's going to take a breed, dog breed, and an address, mentor. So
write down when we fulfill, we're going to emit NFT. minted. And it's going to take that dog breed and then the dog owner. Okay, we've just written a lot of code here. So let's go ahead and see if we can compile this with H H compile, or yarn Hardhead, compile. And Wow, looks like we went ahead and compiled it. This is great. So all of our code now looks good. Now might be a good time to take a quick breather, we've just written a lot of code. And it might be good to just go over all the stuff
that we just went through. A lot of this is familiar, but it's still really good to redo some of this stuff and really get that muscle memory and for these credit, an NFT contract that when you mint, one of these NF T's, you're gonna get a pug a Shiva in you or St. Bernard, based off of some rarity, where the pug is really rare. Ship it in you is sort of rare in the St. Bernard is pretty common. The way we do it is we have this request NF t function, which people have to pay to call and it makes
a request to a chain link node to get a random number. Once our contract gets that random number uses a chance array to figure out which one of the NF T's we're going to actually use for this for that minting. And we're going to set the token URI accordingly. And we're going to store the image data for this on IPFS, which we haven't done yet. So our deploy function for this is going to be really the interesting part of this contract. But because we just went over so much, if you want to take a
quick break quick breather, and then come back, I encourage you to do so we just learned a lot. And we wrote a lot of solidity code. So go take a quick breather, and I'll see you in a minute. So let's go ahead and get on in here, create a new deploy, go to ploy, random ipfs.js. And now this is going to look really similar once again, to the lottery contract that we've already done. And we can copy some boilerplate from our code over here, we're gonna need all this, we'll just copy that, close it
off with a little curly and boom, we've already got a boilerplate. Now, since we're working with chainlink, here, we are going to be working with mocks again. So we're gonna come back new file 00, deploy mocks dot j s. And if you want, you can just copy paste from the earlier section that we did with the with the raffle slash lottery. Since we're going to be doing the exact same thing here, I'm gonna go ahead and pause and you can copy paste from your previous projects. Or if you want, once aga
in, you can just come to the GitHub repo associated with this course, come over to the deploy. And go ahead and grab the deploy mocks right from here. If you grab from the GitHub repo, we also are going to be working with a mock v3 aggregator, but I'm not going to add that part in quite yet, because we don't need it quite yet. So go ahead and pause the video right now. Copy and paste the VRF coordinator mock or pause the video and try to write the mock code yourself. Okay, great. So once you've
done that, we're of course gonna need to concentrate ID network dot config dot chain ID, because we're gonna need to decide if we're actually on a development chain. So same as what we did before then we're gonna say if development chains that includes network dot name, then we're gonna say const VRF coordinator, B to mock goes await ethers dot get contract VRF. Core. The name for the to mock similar to the raffle we're gonna say let VRF coordinate Tor v two address, same, the VRF coordinator v
two address equals VRF. coordinator v two mach mock that address and then we're going to want to create a subscription exactly the same as what we did with our lottery. So we're gonna say const, TX equals weight VRF coordinate tore V to mock dot create subscription. And then we'll do const TX receipt equals weight, TX dot weight one. And we're gonna get the sub ID from this exactly the same way we did it in the lottery section. So we'll say that we need that sub ID by saying sub subscription ID
will say subscription ID equals TX receipt, dot events, zero. That args got somebody. So that's what we do if we're on a development chain, else said the VRF coordinate tore V to address equals network config of the chain ID dot VRF coordinate or B to that then the subscription ID equals network config. Chain ID dot subscription ID. Perfect. And then we'll just double check our helper hard hat config. So that Rigby has both the VRF coordinator v2. And we're also going to need a subscription ID.
So right now, I have our subscription ID from our past project from our lottery project. But we can go ahead to V or F dot chain link, we can go to V RF, that chain link can make sure we're on rink B here. Let's see our other subscriptions. And it looks like we have one here. So I'm going to copy this and paste it in for Rigby. Now again, we can go over to DockStar, chain link EVM chains, contract addresses for using reminisce to see more parameters in here, especially for Rigby and make sure th
ese are all correct. We have our subscription here, we'll add a new consumer very soon once we deploy this contract if we're actually going to use RankBrain. So we'll do a little log here with a bunch of hyphens. We'll now get args equals, we'll make our arguments here. And what do we need, we need the coordinator subscription, gasoline callback, address, dog, your dog token, your eyes and admin fee. So we're going to need VRF coordinator for the to address subscription ID. And we'll need the ne
twork config. Chain ID dot gas lane. We need the network config chain ID dot meant fee, then we'll leave that work config chain ID dot callback gas limit the right order? Yes it is. And then we need the dog token your eyes and the mint fee with the done here. Now what do we not have, we don't have this array of token your eyes. Now we can do this one of a couple of ways. If you go to the GitHub repo associated with this, go to deploy, we actually did the randomness for oh three in the get here,
there's one section where we just automatically say, okay, great token, you rise is just going to be these three. And then if we can actually even copy paste these CDs on IPFS, these are the better ones that actually do have the IPFS as the image. And we can see them like that. So we could just use the stuff that I've already deployed. And if you want to do that, you absolutely 100 percent Can, or what we could do is we get to actually learn to upload programmatically our own images to IPFS. Tha
t sounds a lot cooler. So let's go ahead and do that. Now what I want you to do, if you want to use your own images for this, feel free to do so. But if you want to just follow along with us, then we're going to go to the Hardhead NFT FCC repo. And we're going to grab these random NF T's from him. So all you can do is you can come to here. And we can go ahead, we can right click Save Image, Jas, we'll save it to our downloads, let's actually create a new folder, we'll call it images. And the ima
ges will create a new folder called random, then we can pull it just right into here, make the name random NFT. And this is just going to be plugged up png. So we can do that for all of our images. Now in our images tag, we have the pug ship in you and St Bernard. So we have these locally. But we want to upload these to IPFS. We want to upload them in a way that anybody can actually pin them and work with them. So before we do all this stuff, where we get the arguments to deploy this contract, w
e're going to need to get the IPFS hashes of our images. And there's a couple of ways we can do this. We do with our own IPFS node, which I've already shown you how to do that manually, we can also do that programmatically. Now, I'm not going to show you how to do this here. However, if you go through the IPFS documentation, you actually can learn how to do through the command line and even through some scripts. However, if we're the only node that's running this, again, it's kind of centralized
. So ideally, we'd want these images and these token your eyes and this and this token metadata on our own IPFS node and some other nodes. So the second way that we can look at this is using something like Hinata Hinata is a service that basically you just pay to help pin NF T for you. And this is going to be the one that we're going to be looking at here. Now the issue with binotto of course, is that we're just paying once single centralized entity to go ahead and pin our data, we're kind of tr
usting that they're actually going to pin it and that they're not going to go down. The final way that we could look into actually getting our data is was this thing called NF T dot storage. And if T dot storage uses the file coin network on the back end to pin our data now filecoin is a blockchain dedicated to pinning IPFS data and storing decentralized data. For us, the process is a little bit more complicated. But NFT dot storage makes it really, really easy. Now, we're not going to go over u
sing NFT dot storage in this video. However, if you want to look into NF T dot storage, for putting your data in the GitHub repo associated with this course, we do have a script that uploads your code to NFT to storage called in the utils folder, upload to NFT. Storage. And if you want to go and try it out, I recommend that you do so working with NF T dot storage will be one of the most persistent ways to keep our data up. But it's still good to upload your own data to your own IPFS node, which
we've learned how to do manually and at least get one other person also pinning your data. And then ideally, an entire decentralized network, pinning your data, which is what NFS storage helps you do. But for now, for us, we're just going to work with pinata to keep it nice and simple for this video. And then uploading uploading our metadata and our token, your eyes up to IPFS will give us this list of token your eyes for our three dogs. So up at the top here, we're going to do a little if we're
gonna say if process dot e NV dot upload to pinata equals true, yes, we're going to use the string true like that. Then we're going to upload to pinata. Above here we're going to say let's token your eyes. And we're gonna say token your eyes equals await, handle token your eyes. And we're going to create a function called handle token your eyes, which is going to upload our code to pinata down outside of this, we're going to create a new function called async. function. And we'll token your eye
s. And this is going to return an array of token your eyes for us to upload to our smart contract, we're gonna say token, your eyes equals this and then way at the bottom, we're gonna say return token your rise, right, so we're going to be returning this array here. Now we need to do two things, we need to both store the image in IPFS. And then we need to store the metadata in IPFS. So first, we're going to create a store images function. And this is where we're going to actually get to go to ou
r utils. And we're going to create a new folder in here, we're going to create a file called New File, Upload to pinata dot j s, we're going to add all of our code for actually uploading to pinata in here. Because again, pinata is this service that we're going to be using to just pin data for us and work with pinata, we can go ahead, try for free. And we can create our own application. And we're good to go. See the setup here looks really similar to an IPFS node, because that's essentially what
pinata is. It's just an IPFS node, run by somebody else. And we can say, Hey, can you please pin this data for us. So a manual way we could do this is we could just hit Upload Cid just like an IPFS node and put the hash of some IPFS file, and pinata would pin it for us, we could also upload a file or a folder just like an IPFS node. But for us, we're just going to leave this blank because we're going to want to do this programmatically, because we're engineers. So what we can do is we come over
to our profile, we'll open up API keys and documentation. And the documentation pretty much has everything that we need to get started. If you scroll down to the pinata Node js SDK, this is basically what we're going to be working with, they've already created an SDK for us that we can work with, we're gonna go ahead and install this pinata SDK. So they're using NPM, install dash to save, we're just gonna go ahead and use yarn, add dash dash dev at pinata dash SDK, and they have all these differ
ent endpoints, we can call to actually pin data, we're going to be doing pin file to IPFS, because we're going to upload our files and also pin JSON to IPFS. Since JSON is going to be the metadata, and file is going to be the actual image. And if you click on it, it'll even give you kind of the output of the SDK here. So back in our code, now that we've downloaded this, we can go ahead and start creating this. So we'll say const pinata SDK equals require at pinata slash SDK, and then we'll creat
e a function async function called store images, it'll take an images file path. So we're going to use this function will pass it our images, random n of t file paths, and we're going to have it store everything in that folder to help us work with paths. We're also going to Install this path package. So we're gonna do yarn, add dash dash dev path, like, so, we're just going to work with Fs as well not Fs extra. So now that that's up, we're gonna say const. Path equals require path. And in here,
we're gonna say const, full images, path, equals path dot resolve, images file path. So if we give that like dot slash images, slash random, you know, NF T or whatever, this will just give us give you the full output of the path. So we're getting the full images path, and then we'll say, we'll get those files by doing const files equals Fs. So we'll do we'll grab s will say const Fs equals require Fs just to read these files in here, that read DirSync. We're just going to read the entire directo
ry and get our files back to read DirSync full images path. And to actually test that this is working, what we're going to do is we're going to do module dot exports, equals store images. And then back in our deploy script here, we can just go ahead and comment out args. And we can do import const, store images equals require dot dot slash utils, slash upload to pinata. And in this script, we could just do a little, we just call this we could say await, or images, and then we'll pass pass our im
ages location, maybe way at the top, even outside of the function, we'll say const images location equals dot slash images slash random and ft. So we'll do a weight store images like that. And we should be able to run Hardhead deploy. Then if we add some tags to this deploy thing, module, dot exports, dot tags equals, we'll say all random IPFS. And then main, we do Hardhead deployed dash dash tags, random IPFS will also do mocks believe, and I need to create a test folder in here New Folder test
. And we need to add that VF coordinator v2 Mock in here. So again, I'm just copy pasting the VRF coordinator v2 Mock from our raffle project. Feel free to pause, copy, paste it over, or again, everything's available on the GitHub. So we'll try one more time. Tags, random IPFS, and mocks and boom, okay, mocks deployed and perfect pug dot png ship any png St. Bernard PNG. Great. So we're getting the files correctly here. Now let's create a little array for responses from the pinata server. So we'
ll say responses equals this. And we'll say for each file index in files for each one of these files in here, we're gonna say const readable stream for file equals Fs dot create read stream of the full images path slash files of file index. What does this line doing? Well, we're creating a read stream. Since this is an image file, it doesn't work exactly the same as just like push this data, right? We have to create a stream where we stream all the data inside of these images. Because these imag
es, even though they're just like a cute little image here, they're really this kind of this big file with all this bytes and all this data in here, and then we're going to send it by doing try, we'll say const response equals await. And this is where we're going to do pinata stuff. If we go back to the pinata docks, there's some stuff about keys in here. What we can do, if you go to your profile, go to API keys, we can create a new key, we'll say this is an admin key, why not? We'll give it all
the pinning access here. Maybe we'll give it this, maybe we'll just give it everything, whatever you want to do. And then we'll call this hard hat, Free Code Camp key, create key. Now we're going to want to grab these and drop these into a dot env. So the API key, go ahead and copy, come back over here. Open up our dot env. And we're gonna call it our pinata. And data API key equals that key. We're going to grab the API secret and say pinata API secret equals that key. We don't need this massiv
e token here for what we're going to do. But if you want it, you can absolutely have it. And then outside of our store images, we're going to say const pinata API key equals price says, do you need that pinata API key? And then can't pinata. API secret equals process dot E and V dot pinata API secret. And then we'll say const. pinata equals pin auta s. DK of pinata API key comma, pinata API. Secret in order to work with pinata, we need to pass it an API key and API secret so that pinata knows it
's us who's working with them. So once we initialize this pinata thing, we can now run pinata dot and then do some pinata stuff, right, we want to work with this pin file to IPFS, which takes this readable stream, which is why we created that readable string, so pinata that pin file to IPFS. Of readable stream or file. And then we're going to push this response on to our responses array. So we'll say responses dot push response. And then we're going to catch error, just in case there's some weir
d error here. And we'll just say console dot log error, and then we're going to return responses and files. So we're going to return all the responses from pushing all these files up, and then the files as well. Now, at this current point, we can go ahead and actually test this out ourselves. So we have this in here. If we go back to our deploy, at the top, we have this if process dot E and V dot upload to Niada equals true, do this stuff here, uploading to IPFS. And the final thing we need to d
o in here, of course, is going to be require dot env dot config, so that we can pull in our dot env file. Down here, we're just doing a weight store images. So if we run this as is, it should go ahead and store images. So let's run that same command, or that deploy random IPFS and the MOX to run this store images command. And if we come back to our pinata, after we run it, we'll be able to see the code uploaded here. If we run now, the script loaded IPFS it'll give us a little bit of a delay, be
cause it needs to upload these big picture files to IPFS. or more correctly. pinata, I'm gonna say uploading to nada. And we could even say, console dot log, working on file index, done Excel. And okay, great. It looks like it finished running. So if we come back to our project here, and we do a little refresh, we see our three files have been uploaded, and we see they each come with their own CID. Now, if you want, you can go ahead and copy the CID. And if you have your IPFS node, what you can
do, what we can do is actually we can hit import from IPFS. Paste it in here. And we can say exactly what this is, which is IPFS dot dot slash last as the St. Bernard called St. Bernard. Important. And now we'll have it pinned on our IPFS. I've got mine saved in a little puppies file. Now that we've got them uploaded, and pinata do actually recommend you pin your own on your own node as well. So cool. So we've got a way to get those images up onto IPFS. Awesome onto. Now that we've done that, we
're also going to need to store the token URI metadata. So let's go ahead and we'll delete that for now. What we can do back in here, is back up at the top again, we can say const meta data, template equals and we'll create a metadata template. This is going to have all the basics of what we need for our metadata for our token URI. So in here, we'll have a name, set, it's blank, we'll have a description, which will also set as blank will have the image which this is going to be replaced with the
image URI that IPFS URI we just created. And if you want to give your NFT like any types of stats, you can do some you can create this Attributes section like so. And if you give it like traits type, cuteness, comma, value 100. And this is how if you wanted to create like different cards or have different attack, defense, HP speed in different different stats for your NF T's, you would add them in this Attributes section. Typically, you'd want these attributes also stored on chain so your contr
acts can obviously programmatically interact with these attributes. But so now we have this metadata data template. This is what we're going to fill out for each one of our dogs. Yes, we're going to create a new function in here called async, store token URI metadata. And we'll pass in the meta data to the async function. And we'll pass in the metadata that we get from our script over here. So we have this little template here. And we're going to populate this template based off of what we get f
rom storing data in IPFS. So now we're going to write the rest of this handle token your eyes bit. And so we're going to want to do in our data and V, we're going to say, upload to pinata equals true, so that we can do everything and handle token your eyes. So upload to pinata, it's true, we'll scroll down, we'll start creating this. So the first thing we got to do, obviously, we're gonna want to get those responses and those files, right, because it's in the responses, pin file to IPFS is going
to return the hash of the file, right, and we need that hash, to add to our metadata. So we're going to do is down here, we're gonna say const, responses, which is going to be image upload, responses, comma files, equals await, store images, and then images, location. And so this response is, is going to be a list of these responses from pinata. And these responses are going to have the hash of each one of these uploaded files. So now we're going to loop through that list and upload each of the
metadata does. So we're going to say for each image upload response index, in image upload responses. For each one of these, we're going to create the metadata, we're going to create metadata and then upload the metadata. So we're gonna say let token URI, metadata equals dot dot, dot meta data template. So this is some fun JavaScript, syntactic sugar, which kind of means like, unpack. So basically, we're saying token URI metadata is going to be equal to this stuff. We're sticking all this stuff
into this token, your metadata variable, now we're gonna say token, your metadata. dot name is going to be equal to files of, of the index, dot replace, dot png, dot png with nothing. So files is going to be each one of those files, right? It's going to be dot png can be St Bernard dot PNG, and it's going to be Shiva dot png. And basically, all we're doing is we're saying, okay, cool, the name inside of our token, metadata is just going to be pug. So we're just going to drop the extension, basi
cally. So that's how we're gonna get the name token, your AI metadata dot description, is going to be equal to and adore a bowl. And then we're just going to get the name, token URI metadata dot name. So it's going to be an adorable pug pup and adorable St. Bernard pop or an adorable ship and you pup token URI metadata dot image, which is probably the most important one here, this is going to be, it's going to be that IPFS extension with the IPFS hash that we get from the response. So we can get
that by doing image, upload responses of the image upload response index dot i IPFS. Hash, so we can go to the pinata docs. And we can see pin file to IPFS returns in IPFS hash, the pin size and the timestamp, all we care about is the IPFS hash. And we're going to use that to give the our metadata image here. And then finally, I'll do a little console dot log uploading. And then we'll say, token, your eye metadata dot name, dot dot dot. And now we'll have to store the file or store store the JS
ON to pinata slash IPFS. And this is where in our upload to pinata bit here, we're going to add this function here. So we have store token URI metadata. And all we're gonna do in here, so we're gonna say try const response equals await, and nada, that pin JSON to IPFS of the metadata, right. And again, we have, we want pin JSON to IPFS, which is going to be really similar. So we need to pass the body, which is going to be the JSON. And we have some optional stuff here, but it's gonna give us the
same return the IPFS hash pin, size and timestamp. And then if this works, well, we're just going to do return response. Otherwise, we'll do catch error. And then we'll just do console dot log error, and then we'll just do return null and then we'll exports or token URI metadata. And then back in our deploy, we'll go ahead and import this store token URI metadata. And we'll scroll down. And they'll do const, metadata, upload response equals await, store token URI metadata where we pass the toke
n, Uri, metadata. And now finally, and now with all of these metadata is being uploaded are finally going to have the token you arise that we need. So we'll say, token, your eyes dot push, IPFS, slash slash, and then the metadata response here, metadata upload response dot IPFS. Hash. So we finally will have this array of IPFS hashes that points to the metadata, and each one of these metadata are pointing to the image. And then we'll do a little console dot log token. You arise, uploaded, they a
re and then we'll do another little console dot log token your eyes. Oh, all right. So let's go ahead and run this. And let's see if it works. In our pinata, we should see both the images and then also the metadata. If process dot E and V dot upload to pinata equals true, looks like it is true. And we should run this and handle token, your eyes will both upload our images with store images here and then upload our metadata. We'll only see it in here once because again, it's gonna have the exact
same Cid right, it's gonna have the same hash, so we won't get duplicates of the same file in pinata, or in our IPFS. So let's open this up. Let's run this one more time, or had deployed dash dash tags, random IPFS and mocks. Okay, it looks like we almost worked uploading to banana working on zero working on one working on two metadata template is not defined. Ha, because I spelt meta data template, meta data template, let's spell things correctly. Now let's try this again, it working on zero is
it working on two image upload response is not defined. I should spell correctly. There we go. Let's, let's do our caps correctly. Let's try this one more time. Okay, 012, uploading pug uploading Shiva in you uploading St. Bernard token your eyes upload it and they're here. Now if we grab this, and stick it into our browser, or your IPFS node, boom, we have them in here. And what we can do is we can grab this hash, we can jump into our IPFS desktop, go to files, we import from IPFS paste it in
here. And you know give it the name etc, that we have it on our own IPFS node as well. Awesome. Now if we go over to pinata give this a little refresh, we can see we have everything in here. So if I copy one of these, and I go to IPFS dot dot slash paste that in, we can see the metadata in here. And everything looks good. So this is absolutely massive that we've just done this because now we can store data both on our own IPFS node and at least one other nodes so that if our computer goes down o
r our server goes down, and there's at least somebody else who's done it. Now we finally have this list of token your eyes, we can finally go back to our arguments. And now we can do like this. And we can upload all of those token your eyes to our smart contract. And then we're going to need a mint fee as well for this. So if we go to our upper heart at config will create like a little mint fee in here, say mint fee is going to be whatever we want 12345678123456789 What we'll do is 0.01 eath. So
we'll even drop this down one, we'll do it for we'll do it for the Hard Hat Network. And then we'll also do it for Rinckey as well. We have the arguments here. Now we can finally deploy our contract. So we'll do const random IPFS. And if t equals await, deploy, if the contract is random IPFS NF T from Deployer. args is args. Log is true. And then wait confirmations is going to be network dot config dot block for confirm terminations, or one, and great they might do another little line here. We'
ll do the verification bit. I'm actually just going to copy that from our deploy. Our basic I'm just going to copy this it's going to be code is going to be exactly the same, except for we're going to verify random IPFS instead of and then actually we use args instead of arguments, then that is it. So we'll give this a quick deploy test, HH deploy or yarn Hardhead deploy. And it looks like we almost worked we almost got Everything's done. Network config is not defined, because we didn't import i
t. So let's go ahead and import network config from our helper Hardhead. Config. So import network config. We'll try this one more time chain ID is not defined, it's going to be chain ID, that chain Id try one more time. And awesome, it's at least working for our heart Hat Network. And then we can copy this array, and just paste it in here. Boom. And now we have this token your eyes. And now back in our dot env. Now we can set this to false. Since we have all those token neurons already, we just
run hard hit Deploy, we'll just use the token heroes that we already have uploaded. Yes, we have done it. Now I know you're excited to see this on something like open See, you're excited to see this right away. But let's save deploying all these to rink B for our last thing, because again, deploying to test nets is really slow. So let's just wait until our last bit and then we'll go ahead, and we'll deploy this to rank B. But before we write tests, something that I noticed when I was writing my
test is that we forgot to update the token counter. So in here, before we do, our safe, men will do s token counter plus equals s token counter, which is going to be esto. Encounter equals es token counter plus one. And that's a perfect example of why writing tests is so important. Before you write any tests, you're definitely going to need to fund that subscription, which we didn't do in here. So we need to do a wait VRF coordinate Tor V to mock dot fund, sub scription. subscription ID, comma
will do fund amount, and then just up at the top, actually, we can even pull this out too. Since that's not gonna change at all. We can do let token year I was like that looks like const fund amount equals cool. Or you could do you know, you could also do ethers dot parse. But as you know, before we can even deploy to rink beam, what should we do? Well, you got it right, we should absolutely 100 percent write some tests. So we're create a new file called random IPFS NF t dot test dot j s. And we
can write some tests here. Now, once again, there isn't anything new that you're going to learn in this test here, it's going to be very similar to the lottery tests that we've written before. So here's what I'm going to say, I'm going to highly recommend once again, that you try to write at least two or three of your own tests, but definitely write a test fulfill random words. But I'm going to encourage you to pause the video now, please pause the video and try to write some tests yourself str
uggling with some of these tests. And writing some of these tests is going to be what really gives you those coding muscles, if you will, that's going to give you the skills to keep writing these tests and be really fast and really efficient. When you're building these smart contracts. These tests are the tests that protect you from writing bad immutable code. So please pause the video, I'm going to copy paste from the GitHub repo. But please take this time to write some of your own tests here.
Alright, great. Did you write some tests? Hope you did. If you didn't write some tests, pause this video and go write some tests. I promise you doing these tests, writing exercises on your own will help you dramatically at this point, what have we done, we've done some some amazing stuff, we've deployed a basic NFT with pretty much nothing to it, then we've deployed a provably random NFT with random stats with random traits with different rarities, for each NF T's depending on when it was minted
, or who minted it. We've stored the data for this on IPFS. And we've learned how to programmatically upload our files to pinata, which is another pinning service for us. We learned a little bit about NFT debt storage, which is another way to pin data to IPFS. And then of course, we learned that if we wanted to, we could programmatically pin data to IPFS on our own node. But since a lot of us aren't gonna be running our own computers 24/7. We went ahead and said, Okay, well, we'll stick with pin
ata for our default here. Now that we've done all that, boom, got another little checkmark here. Now I got something to say we don't need to host our data on IPFS can actually host our data, our metadata directly on chain if we want to. However, there are some pros and cons to IT pros of hosting on IPFS, or that's going to be cheap. And the cons are that someone needs to pin our data, right? There's at least one person always needs to have her data pinned, right? It's decentralized, but you at l
east need somebody to pin your data, right? And using something like file coin is a way to incentivize people to pin that data. But if you're not using File coin, it's not necessarily guaranteed the pros of doing our SVG on chain NFT the data A is on chain. And you never have to worry about somebody actually pinning the data. The cons are that this is much more expensive. These little images, right here are actually surprisingly large and storing them on chain can actually get pretty expensive.
So we're going to use some different images, so much smaller images, much cheaper images to work with here. And if you want to see another version of this, I have another video, how to make NFT art with on chain metadata, it goes through pretty much what we're about to go through here as well if you want a second reference, and there's a link to this in the GitHub repo associated with this course. So instead of these PNGs that we're using, we're going to use something called SVG s. Now, an SVG s
tands for Scalable Vector Graphics. And these are much much more minimalistic files that we can go ahead and upload to to the blockchain. So that's why we're going to use them because since there's so much more minimalistic, they're a lot cheaper to upload. Because remember, the more data that you upload to the blockchain, the more expensive it is. Now in this video, I make randomize SVG data on chain. And here's kind of an example of what one looks like. It's just a whole bunch of random lines.
Not super thrilling, but random and kind of cool. And it's 100 percent. On chain, these SVG is actually work right in HTML. So if you want to use these for your websites, you can as well now there's a link to this tutorial in the GitHub repo associated with this course, where we can go ahead and try it yourself. And we can actually play with making an SVG, right, so they have all these different commands in this web through schools.com/graphics/svg intro dot ASP, you can see some of the differe
nt commands, right, you can make a rectangle you can make a circle path is a big one where you can say exactly what the path or the line you want to draw is going to look like. There's a whole bunch of stuff you can make in this SVG. And the cool thing is, no matter how big you make an SVG, the quality is always going to be exactly the same, because SVG just explains exactly how to draw it no matter how big or how little, the image is going to be. So if you want to learn more about SVG is you wa
nt to play with SVG is you know, you can come in here and try it yourself. So with that being said, that's what we're going to store on chain. So that's how we're going to store this SVG stuff on chain. But we're gonna go one step further, we're gonna make this dynamic, we're gonna make this actually change based off of some data on chain. If you go to the GitHub repo associated with this lesson, and you go to the images, and you go to dynamic NFT, you'll see two images, see happy dot SVG, which
looks like this. And you'll see frown dot SVG, which looks like this. So we're going to make this NFT dynamic in the sense that we're going to say, if the price of eath is above some number, then we're going to have it be a happy face. And then if it's below that, we're going to make it a frowny face. So our NFT is going to change based off of some real world parameters. And this is obviously really powerful and really cool, because we can have an NFT that changes based off stats, we can have a
n NF t that changes based off of really whatever, and we're going to store all the data 100 percent on chain, it's going to be a little bit more expensive. So that's what we're going to be building here. Let's go ahead, let's jump into it. And let's do the final contract for our ultimate NFT section. So we're going to create a new contract in here, new contract, and this is going to be our dynamic, SVG and F T dot soul. And it's going to look real similar to what we've been doing. slash slash dy
namic. SVG and ft dot saw, slash lat spdx, license identifier, and my team pragma. solidity, Eric zero, point 8.7. Contract, dynamic SVG, NF t. Now let's talk about what the architecture of this is going to look like. It's gonna look like pretty normal NF T, with a couple of caveats. We're gonna give it a min function to mint, these NF T's are also going to store our SVG information somewhere. And then we're going to need to have some logic to say show x image or show y image, right. And as we k
now, that's really just going to be switching the token URI to say show X or show y. So let's go into how we'd actually do this. So first, we know this is going to be in ERC. 721. So we can go ahead and import that from open Zeppelin. So we're going to say import at open Zeppelin slash contracts, slash token slash ERC. 721 slash ERC. 721 That's all. Now we're not going to call that set token URI function that we call before so we can just use the raw ERC 721 instead of an extension. So we'll say
our contract is ERC 721 and Now that we're making it an ERC 721. We can say construct dorm like this, then we'll call the constructor of the ERC. 721, which we're going to call this dynamic SVG, and f t DSN, dynamic SVG and s, t and f t, like so then we're also going to need a mint function. So let's just create that right now say function, mint and f t or request NFT. And we'll be a little bit looser here, we'll say the user doesn't need to pay any money for this. So this will just be a public
function. And we're just going to mint them and NFT. Same thing, we're just going to call Safe mint message dot sender. And of course, we need that token count term. So let's go ahead and in our top will do you in 256, private s underscore token counter, we'll do token counter here. And then after we meant we'll do tag counter plus, there's gonna be equals token counter plus one. And then that's pretty much it, we have a way to meant we've done some of the basics here. We'll even we'll be expli
cit will say s token counter equals zero to initialize it. But now what is this token going to look like? We want these to look like SVGs. And we want it to be based off the price of some asset in our constructor, all right, create a string memory. We'll call it low SVG and a string memory, high SVG. And in our code will save this low SVG in this highest V G. So these will be the images, these will be like the frowny face and the smiley face that will just import as input parameters here. So as
we know, we can make these immutable since these are probably not going to change. We can say String, private, I underscore low image URI. And in string private, I underscore high image URI. But if we just pass the SVG data, right, the SVG data is going to look like what in this GitHub, I can go to display the source blob here and I can see exactly what this code looks like this code here is definitely not an image URI. What we need is the image URI to look something like this, right? Now, the w
ay that we're going to pass it in is like with this SVG code, right? Because we want to just pass it the SVG code, and then have the contract handle everything else. So how do we actually do this? Well, what we can do is we can create a function called SVG to image URI. And on chain, we can convert these SVGs from SVGs. To image arise. So instead of having IPFS, as their start, we're gonna use something called base 64 encoding, you can actually encode any SVG to a base 64 image URL. That's right
. It'll look something like this base. 64 is group a binary to text encoding schemes that represents binary data. Or in our case, our SVG data. Base. 64 is particularly prevalent in the world wide web, or one of its uses is the ability to embed image files or other binary assets inside textual assets, such as HTML, and CSS, what we can do, can actually convert all this SVG stuff to a URL or an image URI would be great, right? That's exactly what we want, we want to be able to convert this to a U
RL or an image URI. Now, if you take one of these images, or these SVG images, like the happy to have SVG, what we can actually do in this happy dot SVG is we can actually copy the image address, which is going to be the URL of this address. And if we paste it back in, we'll see justice file here. And in this site, we can actually do data type, remote URL, paste it in here. And we can say encode SVG to base 64. And down here, we'll get this weird job role of numbers and letters and stuff. This b
ase 64 encoding represents the SVG that we just got and what we can do in our browser, we can type data, colon, image, slash SVG, plus XML, semicolon, base, 64, comma, and then paste that massive thing in here and Enter. And wouldn't you know it, we get exactly that image back up. So that huge, massive thing here is the base 64 encoding of this image. So with this basic C four encoded image, we can use this on chain as the image you arrive for our images. And then for our metadata. We'll just ba
ke that directly into our token URI. You'll see what I mean in a second. So we have a way where we can actually directly put our SVG code right into our smart contracts. Let's figure out how to do that. So we have function, SVG to image URI, so we know we're going to want to probably do that same base 64 encoding on chain. We're gonna 100 percent do this off chain if you want to save some gas but it's kind of fun for To show how to do this all on chain, so we'll make this a public pure function.
And we'll have it returns a string memory. So we're going to give this function an SVG, which we're going to pass in from our constructor. And we're going to return a string, which is going to be that base 64 encoded URL that we just saw, while up at our top will do string, private constant, base S feed, base 64, encoded SVG prefix equals that right there. And we'll use this to generate our SVG now, well, we can do. And then we're going to do string memory SVG, we're going to encode this SVG in
basically for ourself by adding the base 64 encoding on chain. Now, we don't really want to have to rewrite that ourselves. So luckily for us, somebody has already done this. And we can see the GitHub repo associated with this, this was created by one of the LoopRing devs really awesome project, if you want to check that out as well. And we're going to borrow this code for our SVG on chain. So what we can do is we can add this in here, add their GitHub code, where they have basically everything
that we need in here to encode and decode basics before, we can do yarn, add dash dash Dev, base 64 Dash soul, this is going to add their code as a dependency. And once we've added it, we can go ahead and import it with import, base 64, dash soul slash, base 64 dot Sol. And this contract comes with an encoder. So then we can just do string memory, SVG base, 64, encoded, equals base 64 dot ENCODE. And here's where it gets a little bit weird. We'll do bytes string, abi dot ENCODE, act, SVG, and t
hen we'll return string API dot encode packed, base 64, encoded SVG prefix, comma SVG base 64 encoded, and just this function, this SVG to image URI will take in any SVG and spit us back out a URL or URI that looks exactly like this. Now, I kind of sped through some stuff in here. There's a whole bunch of new stuff like ABI dot encode packed that we did twice, what is this ABI dot encode packed doing? Well, let's learn about that. So from a really, really high level, this is basically how you co
ncatenate strings. Right, this is how you combine strings together. And we're going to jump over remix to actually explore this ABI dot encode pact and this ABI encoding stuff a little bit more. 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 opcodes. And all this crazy, low level, 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. That's 100 percent. 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 appro
ach this section, when you approach this sub lesson on EVM, opcodes, and coding and calling, just know that if you don't 100 percent understand it the first time that is okay, if you want to watch this section a couple of 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 dot soul. And remember, all the code that we're going to be going with in here is going to be
in this sub 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 dot soul. And then in a little bit, we're going to work on this call anything that soul so we're in this encoding dot soul. And let's just make our basic code here. So we'll say spdx, license identifier, MIT pragma, solidity, carrot, zero, point 8.7, like that, do contract encoding, boom, compile, or Command S or ctrl S great things are looking good. Now remember, t
he whole purpose for this is to first understand what's going on here, and more about this API dot encode packed stuff. So let's first just write a function that should owes us wrapping API dot encode packed with some strings and wrapping it around a string is going to return a string. So we could do function, bind 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, API dot enco
de packed. I'm I'm comma, space in here, I miss you, like so. We need another parenthesis here. Okay, great. Now let's go ahead and deploy this, we'll start a JavaScript VM will deploy encoding coding.so. 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 misuse together into its bytes form, because API dot encode packed returns a bytes object, and we are typecasting it by wrapping it in thi
s string thing to be a string. And solidity says, okay, yeah, bytes to string, that's fine, that totally works. And this API dot encode packed are 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 gonna 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 dot
encode pact, we see ABI dot encode pact right here, we scroll down, we'll see some more that we're familiar with as well. Like, for example, message dot sender, sender of the message, message dot value. 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.8, point, well, plus, you can actually do string dot concat, you know, string a, comma string B, if you want to, instead of doing this API to encode p
acked, but I still wanted to show you the API dot 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 pact, 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 file
s, we got a dot ABI file, and a dot bin or dot binary. Back in our ether symbol storage, when we ran yarn, compile. The two main files that we got, were this symbol storage that abi, which was this, you know, this ABI thing that we've become familiar with. And then the simple storage dot bin, which is the binary, which has a whole bunch of just numbers and letters and stuff we didn't understand. And you can see that in remix to, like if we were to compile this, you get a 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 bytecode 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 low level 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 nonce, it has a gas price guess limit to value data, we kind of skipped over the VRS a little bit, because that's kind of that mathy component of the transaction signature. But again, back in our ethos project, we did this as well, right in our deploy script, ended up sending a transaction ourselves, using just ethers. We
passed a nonce, a gas price, gas limit to value data was this massive thing to declare a contract, and then also the chain ID. We didn't work with the VAR s, because ethers does that for us. But there's also this VAR s component that 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 contra
ct bytecode. Right. So when we compile it, 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 the 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 byte code right what we send in our trend In this action is this data thing, we send this this weird bunch of garbled 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 dot soul and the GitHub repo. There's 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 cerium 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 Aetherium 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 w
e 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, I 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 next XYZ and all this random stuff. So this bytecode represents the low level computer instructions to make our contract happen. And all these numbers and letters represent kind of an alphab
et, 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 opcodes. If you go to create a new tab, if you go to EVM dot 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 opcode. And then you can see name, so this opcode section is saying, Hey, if you see a 00 in this bytecode, th
at 00 represents this opcode stop, which does what which halts execution, if you see a 01 you're gonna 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 all the way down to f f 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. Oh six, one says, Okay, the first thing w
e want you to do is the O six, one opcode. And if we go to EVM, opcodes, we look for six one, it's saying push to place to buy item on the stack. That's exactly how it's reading this any language that can compile down to this opcode stuff down to this specific set of Aetherium opcodes, or EVM. opcodes, is what's known as the EVM, the Etherium virtual machine. So being able to read these op codes is sometimes abstractly called the EVM, the Etherium virtual machine, the EVM basically represents al
l the instructions, a computer must be able to read for it to interact with Aetherium, or Aetherium, like applications. And this is why so many blockchains all work with solidity because solidity compiles down to this bytecode here, and polygon, avalanche arbitrage Aetherium, they all compiled 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 dot
encode packed, all that does is concatenate strings, abi encode pack can do actually way more. And if we look at these global variables, API dot encode 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 wi
ll be a public pure function, since we're not going to read any state, and we'll say returns a bytes memory. We're going to have this function return a bytes object, we're going to have it returned the what this number is going to look like but in binary, so we'll say bytes, memory number equals ABI dot encode one, and then return number. So we're going to encode number down to it's a bi or it's binary format. So I know a lot of times when we say oh, what's the ABI what's the ABI right? Previous
ly, we say, Oh, the ABI is, is this thing, right? 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 or numbers down to it's basically it's binary, this ABI dot 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 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, Watch 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 under
stand 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 key here as well. It'll return a bytes memory, because we want to give it that binary stuff or that bites stuff. And we'll say bytes memory, some string equals ABI dot encode some string, and then return some string. Now let's compile that delete our old contract, deploy that code string, we get this big, big, big object here. And this i
s 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 ABI dot encode tact, 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 packed mode. And it does the same encoding
with some stipulations type shorter than 32 bytes are concatenated directly without padding, or sign extension, dynamic types are encoded in place. And without the length array elements are padded, but still encoded in place, you can kind of think of ENCODE packed as sort of like a compressor, right? It's the ENCODE function. But it compresses stuff, if we wanted to encode some string but want to save space. And we didn't need the perfect low level binary of it. We could do function and code str
ing packed, make this a public pure, and have it return a bytes memory. We could say, bytes memory, some string equals ABI dot encode packed once again, some string. So we're doing a code pack instead of a code. 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 encoded string is gonna give us and we have encoded string packed, which returns us this muc
h, much smaller bytes object. So you see the size difference, if we're trying to save gas, in code, string packed is going to be a way for us to save a lot more gas. Now, abi dot encode pact is actually really similar to something that we've done before, which is typecasting, if we didn't function and code string, bytes, public pure returns, bytes, memory, bytes, memories, some string equals bytes, some string, turn some string, these two are going to look nearly identical, right? So if we compi
le, we'll delete our old contract, deploy this code string bytes, which gives us this and encode string pack using the ABI to encode pack, they give us the exact same output, whereas encode strings to give 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 I've left a link inside of the code here, if you want to learn more, which is exactly what we're doing in ou
r NFT. Right, we're doing ABR dot encode 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 typecasting 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 s
ection, but some other viewers might be going okay, Patrick, this is seems pretty cool. But I'm sure this encode pacts in this encode function aren't just here to concatenate strings, they probably have some other function, what do they actually do? Well, if that's what you're asking, I'm glad you asked. And I'm glad you're curious, because 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 can say, function,
decode string, public, your returns string memory, string memory, some string equals ABI dot decode. This is going to take a couple parameters. So if you look in the docs here, abi dot 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 Adding, let's give it as
input this encode 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 it's really big. So we're gonna 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's
like, okay, cool. I can decode this, but like, what, what do you want me to do with it, and we say, Oh, this is a string, so decode it into a string. And then we can do return some string. Now, once again, we deploy that old Cotters, we delete the last contract, we deploy this new one. So in code string, and code string, whereas in code, string, and code string returns this massive thing, as a human being, we're like, God, 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 encode and multi and 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 of things, we'll say bytes, memory, some string equals ABI dot encode some string, comma, it's bigger. So we're going to encode two strings here, we're gonna encode some string,
and it's bigger. So we have two strings, we're going to encode and we'll return some string, even though it's you know, bytes. 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, some string equals API decode, we'll say, string memory, some string, comma string memory, some other string. So we're gonna get to returns equals Avi dot d
ecode. 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 are some string, there we go. Now 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 in code, which gives us this even bigger bites object, right? Because this is two strings encoded. And now if we hit multi decode, tak
e a second, what do you think it's going to put out output? Let's go ahead and hit it. Now it's gonna give us two strings, right, it's gonna give you 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 pack thing, right? We could do function, multi encode packed, public pure returns,
bytes memory, and then bytes memory, some string equals ABI dot encode packed some string, comma, it's bigger than return some string, 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 gonna say this doesn't work. Try to do function, multi decode, packed, public pure returns, string memory, string memory, some string equals Avi dot decode m
ulti encode packed in a string and have exactly what we did above to, if we do return some string, what do you think's gonna happen? Let's, let's try to delete the old contract, deploy a new one. We'll do multi decode, packed, multi encode multi decode, packed, and we actually just get an error. solidity basically goes, 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 more to string cast packed like this a public pure returns s
tring memory, string, memory, some string equals string, multi and code packed, return some string. This one will work right because again, this pact encoding is kind of similar to just type casting. So we'll compile will redeploy multi string cast pact, we get some Trying, 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 in ABI dot encode and decoding, and we know that okay, this is what the computer, this is, wh
at Aetherium. This is what the EVM, or any EVM compatible chain is looking for. It's looking for this bytecode. 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 can actually populate this data value of our transactions ourselves with the binary
that 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 to 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 lo
ok 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 EVM 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 newfound data and coding
stuff, what we can actually do is send the data field of a transaction ourself, in a transaction call back in this ether throwback where this data thing was the contract creation code. Well, instead, we could populate this data thing with our function call code, the exact function that we want to call in the binary in hex addition. Now you might be thinking, Oh, well, why would I do that, I can always just use the interface, the ABI, 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, send a function. Now, when I said, you always need the API. Originally, we we
re kind of talking about this thing, this big, this big thing, which is cool, which is the API. But this is like the human readable API, you can also do it with the non 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, h
ow do we populate the data field? What do we populate the data field with to make one of these function calls? And then how do we send these transactions slowly, 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, because this is, we use a similar setup in our fulfill random words for our lottery, right, we sent money doing this recent winner dot call, right? Recently,
it was the address of the recent winner, and we did not call. And then we have this weird stuff in this brackets here, and then nothing in the parentheses. So we did actually, essentially, we use 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, write static calls gonna be like, okay, don't change the state of the bl
ockchain with this one, just give us the return value. So this is kind of similar to like a view or a pure function at low level, there's also a Send word but like, basically forget about it. We're just gonna be working with call, instead of call. And, you know, later on, we'll learn about another one called delegate call. But don't worry about that for now. Recent winter duck call like this, in these little squiggly brackets, we said, Okay, we updated the value directly of our transaction in so
lidity. So which again, if we have these transaction fields, and we just directly updated value in these little brackets, right, we can also directly update gas limited 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 empt
y, which is why, again, remember how we hit this button before, right and we had called data be empty, that's essentially running this command with called data be empty with this section be empty, and then just updating the value that we set with the transaction. And so it's this section that we can use to populate data to actually call specific functions. We're going to put a whole bunch more comments here. So when 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 them if we want to call a function or send any data, we can do this in the parentheses. And I think I spelt 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. Well, we learned from really high
level, if we want to combine strings, we can do ABI dot encode packed and then typecast that to a string. And in newer versions of solidity you can do, you can do string dot concat, you know, Hi, Mom, come on, miss you. In newer versions of solidity. This works as well, but not in older versions of solidity. Then we learned a lot about some low level stuff we learned, okay, when we compile our contracts, we get an ABI file, and this weird binary thing that numbers and letters stuff that gets wh
en 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 in with what parameters and this is what we're gonna go over next. Now, we learned that we can actually encode stuff into this binary into this low level code. And any program any process that can read this low level stuff and execute accordingly, read this EVM stuff, rea
d the specific binary that Aetherium 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. Alright, so now's 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. Alright, welcome back. Now that we've learned about this encoding stuff, let's learn how we can populate this parenthesis this data 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 gonna call it call anything, that's all 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 parameters that we want to add, right, because 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 Aetherium based smart contracts and 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 funct
ion signature is just going to be a string, which defines the function name of 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 un 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 byt
ecode, in the binary code, this function selector is how slitting 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 zero point
8.7 Say contract, call anything. And we'll give this to stored variables, give the to stored variables and address public s, underscore some amount, or some address, and then you in 256, public s underscore mount. And then we'll create a function called transfer function transfer. Now normally in here, we would actually do like transfer for like an ERC 20 transfer, but we're just going to do address some address, and then you add 256 amount, amount here, we'll make this a public function. And t
hen all we'll do is we'll set S, some address equals some address, and then s amount equals amount. So here's gonna 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 some address amount, that gets boiled down to the function selector, and the function signature. And of course, in our bytecode, 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 gonna say get selector one, because I'm gonna show you a few ways to get the function selector, we'll make this a public pure. And we'll have this return a bytes for selector, we could say select or equals bytes for, and then we hash with a check to 56 of the bytes of that signature, which is transfer. And it takes an address and a UNT 56. Right? If we compile this, and then we run it,
let's get rid of our old contract, deploy, make sure we're on call anything, if you have the other one up. In here, now we have a couple of things, we hit Get selector one, we get this Oh X, a 905, 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, 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 un 256 as input param
eter. So we see address you into 56. Our function knows to execute this data here. Great. And then of course, sml, 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 or an address. And we'll do 777 for an amount. If we hit transfer, we have the log up, right, we'll get a little checkmark 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'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 gonna do is we're gonna say fun
ction, 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, we're gonna say address, some address. And if it is x, amount, public pure returns, bytes memory. And then we can return and use one of those ABI and codings from the cheat sheet. Now, so far, we've just been doing API and code for a lot of our encoding. So it since we have t
he function selector, we can actually do ABI dot encode with selector. This ABI encodes the given arguments starting from the second and prepends, the given four byte selector. When we do in Cobra selector, we're just sticking our selector onto the data that we're going to give it. So we're going to do return API dot encode with select door. 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 gonna
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 up, we now got a new function called Get Data to call and transfer, we'll just pass you know, we'll just pass this contract 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 Mt. 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'll say address some address, you in 256 amount, we'll make this a public function. And we'll have a returns a bytes four and a bool. 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 dot call, right, we're going to do some address. And then for us, we're going to address this dot call. And then we're saying this contracts address which we could put any address here address
dot 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.com. And we could just do get data to call transfer address amounts, right, we could do it like this. Or we could do it kind of the wrong way. We could do ABI dot and code with select dorm, get selector one, comma, some address, comma amount. And actually, there's no semicolon there, sorry. So those are going to be the same. And this dot call thing, r
ight, it's going to return exactly what we saw before, it's going to return a bool success. So whether or not the transaction was successful, and then bytes, memory, returned 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 return bytes, four bytes for a return datum, and then success. So we're just going to return the first four bytes of whatever data we get returned. And then we're go
ing 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 dot 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 righ
t now sml, and estimators 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 gonna get this transaction response here. But if we scroll down, we'll ever see the decoded output, which is a bytes for of just a bunch of zeros, right? Because our transfer doesn't actually return anything. So it's just gonna be a whole bunch of zeros, and then our Boolean true, which means it was su
ccessful. 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 ABI dot encode
with selector bytes for CAC 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 encoded with selector, we can do encode with SIG netshare, the function signature, and then we'll copy our function signature from up here, paste that in here. Compile, we ran into a compilation error, up, these are the same call transfer function directly SIG, ca
lled that compile, leader, 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, let me check these we can see that that does the exact same thing. So this is API dot encode with signature. This is abi dot encode selector. Encode with signature just turns us into the selector for us. That's all up here, we just, we encoded this selector ourselves. Now, t
here are a whole bunch of different ways to get the selectors. And we're not going to code these out ourselves. I'm just gonna 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 comments to explain what they're doing. Well, we are going to show you though, it's actually how to 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 byte information to call the transfer function on a different contract. And we're gonna show you how that can work. This is just another contract
that I've 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, it's going 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 we'll give it a new number of 123. Right, and we'll click call transfer function. And then when we go back up here, we see that this has indeed been updated. Now doing this call stuff is considered low level. 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 level calls some security auditor checkers might say, hey, like this books been out a little bit, you doing this low level stuff. But with that being said, You have just learned a ton about lower level solidity. This is some really advanced stuff. An
d 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 openzeppelin, it really breaks down exactly wha
t's going on behind the scenes of a contract. If you want to learn more about opcodes, about low level 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. With that being said, here we are back in our NFT. And now we know all about this ABI dot encoding stuff, right and what it does, and we know that ABI dot encode packed, the way we
're using here is just a way to concatenate strings. And we're not using ABI dot encode for really any of its crazy superpowers, but we might in the later section of this course. In other case, so we do use this base 64 dot encode thing that we've imported, right, we imported this base 64 dot encode so that we can encode our SVG that we pass it in to its base 64 encoding. I'm going to copy paste an example here, you don't have to do this. But like, for example, we'll pass it in like SVG width eq
uals blah, blah, blah, all this SVG stuff, kind of similar to what I was showing you before, we pass that in as an input parameter here, and output it, we're gonna get the base 64 encoding of it, we're gonna get this massive kind of string here. We will test this later to make sure that this works. Normally, if I added a function in like this right now, I probably would test it right away. For now we can just leave it in here. That's going to be great for getting this image here. But we don't wa
nt just an image, right? We were going to need that metadata. We need this to be a JSON object, not just an image URL like this, we need stick this image, this base 64 encoded image into this image field of our JSON. So how do we actually do this? Well, what we can do is we know that our ERC 721 code comes with a token URI, and it's that token URI that points to this, which tells us what our code is going to look like. So what we can do is we can actually base 64 encode our JSON as well, to turn
into a JSON token URI. So we basically four encoded this image to get this, we're going to stick this URL into our JSON. And then we're going to base 64 encode our JSON, and that's going to be the URI that our token uses. So we have our function, token URI, right. And this takes a un 256 token ID, we'll say it's going to be a public view, public view override, and it returns a string memory. So we're going to override the token URI function of the ERC 721 to whatever we want it to be. And here
we're going to encode some JSON text that we give our contract into a base 64 based JSON token URI just to get started we'll do a require underscore exists. Token ID, and then I'm just gonna say your I query for non existent token. And yeah, this price should be an if not exists, Revert with an error. However, we're just going to go like this. And this exists function comes in my ear C 721. So we're going to do same thing here. So we're gonna say require this token, a D exists. And again, we can
100 percent. And probably should make this an IF EXISTS token, ID, you know, now what we want to do is we want to figure out how to make this token URI return a base 64 encoded version of this JSON. So first, we know how to how to concatenate a string, right, so that's gonna be the first thing that we're going to do. So we'll do API dot and code packed. And we're going to encode ourselves the JSON on chain, we're going to use single quotes here, because inside of this API and code packed, we're
going to use double quotes in here is where we're going to add our JSON. So we'll give a name, right, so the first piece of metadata needs to be a name. So we'll give it a name. And we'll put a comma here. And we'll say the name of this NF T is going to be the name we get from, we have a name function, which returns the name. So we're gonna say the name is going to be the name. And we're gonna just concatenate all this stuff, name right there. We're gonna continue on with the JSON. So we put a
little quote here, and a little quote here. So we encapsulate this name in quotes, right? Because remember, we're, we're concatenating, this big string that we're making here, we'll do a comma, we'll say, description, we'll do another quote. And this time, we're just going to put the description ourselves, and we'll say, and NFT, that changes, based on the chain link feed, we'll put an end quote here and a comma, and we'll put a comma outside the quote, down here, we'll say, attributes. We'll ju
st say, trait type, it's going to be coolness. Comma, value, me 100. Boom, to a comma to image. We'll put a comma out here. And this is where we're going to put our image URI, image URI, which we're going to have to get from somewhere. So for now, I'm just gonna say, string. Memory image URI equals i, right, which clearly isn't an image arrived. But just to make this format and stuff, we'll we'll put this there. This is where we're going to put that image URI that we get from SVG to image URI. A
nd then that's it. I mean, close off our JSON, though. So doing ABI dot encode pack is going to concatenate this all together. So this is basically going to be a string that looks like this. Great. But how do we turn this into a base 64 encoded token you arrive so that other people can read it is we're going to typecast this whole thing to bytes. And then now that this whole thing is in bytes, we can do exactly what we did with the SVG above is now we can base 64 encoded. So we'll do base 64, do
t ENCODE. And then we'll just put another pair of parentheses around this save and auto formatted. And this here is going to give us this second line, right, it's going to give us all of this bit, but it's not going to give us this first bit, right. So we just need to append to this first bit now. And we should be good to go. For basics before data image SVG plus XML basics, the form, this is the prefix for images for SVG images, right? We use that above because that's the prefix for SVG images.
The prefix for base 64. Jason is going to be it's going to be data application JSON base 64. So we're going to do it like this instead. Now the ERC 721 has something called a base URI that we're going to override and that we're going to use. So we're gonna say function underscore base URI. This will be internal pure. And we're going to override the one that ERC 721 has. And this is going to returns a string memory. And we're just going to return this bit right here. And now we can use this base
URI. to append, right, we're going to append this first part to our base 64 encoded JSON. So in order to append them, once again, we'll do ABI dot ENCODE, packed. And then we'll put this down here. And we'll say, we're going to, we're going to concatenate base URI to this massive thing that we just created. And then we save and we ought to format the now this is obviously a bytes object, and we want it to be a string. So then all we got to do is typecast it as a string, but another prints see d
own here, and then we can actually just return this, but basically what we're doing is we're creating a JSON string, we encode it in bytes, that way we can encode it in base 64. Once we have encoded in base 64, which is going to look like this second string, it's gonna look like here out, we then just append this initial part. But for JSON objects, it's data application JSON. We we append that we do API dot encode packed, and then cast it to string and then boom, we now have a token URI. That'll
look something like this. And then all we have to do is update our image URI with what we get from our function appear, and then we'll be good to go. So let's finish this out. Let's do this. So in our constructor, we're passing a low SVG and a high SVG. And what are these low SVG is in these high SVG as well, basically saying, when the price of this asset is too low, show a frown. And when the price of the asset is high, show a smiley face. So we're gonna give it this frown, SVG, and this happy
SVG as input parameters, low CG and high SVG, we probably want to save those. But we don't necessarily want to save them in like their SVG format. So we just want to store the image URI, right, we will just want to store this string up here instead of the actual SVG. So right in our constructor, we can do I underscore low image URI equals, and we have this SVG to image your eye function, where we can pass the low SVG. And then we can do the same thing for the high image URI. So now, SVG image U
RI is going to return something that looks like this. And we're going to store just this string this image URI on chain. Now that we have the two of those, we can use that down below. In our token, Uri function, when somebody calls token, your I have token ID zero, we're going to stick into our JSON, either the low image or I or the high image arrive. And we're actually going to base that off of the channeling price feed. So how do we do that? Well, we've already worked with channeling price fee
ds before so let's go ahead and add it. So yarn add dash dash dev at chain link slash contracts. Once that's done at the top, we can do import at chain link slash contracts, slash SRC slash V 0.8, slash interfaces, slash ag reg gate, Tor V three interface, that soul like so. And then down here, let's comment this out. For now, we're going to want to call a price feed to figure out what the price is and then show the high image or the low image based off that. So in order to get a price feed in o
ur constructor, let's just add another price feed address, street address. And then we'll make another variable. We'll do aggregate Tor v3 interface. Internal, immutable, I underscore price feed. And we'll say in our constructor, I price feed equals aggregate Tor v3 interface at price feed, address. And then what we can do down here, the old bunch of commas in here into 256 Price comma, comma comma equals i price feed that latest round data. And what we can do is we can say if price is greater t
han or equal to some value, then show one image dry otherwise, show another one. So we can say String memory, image URI equals s underscore low image URI. And then if the price is higher than some value, well greater than the image URI we're going to use is going to be there's gonna be AI is going to equal the high image URI. And then we have image right down here. So all we got to do is figure out the price. So we can make, and in our mind, we'll let the mentors choose the value that they want
to use. So we can say, into 256, I value and we'll assign each NFT, their own high value. So we'll need to create like a little mapping up top, we'll say, mapping, you went to 56. Two, you went to 56. Let's just make this public for the heck of it public s underscore token ID to high value. And we'll say that when they meant an NF T will do s token ID to high value, s underscore token counter. We'll set that equal to high value. So when they meant they choose the high value that they want. And t
hen down here we'll say if the price is greater than or equal to the high value of the token ID, then we'll use the high one. Otherwise, we'll just use the low one. Oops, and this needs to be you into videos x two into 256. Excuse me, since we want to be able to compare them pretty equally. And boom, our contract looks really good. Now the only thing we'd want to add in here is probably an event. So we probably want to emit an event in time we met to one of these NF T's. So we might do event cre
ated NF T, will say you went to 56 indexed token ID comma int 256. I value like so. And then when we met this NFT, will do emit create n t, s underscore token counter, comma, I value. And then it's best practice to to have to update our token counter before we actually do the minting. So we'll do that as well. Okay, there's a ton of code here. And like I said, we definitely would not have written all that code without having compiled to run some tests first, but we decided we want to just write
it all right off first. So and I did some misspellings. Let's just make sure everything compiles here. Awesome. Everything's compiled here. As you already know, a couple things that we're going to need to do to test this out. First thing we're gonna need to do is write our deploy function, we've got our basic NFT, we've got our random and f t, both of these hosted on IPFS. Now we're going to do a dynamic NFT that's hosted 100 percent on chain, and it changes based off the price of an asset. So l
et's do this. Oh, three, deploy dynamic, SVG nft.js. We are no, we're gonna need a little bit of boilerplate. So let's go to our basic NFT. And we'll just grab all this the first seven lines or so. And we'll just paste it in here. What do we need for our constructor? Well, we need a price feed address, a low SVG and a highest CG. Okay, so let's get all of those. So price feed address is something we've already done before. And we can add that into our helper Hardhead config. And we'll do one and
a foreign local, we're going to use what we're going to use a mock. And if we're on Rinkeby, or an actual network, we're going to use an actual address. So let's go ahead to dark side chain that link will grab a price feed address, the M Aetherium. data feeds will go to rank B, rank B and let's just use eath USD copy that will make a new entry eath USD price feed like so. And for localhost, we're good. So since we know for localhost, we're going to need to do a mock. Let's see if we have a pric
e feed mock. Okay, now we don't, we're gonna need a mock v3 aggregator dot soul. I just copied pasted mine. If you want, you can just go right to the to a repo here. Or you can copy from a previous section, just a reminder heart at f and f t FCC contracts asked moc v3 aggregator and this is using point 06 of solidity. So we're going to want to make sure that in our hard hat dot config, we have at least one 0.6 version, which we do so we're good there. That means in our deploy mocks, we're going
to want to add So initial price will be 2000 decimals will be a team. So now we've waited to deploy mocks for that price feed. So we're gonna say const chain ID equals network dot config dot chain Id do if development chains dot includes network dot name, and the more we need to import development chains looks like where did say const eth USD akregator equals we'll get that price feed equals awaits ethers dot get contract Mark v3 Air gate tour, and then we'll up here we'll do let eath USD price
feed address eath USD price feed address equals eath USD aggregate tore that address else will say the eath USD price feed address is going to be equal to what we find in the network config. Network config. Chain ID dot eth USD price. Okay, so we have the eth USD price feed rate. Now we need the lowest VG and the high SVG. So we're going to create a new folder in our images folder. So we go CD images, MK dir dynamic NF t. And now we'll have two folders in here dynamic which is empty and random,
which has all the random stuff. If you want to use your own SVGs for this, you absolutely can. But if you want to just come to my images file and then save these images as so just come right click Save image as. Save them. and then drag and drop them into your images files here, you can absolutely do that. So now that we have those, we want to go ahead and read those into our script here. We'll say const, low SVG equals a weight. And we're going to use Fs again. So we're gonna do const Fs equals
require Fs, or do await Fs dot read file sync, we're going to read in this file, which for me, it's at dot slash images slash dynamic NF T slash brown dot SVG. And we're using encoding of UTF eight. And then we'll say const. Hi, SVG equals await Fs dot read file sync. Copy this whole thing, because we're using the same stuff. This one's going to be happy about SVG. And that's it. So when price is good, we're gonna do happiness, SVG, when price is bad, we're gonna do frown at SVG. Now, let's go
ahead and let's deploy this contract. So we'll say arguments or args equals, it's gonna be the price feed address, low SVG, and then high SVG. And we'll say const, dynamic S, G and F T equals await, deploy dynamic SVG and f t, comma little bracket here, from Deployer. args, args log true. And the weights confirmations, it's going to be network dot config, that block confirmations, or one will do some logging, I will do log to do that. But Larry, do some verification, I'm actually just going to c
opy paste that from our last script, because it's going to be exactly the same copy paste. But instead of random IPFS, it's going to be dynamic SVG and f t. The rest of this looks good. And that's just about it. So we'll do module, exports dot tags, equals and we'll do all dynamic. SVG. And we'll do main. Oh, okay. Let's try to see if our deploy script that we just created works. To do h h, or yarn hardhat deployed dash dash tags, die Namic SVG, that makes sense, because we didn't deploy the moc
ks. So we'll do tags, dynamic SVGs. And then also the mocks. Local network detected play marks, we deploy the marks, deploying dynamic SVG, awesome. You know what comes next? You Gosh, darn right, it's time for some tests. Now, once again, I'm going to encourage you to pause the video now and try to write your own test for this test for this section actually can be a little bit tricky. Since we are going to be manipulating the price of our mock aggregator, we are checking for these long strings,
and such. So be sure to use the GitHub repository associated with this lesson, in case you get lost. Now, I want to show you what this looks like on a marketplace, like OpenCL. So we are going to deploy this to rink B. Now keep in mind test that can be slow. So you might want to be patient here. And you don't even have to do it if you don't want to. But it is kind of nice to see. Okay, that's what it really looks like. And you can go to the contract on chain once it's verified. And you can read
the token URI and everything. And it's pretty fun. So let's just add one more bit to our deploy folder. Let's add a mint script that just emits an NF T for each one of these contracts. So we're going to create no for mint.js. And we're just going to have each one of these contracts mint NFT. Let's go ahead and do this. So in here, we'll do const ethers network equals require arhat. And then I'm going to do a little copy paste in. I'm just going to copy this part because I know I'm going to need
that. We are going to need a deploy but we're not going to need to deploy. So I'll grab get named accounts, get named accounts, it's going to come right from there. So we have a Deployer. Our deployer is just gonna be used to mint them. First we'll mint the basic NF t. So we'll say const basic NF t equals wait ethers dot get contract, basic N ft, and we'll connect the deployer to it. And then we'll say const basic mint and if T or basic mint, TX equals await basic NF T dot mint NF t. And then w
e'll do a weight basic mint, TX dot weight one and then we'll do a little console dot log base Again, T index zero has token URI, we'll put in a little await basic NF T dot token URI of zero. That's it for the basic entity. Now we'll do our random IPFS and empty. So we'll say const, random IPFS NF t equals await ethers dot get contract, random IPFS and f t, connected to the Deployer. This one, we need a mint fee. So we'll say const, mint V equals await random IPFS NF T dot get mint fee. And then
we'll do the mint. So we'll say const, random IPFS and ft mint, TX equals await, random IPFS and F T dot request and F team. And for this one, we need to pass a value, which is going to be the mint v.to string. Now for this one, just like what we saw in our tests, we're going to have to do this await new promise again, right, because we need to wait for it to return need to listen for those events, we probably should set up the listener first. So let's actually set up the listener first. So we'
re going to do await new promise, and we're gonna do async function. And we're going to do resolve reject. In here, we're gonna use that, that fun little arrow syntax in here. And now since we're in this function here, we actually set the timeout resolve like this, which means we have five minutes to time this out, you might want to bump this up even more five minutes might not be enough, this is gonna be 300 milliseconds here, we're gonna do that once again. So we'll say random IPFS and ft dot
once. Once we get that NFT minted event, we're going to run an async function, we're just gonna do resolve. And inside here is where we can actually put, actually requesting the NFT. But below our listener, right, so in there, and then we can say if developments chains, that includes network dot name. So let's just make sure we import those development chains and network or affect them and chains that includes network dot name. So we're on a test net, this is where we go ahead and we pretend to
be those mocks. So we'll say const Request ID equals random IPFS. Oh, actually, we're going to need to do const random IPFS and ft min TX receipt equals await on IPFS and empty minted TX dot weight one. So we're gonna need to get the receipt. And from the receipt, we can get the request ID. That events one dot args dot request id.to string. And then we can do const VRF. coordinator V to mock equals await ethers dot get contract, the RF coordinate for V to mock, connect this to the Deployer. And
then we'll do a wait the RF corded and a Tor V to mock that fulfill random words with Request ID, random IPFS. And if T dot address, we can do console dot log random IPFS and have T index zero token URI to await random IP. That's NF T dot token URI of zero. Finally, we can do our dynamic SVG, NF t. So we can say const, high high value equals ethers.utils.do parse ether here. So we'll say 4000 $4,000 will be the high value. We'll say const. Dynamic SVG and f t equals await ethers dot get contract
, dynamic. SVG and a T will connect it to the deployer say const by Namic, s, B, G, and f t mint, TX equals await dynamic SVG and F T dot mint and f t i value to string then we'll just do wait. This stat wait one. And finally console dot log dynamic. SVG NFT index zero token URI is going to be a weight dynamic. SVG and ft dot token URI of zero. Okay, I think that looks good. Let's try this on a local network. So we'll do yarn hard hat deploy. And we'll run all those scripts It looks like everyth
ing worked. So we have random, basic NFT index zero has a token year, I have this IPFS thing, random IPFS NFT. index zero has this thing. And then our SVG has this giant monstrosity, okay, perfect. And then we can even check, right, we can even grab this IPFS hash, we go to our IPFS node, or if you installed IPFS in your browser, or you're working with Brave, we can just pop it right into our browsers and see what it looks like. Right. And then if I zoom in, and adorable St. Bernard, with the im
age of the St. Bernard, looking like that, this one's also gonna be St. Bernard. And then of course, are SVG, which we can also copy, paste, and boom, that looks great. And then we can copy the image. And it's a frowny face or shad. But Awesome. Okay, so it's working locally for us. Now, let's go ahead and try to make this work on an actual test net. So hopefully, our helper hard hat config is set up correctly. And there's enough stuff in here where we need to make sure that we have a subscripti
on ID, right, we're going to need to make sure we have a subscription ID. And we shouldn't call the mint function, right, because we're going to need to add our consumer to the VRF. Before we can actually meant so let me let's add some tags to our meant here. So we'll do module dot exports, dot tags equals, and we'll say all comma meant a while ago, I said okay, let's add a main tag. Now we're coming around to why we added this main tag here. So what we want to do is want to deploy all of these
contracts. But before we finally meant for our IPFS one, we need to add that contract to our consumer, here's what we're gonna do, we're gonna run yarn, Hardhead, deploy dash dash network Rinkeby dash dash tags main. Now, this won't meant any of our NF T's, okay, won't mean to any of our NF T's, it'll just deploy those contracts might just sit around and wait a little bit for these to actually deploy. So this is a great time to go take a break, maybe go take a walk, get a sip of water, get a cup
of coffee, whatever you want to do. Yeah, once everything is deployed, then we can go to V or F dot chain dot link, we're already connected here, we used our subscription. And then we would just add our IPFS consumer in here. And we'd be good to go. And All right, once everything goes through, and we have all three of our transactions on the blockchain, we can go ahead, we can grab our random IPFS NF T, we'll grab that address, we'll come back over to V or F dot chain dot link slash rink D, we'
ll go to our subscription ID, and we'll add a new consumer will add that contract address. So we'll go ahead and approve and Metamask. And once this goes through, we can finish running the mint part of our deploy folder. Once it's confirmed, we can close maybe we can do a little refresh, we should see our new address added as a subscription here. Now that we've added that we can mint one NF T from each one of these contracts are in hard hats, deploy dash dash tags meant dash dash network Rinkeby
. And we'll have to wait a little bit for this too. Okay, now that we have them all minted, we should get a little output like this. Right? Basic NF t zero has token URI here. Basic random IPFS NF T has token your eye here. And then our SVG has this as a token year, right. So what can we do now? Well, let me go grab, I'll grab my wallet address and stick it into Rinkeby ether scan. And we can see we called mint request and mint again. And we created three contracts, right, we created our basic N
FT, our random IPFS NFT and our dynamic SVG NFT. What we can do now is we can grab, we can copy the address of our contract. And we can go to test nets that open see that i Oh, and we can put that address in the bar here in the search bar here. Now this part is incredibly, incredibly variable. Okay, open C can be really slow. And it can take open see up to a couple of hours to register that a contract has been deployed to a test net. So if it doesn't show up right away, don't be discouraged. Don
't let it drag you down. But if it does, you should be able to click on your collection and see the NFT is actually here. I'm going to grab our random IPFS NFT. Let's grab that contract address. I'm going to grab that test net site open c.io. Paste that address in there. And what do you know we do indeed see, random IPFS and f t, right and I've deployed a couple of them. So this one's v two, and we have our adorable Shiva in you right here. So this is what it looks like an open C now we can 100
percent verify that our code is good even if it doesn't show up on Open. See. If we go to the contract we go to read contract. And then we go to token URI punch and zero here. A query, grabbed this, stick it into our browsers, the JSON looks good. So let's grab the image URI. Paste that in. And if we can see this here, that means that our code is good. And you have successfully deployed a number of FFTs to the blockchain. We have learned a massive amount in this course, this is definitely one of
the most jam packed one. And it's all about art. Right? Isn't that crazy? Let's do a quick refresher of this entire course here. So first off, we learned the basics of an NF T with our basic NF T dot Sol, we learn that these NF T's are based off of the ERC 721 standard. And that just means they have functions like name, token, Uri, etc. We learned that NF T's use this token URI to tell us what the token actually looks like a token, your eye will look something like this, it's going to be a name
a description, it's going to have an image URL, which points to a different location for what the NFT actually looks like. It'll have stuff like attributes, it can have stuff like attributes, and a few other tags. This is known as the metadata of the NFT. And this tells us about the NFT. We can also have all that metadata on chain, of course, to customize it on chain, and make it look and grow and change and be interactive on chain, we learned more about IPFS, we actually wrote a script called
upload to pinjarra.js, where we can actually programmatically upload images and files to another IPFS pinning service for us, we can of course, always use our own IPFS nodes if we want. Now this token URI can really be anything. And we hosted it on IPFS for our basic NFT and for our random NFT. But for our dynamic NFT, we actually hosted the token, you're right 100 percent On chain, so we didn't use IPFS. And we made this dynamic where the token URI actually changes based off of the price of a c
hangeling price feed in our random IPFS NFT, we gave our NFT a chance we gave different rarities to the different dogs so that we could create programmatically rare NF TS where our pug is super rare. Our Shiva is sort of rare, and our St. Bernard is pretty common. So the fact that we got to ship it in you was awesome. We did some amazing deployments, we wrote some tests. Not only that, but we learned a lot about transactions, and how we can actually add whatever data we want to this data section
. And a little bit more about what our transactions look like, and how we can actually use functions, selectors and function signatures to be able to call anything, right and we learn more about ABI dot encoding, and encoding packed and all this binary stuff if you want it to go deep into that. So this was an absolutely JAM PACKED session. And you should be incredibly proud of yourself, especially with your little puppy that you can see on open sea or you can see directly on ether scan, or you c
an just look at it and IPFS and be really proud of what you've done. But with that being said, huge congratulations on making this far. Definitely definitely definitely take a break here, and we'll see you in the next one. Okay, now we have less than fifth team, which is going to be our next JS NFT marketplace. And if you finish this lesson, you are a web three full stack monster, this is going to be our most complicated front end using the web three stack and using a lot of really advanced web
three, and blockchain tools. So get really excited because we are going to learn a ton in this lesson. Now there are actually three different repos associated with this lesson. The first one is going to be our typical hard hat project. For the back end, after the hard hat project, we actually have two repos both are going to be our front end repos, and they're going to be slightly different. In this project, we're going to learn more about how events are so important and why events are so import
ant, especially for off chain services. And so we're actually going to look at two different ways to work with them, one using the mirallas, or a centralized database, and then one using the graph. And the reason that I want to show both of these is that oftentimes, when people are looking to scale the projects, when people are looking to get things done really quickly, taking a more centralized approach can often be a little quicker, and you can sometimes add more functionality to your website.
And there's still a lot of protocols that have decentralized backends. And centralized front ends. One such example, is open sea, open sea, for example, has the ability to actually like different and fts. Now, this isn't something that we would actually want to spend any gas on. But it is something that we're gonna have to store in some type of database somewhere, so that people have the ability to do that. So I want to show you this optional first way to build these front ends, since all of ou
r logic is still going to be 100 percent. On chain, the front end matters a little bit less, because anybody can still interact with the contracts that we build on chain. Now in web three, we don't want to stay there. However, getting an MVP done getting a minimal viable project done is really, really important. So using a centralized server, like Morales, or centralized project can make us much quicker. In fact, we have been using centralized services, like alchemy, kind of throughout this whol
e project. But of course, I also want to show you the decentralized way to make your front end. So after we work with Morales, we're also going to show you how to use the graph then for to do all this event indexing. Now the graph is going to be the decentralized way we can make our front end and work with these events. And the graph also comes with its own graph repo. So we'll learn all about that once we get to the front end section. But let me show you what we're going to build because it is
really cool. Now that we've learned a ton about how to make NF T's what they are, we're going to make our own NFT marketplace. And like I said, this is really going to be our deep dive into all these amazing front end tools. So here's what our front end is gonna look like. But what we can do is we can connect with our little connect button, we hit Metamask Metamask pops up, we'll go ahead and connect. And now that we're connected, we can see the different entities in here. And if we're on an add
ress that's owned by us, it will say owned by you. And if we switch addresses, or UI will go ahead and update, connect there. And now we're owned by a different address. Now, if it's owned by us, we get this little hover that says Update listing. And right now it's worth 0.18. That's what it's listed for on our marketplace. If it's owned by us, and we click it, we can update it to a different price. Let's update it to 50 eath, or whatever your layer one currency is, we'll just say new listing pr
ice, we'll go ahead and confirm. And I'll say listing updated, please refresh, and what we can do them. And we'll mine some blocks on the back end, and boom, now we see that it's worth 50 here. Now if we switch to a different account, now we can see owned by blah, blah, blah, and the hovered now says by me, if his selected as a different user, I'm gonna get this transaction to actually buy it. Now go ahead and confirm that I'm gonna buy it, I get a little pop up. This is item bought successfully
. Now if I do a little refresh, we'll now see that that NFT is gone from the marketplace, since we bought it right, it's no longer available to be sold. Now what we can do then is we can come over to sell NF Ts and at the bottom, we'll see a withdraw proceeds. So whenever somebody buys an NF T, the NFT marketplace actually keeps the proceeds that actually keeps the result of the sale. So if we switch back to our address that had the NF T listed, we can now see Withdraw 50 proceeds because we kno
w that we have 50 eath, because we just bought that for 50. So if we hit withdraw, Metamask is gonna pop up, we can go ahead and confirm, wait a little bit as transaction populates, and boom once it goes through, we'll see now we have zero proceeds. Right, we withdrew everything from here. So what we can do now, is we can relist that NFT. So if we come back, let's go back to the one who just bought that NF t. If we know the address and the token ID of the NF t and we own it, we can go ahead and
relist it, because we can place the address in here with the token ID Give us some sort of price, we'll submit, we'll approve giving the NFT marketplace access to our NFT to our little doggie. And then we'll go ahead and actually send the transaction to actually list the NFT on a marketplace that we get NFT listed successfully. After we remove some blocks in the back end, we can go back to the front end. And we now see, it's owned by us, instead of the original owner, right and set for 10 ether.
And then we can of course, switch back to a different user, and we can have them actually buy. So this is going to be a NFT marketplace that's completely decentralized, we are going to learn a ton about front end a ton about indexing a ton about events, and why they are so powerful. And I'm really excited for you for this one. Because if you get through this one, you will have so many tools at your fingertips for working with the blockchain. Are you ready, let's jump in. Let's build the contrac
ts first, and then we'll build the front end. Let's do this. Now this project is going to be based off the Arteon project, which is a completely open source decentralized smart contract NFT marketplace, I'll leave a link to it in the GitHub repo associated with this course, ours of course, is going to be a minimalistic version of this. So we're in our VS code pre normal. And we're going to create a new folder here called hard hat. And if T marketplace, FCC, oops, MK dir, like them, we're gonna c
d into it. And then open this up and its own VS code. Once again, you can use code period, or file open folder, and open this folder. Once we get in here, we're going to do all of our normal stuff that we've been doing throughout the course. And once again, if you want to copy paste over your package, JSON, if you want to copy paste in the modules, whatever you want to do, feel free to do so I'm gonna go ahead actually, this repo here, we're gonna scroll up and just grab once again, this line fr
om less than nine. And just run that I know I'm gonna be using prettier so I'm just gonna go ahead and copy paste those two prettier files over prettier ignore and prettier RC going to be using them again, for linting. With solidity we're going to use Sol hint dot JSON. So we're going to grab that dot soul hint dot JSON. And the dots will hint dot ignore. I'm also going to grab the hard hat dot config dot j s because we're going to be using a really, really similar setup. And this hard hat dot c
onfig dot j s. It's got waffle in it, ether scan, hard hat deploy coverage gas reporter sizer and Dottie and v dot config, we're going to bring over our Dotty and V. And we're also gonna bring over our utils folder as well. Right, so a lot of that boilerplate we're gonna bring on over. And now just like that, since we have the hard hat dot config dot j s in here, if we run yarn, hard hat, right now, yarn hard hat will actually see we get the output like this. So let's go ahead. And before we act
ually write our contracts, let's go ahead and write a little doc saying what our contract is even going to do, what do we want this to do? We're going to create a decentralized NFT marketplace. So what does that mean? What will we probably need? Well, we'll probably need some type of list item function, because we'll want to list NF T's and this will be to list NF t's on the marketplace, we'll need some type of buy item to buy the NF T's. And then we'll probably need maybe like a cancel listing
or cancel item, if you no longer want to sell it, maybe an update listing, update price. And then maybe a withdraw proceeds to withdraw payment or my bot and fts. So when somebody buys an NFT, I'm gonna have to withdraw it from the contract since the contract is going to be the one to actually hold those funds. That looks pretty good to me. Let's go ahead and start building this. So let's create a new folder, contracts. And let's jump into this. So we'll create a new file NFT marketplace. That's
all. So let's get our boilerplate. spdx pragma, solidity, carrot zero, point, 8.7, contract and ft. Marketplace, boom. If we're doing this, right, h h compile or yarn Hardhead to compile or MPX, art, hit, compile, boom, things are looking good. So if we go back to our readme, we can grab these here, even stick them in as like a little comment for us to kind of reference later on. Let's start with listing the items. How are we going to keep track of listing people's items. And once again, rememb
er, when I'm usually coding this, I'm going back and forth between writing tests and writing the actual code. We're just going to write all the solidity in one chunk, and then go write the tests. So we're going to say, these are going to be our main functions. I'm going to start with function list item. And we are going to make this one look really, really good. So we're going to do natspec. And everything, this is going to need to be an external function, right, we're probably not going to want
any of our internal functions calling list item, it's going to be called by external projects or external accounts are probably going to need an address and ft address, write the address of the NFT, contract a un 256 token ID, the ID of the token ID of the contract that we're going to use. And then we're going to want to set a un 256 price. So first off, we're probably going to want the price to be greater than zero. So maybe we'll put in like a little if or require statement here, we'll say if
price is less than or equal to zero, then we'll go ahead and revert with a price must be above zero error. And then of course, we'll prepend it with the name of the contract into underscores. And then at the top, the error price must be above zero. Now in order for us to list it, we could actually do this one of two ways we could one, we could send the NFT to the contract, this would require us doing like a transfer, right, we could have got the contract hold the NFT. Now we could do this, but
this is going to be kind of gas expensive for someone to actually list on f t. And we can have the owner of the NFT be our NFT marketplace, we could 100 percent do that. The issue with this, though is that the marketplace will then own the NFT. And the user won't be able to say like, Hey, I own this NFT, it's in the marketplace, they technically would be able to but they would have to withdraw it, we might do this a slightly different way where we can say owners can still hold their NFT and give
the marketplace approval to sell the NFT for them. Now, of course the owners of the entity could withdraw approval at any time and the marketplace wouldn't be able to sell it anymore. However, this would be really easy for people to actually read, they would all they would have to do is read like is approved for marketplace. And they can actually see if the item was really listed or not. So we're gonna go ahead and write it this second way, because that's what Ardian does. And this is the least
intrusive way to have this marketplace, right? People still will have ownership of their NF Ts, and the marketplace will just have approval to actually swap and sell their NF T once the prices are met. So since we want to make sure the marketplace has approval, let's make sure the marketplace has approval. So we can call we can call this get approved function on that token ID to make sure that the marketplace is approved to work with the NFT. To do this, we're going to need the AI ERC 720 inter
face and we can actually grab that from open Zeppelin. Right and this interface will wrap around an address and then we can call get approved on that address. So we'll do import at open Zeppelin slash contracts slash token slash ERC 721 slash I ERC 721 dot Sol. And since we're doing an import from open Zeppelin, we'll do yarn add dash dash Dev, add open Zeppelin now that we have this interface in here, what we can do is we'll say I ERC 721 NF t equals IRC 721 wrapped around this NF T address tha
t we're passing in. And we'll say if NF T dot get approved of the token ID that we're trying to list does not equal address this. So if we are not approved, then we'll revert not approved or market place. And then we'll of course we'll want to do prepend it with NFT marketplace into underscores. So error like this, Bada bing bada boom, now that we've gotten a little bit of that out of the way, we're probably going to want to have some type of data structure to list all these NF T's. And typicall
y we get to Okay, do we want to use an array? Or do we want to use a mapping? What do you think? Before we continue? Let's pause for a second, do you think it makes more sense to put these NF T's and an array or an A mapping? And when you're thinking about this, try to think about, okay, well, people are gonna have to buy these and sell these, what makes more sense, think about this for a second, maybe pause it and write in a comment here, what you think an array or a mapping is better. Now, if
you said mapping, I would agree with you. You couldn't do an array and you wouldn't necessarily be wrong, but it's not the way that I would go about that for an array. Anytime someone wants to buy an item, we're gonna have to traverse through the array, we're gonna have to make this massive dynamic array. And that might get a little bit dicey as that array gets really, really big. So we're gonna go ahead and make this a mapping. And this is probably going to be a global variable or a state varia
ble. So up at the top, let's go ahead and create this mapping, it's going to be a mapping of addresses of NFT addresses. Right? So it's going to be the NFT contract address mapped to the NFT, token ID mapped to some type of listing. So we'll say, a mapping of address to a mapping of UNT 256. to, well, what do we want here? Well, we want we want the price, right? So is that another you went up to six. But we also want, we also want to keep track of the sellers, we know who to send money to. So we
could make two mappings or we just create a new type of type listing, let's go ahead and do that. We'll comment this out for now. And so at the top, since this is going to be a type where, say, struct listing, and in here, we're going to do a utility six, the price of the NF t, and then address the seller of the NF team. And now that we have that new typing, we can uncomment this, we can say NFT, contract address map to the NFT token ID mapped to the listing, and we'll make this a private varia
ble called S underscore listings. Now back down in our list item function, we're going to update that s listing mapping. So we're gonna say s listing of NF T address, right, the address of the NF T at the token ID is going to equal we're gonna create a listing of the price. And then who, well the seller is going to be message that sender, right? So message dot sender, they're the one who's actually listing the item. And since we're updating a mapping here, what's the best practice for update map
pings, you guessed it, we need to emit an event and especially for this project, you're gonna see why emitting events, for at least this project, this is so helpful. So we're gonna go ahead and emit an item listed event, which we're going to create in just a second. And we'll give the message that sender, the NFT address, the token ID, and the price item listed. And then up at the top, of course, but below our structure, we're gonna say event item listed will do an address indexed seller address
indexed NFT, address, address indexed token ID, and then a un 256 price. Sorry, this needs to be a un 256 token ID, you int 56. This looks pretty good to us. However, we probably want to make sure we only list and FTEs that haven't already been listed. So we can add like an if then in here. And this is kind of where preference comes in a little bit. But I'm actually going to create a modifier called not listed. So we make sure we don't relist, and if T's that are already listed above our main f
unctions, or do like a little indicator modifier not listed. This is gonna take an an address NFT address, a un 256 token ID and an address owner. And what we're going to say is we're going to check, we're going to make a new listing memory listing equals s underscore listings of NFT address token ID. Now we're gonna say if listing dot price is greater than zero, we're gonna go ahead and revert with already passing the NFT address and a token ID. And of course, we're going to prepend this with N
FT marketplace. And at the top, we do error ft marketplace already listed, like so. And then we're going to put a little underscore right underneath and then up here, we'll do address and if the address you went to 56. Okay, ID. So this modifier looks pretty good. Let's just make sure it's actually going to compile we'll do yarn Hardhead compile or hh compile. Great. That looks good. We'll add this modifier to our list item function will do NFT address, token ID message dot sender. Cool. What el
se should we check for here? Well, we should also check that the NF T that's being listed is owned by message dot sender. This way only the owners of the NF T can actually listed here so let's go ahead and we'll add a is owner modifier modifier is owner NFT address token ID spender you into 256 here and an address spender I ERC 721 NF t equals IRC 721 And if the address address owner equals NF T dot owner a Have a token ID. And then we'll say if spender does not equal owner. And we'll revert wit
h a not owner error that we're going to go ahead and create up top. So we'll say error, not owner. And we'll prepend it with NFT marketplace with two underscores revert revert not owner, then will do underscore for the rest of the code, and boom, now underneath are not listed will do is owner NFT address, token ID message dot center. So now our list item checks to see if it's already listed, make sure that only the owner of the NFT of that token, Id can list it. And then it goes ahead and lists
it looking nicely. Okay, cool. So that is our list item method here. Now let's go ahead and do a little bit of natspec on this. And now we have a little natspec here, which looks really professional. Alright, great. So we have a list item function. All right, what's next? Well, maybe let's make a buy item function for people to buy their NF T's after they've been listed. So let's create them do function by item. So we'll take an address, and if the address un 256 token ID, and this will be an ex
ternal function. And that will also make this payable an external function because we know only people or contracts outside of this contract are going to call by item and payable so that people can spend eath to spend eath, or whatever layer one currency to actually buy these prices, we could want 100 percent at channeling prices in now for listing, we could of course, add price and then do like, you know address token price. And do what we did before with chain link price feeds to convert the p
rice of these tokens into how much they actually cost. And we could 100 percent do that with chaining price feeds. But for simplicity, we're gonna leave that off. But I will put that as a challenge to you through challenge is going to be have this contract accept payment in a subset of tokens as well, of course, we would need to give a little hint here is channeling price feeds to convert the price of the tokens between each other, we're gonna choose which NFT in which token ID we want to buy. S
o what's the first thing that we probably want to do? Well, we probably want to check that this by item is actually listed. So we're actually going to make a new modifier instead of not listed we'll make it is listed up and modifiers modifier is listed. And this is going to take an address and up the address un 256 token ID. And to check to see if this is listed, we'll say listing memory listing equals s underscore listings of the NFT address of the token, Id sort of go into the mapping here. An
d then we're just gonna check the price. So we'll say if the listing that price is less than or equal to zero, so basically, if there's no price, if it's defaulted to zero, if the price is zero, then we're gonna say revert, not listed. And after the address, token ID, and of course, we're going to prepend. And if the marketplace and the marketplace underscore underscore, not listed, and then we're gonna copy this up here, we're gonna say air listed, and this is going to take address, NFT address
, and au int 256 token Id like so, the down in our modifier, then we're going to add the underscore and to add the rest of our code here. So now we have an is listed modifier, we're going to check to make sure that that NFT is actually listed down here now we're gonna say is listed address and ft address or excuse me, and if the address and token ID. Now once again, we're gonna say listing memory listed item equals s underscore listings. And if T address token ID, or say if message dot value is
less than listed item dot price, then we're going to revert with price not met. Then we'll do NFT address, Open ID listed item dot price Excel so we're going to create a new air price not met error. Price not met of course we're going to prepend this with NFT marketplace to take an address. And if the address you went to 56 token ID and then a UNT 256 price. So we can see exe exactly how the price wasn't met, and then back down here, we'll get the full error. So we want to make sure they're send
ing us enough money. First of all, when they send this money, it needs to belong to whomever listed the item. So we actually need to keep track of how much money these people have. So let's create another data structure called proceeds where we keep track of how much money people have earned selling their NF T's. So we'll create a mapping of address to you and 256. And this is going to be a mapping of seller address to amount earned. And we'll make this private called S underscore proceeds. And
what we'll do is when somebody buys an item, is will update their proceeds. So we'll say as proceeds of listed item, that seller equals s proceeds of illicit IO dot seller plus MSG dot value. Now, once we buy this item, we're going to want to delete the listing. So to delete a mapping from a wreck, so to delete an entry and a mapping, we just use delete s underscore listings and ft address of the token ID. So we remove that mapping. And then finally, we're going to go ahead and transfer it. So w
e'll say I ERC 721 and ft address, we're going to call dot transfer from the listed item dot seller to the message dot sender with the token ID. Now you'll notice something here, we don't just send the seller the money. Now why is that? Well, solidity has this concept called pull over push. And it's considered a best practice when working with solidity, you want to shift the risk associated with transferring ether to the user. So instead of sending the money to the user, this is what we don't wa
nt to do want to have them withdraw the money, we always want to shift the risk of working with money and working with eath or whatever layer one you're working with, to the actual user. So we don't want to send them the money directly, we want to create this s proceeds data structure and we can have them withdraw from it later on. Now, we could probably do some checking here. Or we could say okay, check to make sure the NFT was transferred. And if we look at I ERC 721 though, and we're looking
at the transfer from function, we don't see it actually has a return. And if we go to the IP 721 We can see that none of these have a return type though, transfer from doesn't have a return type here. However, we do see this safe transfer from bit safe transfer from it's going to be a little bit better, right because if we look at transfer from transfers ownership of an entity, the caller is responsible to confirm that underscore two is capable of receiving entities or else they may be permanent
ly lost. So maybe instead we want to use safe transfer from which throws an error unless message sender is the current owner and authorize operator, or blah, blah, blah. So instead of transfer from we're going to actually use safe transfer from just to be a little bit safer. So we'll do safe transfer from instead of transfer from. And then since we're updating a mapping, we're going to do what, you guessed it, let's omit an event, we'll call item bot. Lab will be a message that sender, an empty
address, token ID and for listed item that price. So off the top, let's create a new event. To event item bought. And this will be a an address indexed fire an address indexed NFT address an address indexed token ID and then a un 236 price. Just kidding, that doesn't look fantastic. This should be intuitive six. Now it looks fantastic. Now in this buy item, we've set this up in a way that is safe from something called a reentrancy attack. And we've been coding these contracts in a way where we k
ind of do all this state change first. And then we transfer the NFT that token or etc. But why are we doing that? Cognitively we think it might make sense. Okay, first, maybe we should actually send the NFT right, we'd want to send the entity first. This is actually a huge security vulnerability. And to understand why let's learn about one The most common hacks in blockchain, the reentrant. See attack. Now in this sub lesson, we're going to talk about reentrant. C, and in the GitHub repo associa
ted with this lesson, we're going to have the code for everything that we're going to go through here. And the code that we're looking at is based off of this solidity by example. reentrant. See example. And I have a link to it in the GitHub repo associated with this course. Now, I have a sample contract here, it's a place where you can deposit and withdraw your eath. So what it does is it has a mapping called balances, where you can call deposit, and it'll update how much you've deposited into
the protocol. And then it has a withdrawal function as well. So what it does is it first grabs your balance from this balances mapping, make sure that you have more than zero. And then the way that we've been sending eath, this whole time, we do message that sender dot call, we send the balance, and then we update bounces of message sender equals zero. Now this is the line that actually makes this contract incredibly vulnerable. And if we run this right now, though, we'll say hey, no, it looks l
ike it's working as expected, we can go to deploy a copy the accounts that I'm working with, like that in a bounce zero, we can deposit, you know, it's going away, let's go to ether, will deposit to ether, come down, what deposit now had to balance bounces up, we'll hit withdraw, now have bounces goes back to zero. And it seems like it's working as intended. Now, there's actually a way we can attack this function to drain all the money in this contract. And this is what's known as a reentrancy a
ttack. The two most common kinds of attacks in this space are going to be reentrancy attacks, which is what we're talking about here. And Oracle attacks, which usually only happen when a protocol doesn't use the decentralized Oracle, lucky for you, we're teaching you right from the get go how to use chain link so that you can be protected. And it's these two types of attacks that often result in the most amount of money last, there's a leaderboard called rec dot news, which keeps track of many o
f the top attacks that have ever happened in the defi space. With many of them if you go into the retrospectives are either an Oracle attack or a reentrancy attack. And you might be saying, Hey, where are we just talking about NF T's this, this doesn't have anything to do with NF T's we'll get there, don't worry. In a new contract below, we're going to create a new contract called attack down here. And what we'll do with this attack contract is we'll grab this reentrant vulnerable contract, we'l
l say reentrant, vulnerable, public reentrant vulnerable, like so. And we'll save that reentrant vulnerable contract as a global variable. And we'll say construct door address, underscore ranch and vulnerable address. And then we'll say reentrant vulnerable equals rancher and vulnerable at reentrant vulnerable address. Now what we're going to do is we're going to create a function called attack. And it's this function that's going to call withdraw in a malicious way. So we're going to say attack
, this is going to be an external payable contract. And we're going to call the posit on this. So we'll deposit some money first. So we'll do reentrant vulnerable dot the posit will send a value of one ether. And then immediately we will call re N Trent vulnerable dot withdraw. Now at first glance, this seems pretty harmless. But remember, when we call message dot call like this to send we're calling back to this this attack contract. Now when we call this attack contract, is there a way to exec
ute any other code? Well, there is remember how we learned about fallback functions. If we put a fallback function in here or a receive function. When this code runs call and seconds our contract ether we can have it trigger our fallback function to call withdraw again. So that will send our contract more ether than it's do before we update the balance. So let's see what this looks like. So in our fallback here, we'll say if the address of reentrant vulnerable balance is greater than or equal to
one ether aka we're saying if there's money left in the contract, then rancher invulnerable dot withdraw. And then we'll put to get balanced function in our attacking contract. We're going to attack reentrant vulnerable by calling withdraw. When we get to this send section, what are we going to do, we're going to have our fallback function trigger calling withdraw again. Now when we call withdraw again, bounces a message that sender hasn't been zeroed out yet. So the contract code will go, oh,
you still have some money here. Let's go ahead and let's send you that, which will then again, trigger us to call withdraw. And so we'll just keep calling withdraw until we're done. So let's see what this looks like. So we compile this, and then let's go to deploy, first, let's deploy the reentrant vulnerable contract. Alright, and we can have any contract address, you know, like the one that deployed it, we can have a deposit, let's do, we have a deposit one ether deposit. Now we can check the
balances of it. Copy. Paste great, is one. So now let's have a do 10. Deposit, it took the balance. And now we have this much in here. So we have this much in here. And if we withdrew, we withdraw all of it. And if we switched accounts, to somebody else, we hit withdrew. Nothing would happen because that other account doesn't have anything, which makes sense. So there's a lot of money in here, right. And if we do get balanced with the contract, we can see how much money it has, right? It has thi
s much money total. Now what we can do on a different account, let's choose this, this brand new account, let's go ahead and deploy the attack contract. And we'll pass it the reentrant value address as an input parameter. So we'll deploy that. And now what we'll do is we'll call attack. And you'll see even though this contract doesn't have anything deposited in the reentrant vulnerable contract, we will still steal all the funds in here or just about all the funds. So right now hit get balance,
and a reentrant vulnerable, here's what it is, get balance a here zero, you know, there's the address, we had attack now, now that get bounce, oh, excuse me in public, and withdrawal should be payable as well. Now we'll pass one ether as an input parameter to our attack function, and we're going to deposit just one ether. And then we're going to withdraw. And we're going to keep withdrawing, because our fallback function is going to keep calling withdraw. And all we had to do was deposit one eth
er, and we're gonna be able to pull out all 11 that are in here. So we'll hit attack now. Transaction went through, the new balance of our contract is 12, because the one that we deposited and then the 11 that we stole, and the new balance of our old contract is now zero. So this is known as a reentrant. See attack. Basically, since we call a function in another contract in the middle of our withdraw, we allow code to run on a different contract. And the code that ran runs on this contract, reca
lls withdraw before balances is set to zero, we get to here we call the fallback function of our other code, and it calls withdraw, and we need to reread withdraw before we get to setting balances a message that sender equals zero. So this is an issue, obviously. And there are two ways we can prevent it. There's the easy way. And then the mutex way, I don't wanna say the hard way, it's just a different way. So one of the things you'll always see in security tools is you always want to call any e
xternal contract as the last step in your function, or the last step in transaction. And we want to update bounces to zero before we call that external contract, because of balances of message sender is reset to zero before we call external code, then if it were to try to re enter this, it would hit this require step and just cancel out right here and wouldn't be able to send any ether again. So that's the first step that we can do. The next step that we can do is using something called a mutex
lock. And this is what open Zeppelin does with one of the modifiers that they have, we can have some type of a Boolean called locked or something and just right at the top, we can just say require not locked. Otherwise, revert. And then the first thing we do in this contract is we can say locked equals true. And then the last thing we do in here is we say locked equals false. And using this lock in here, we only allow one piece of code to ever execute in here at a time and we only unlock it once
the code finishes. Now open Zeplin comes with a reentrancy guard which we can use on our code. And it has a modifier non reentrant which does essentially what we were talking about with our locks it creates a variable called status and changes it to enter whenever a function has been entered. It runs out code, and then changes it back to not entered when it's finishes. And whenever any code runs, it just requires that it is not entered. So if we wanted to use this on our code, we can import at
open Zeppelin, slash, contracts, slash security, slash reentrancy. Guard about so we can inherit the functions by saying NFT marketplace is reentrancy guard. And then any function that we're nervous is going to have this reentrant see issue, like maybe by item, for example, we would just add the modifier non reentrant. Just like that. And that'll add that mutex, that locking mechanism that we talked about. Now, the mutex way is a little bit more explicit with our security, right? Because we're s
aying, Hey, this is locked. This is a non reentrant function. Still a best practice, whenever you call external code, like what we see here is you do all of your state changes before you call an external contract. Now, you might be saying, Oh, that's cool at all. But what about how does this relate to our NF Ts? Well, imagine for a second, instead of message that sender dot call, this is, you know, all success equals, you know, some NF T dot transfer from, and then we do some transfers from stuf
f in here. And instead of doing some fallback stuff, our NF T has our NF T's function transfer from the similis code to re enter into our withdraw. If we have our withdrawal set up like this, since we're still calling an external contract with NFT. To transfer from that transfer from in that external contract could be malicious and try to re enter our contract. As a best practice, you always want to change your state, before you call any external contracts that you might not have control of, I h
ighly recommend playing around with this a little bit just because seeing is believing. And with that being said, again, all the code for this is going to be available in the GitHub sociated with this lesson for this reentrant vulnerable code. And with that, let's go back to our NFT project. Okay, so now we know why we're doing this safe transfer from at the bottom of our function here at the bottom of our bio, because if our safe transfer function from was a little bit higher, maybe what ends u
p happening is we send multiple NF T's to the wrong address before we update them. So that's why we do that. And we favor push over Paul. As we said, Here, there's a whole lot of these security tips that you'll learn going on through this course and in solidity. But this is still fantastic, right, we have our by item. And we have our list item functions. Let's do a cancel item now, or cancelled listing. So we'll do a function. Cancel listing we'll do the NFT address. And the UN 256 token ID. Thi
s will be an external function. One will want to make sure only the owner of this entity can cancel it. So we'll say is owner. And if T address, token ID message dot Sen. Want to make sure that the NFT is actually listed. So we'll do is listed and ft address, token ID. And great. Now to cancel this, all we're going to do is we're going to delete s listings NFT address token ID, we're just going to delete that mapping. And then we'll emit an event item cancelled message dot sender and if T addres
s and token ID. And of course, we're going to create a new event here. We'll say event item canceled. And it will be an address indexed seller address. Index NFT address. You want to 56 indexed token ID. All right. Great. That was pretty quick. Cancel listening. Boom. Jack. Done. What's next? Okay, let's update our listings. So we'll do function update listing address and if the address you went to for the sixth token ID you went to the six new price will update the price of this of this externa
l we'll make sure it's listed with is listed say is owner do a token ID and then we'll do message dot sender. Now to update our listing We'll just say s underscore listings of NF T address. At token ID dot price equals the new price that we're giving it. And then we'll admit, we can omit like item updated. But we can also just omit an item listed with MSG dot sender NFT address, token ID, new price. Because essentially, by updating it, we're essentially just relisting it with a new price. So we'
re just going to do an item listed event, we only have one more function to do, we need to do a withdraw proceeds. So we'll say function, withdraw proceeds to get all the payments for all of our entities. So we'll get the the proceeds by doing new activity six proceeds equals s underscore proceeds of MSG dot sender, right, we're getting all the payments that were collected in by item, and we're saying if proceeds is less than or equal to zero, then we're going to revert with no proceeds. And we'
re going to make this a NFT. Marketplace underscore underscore no proceeds. Excel create at the top error empty marketplace no proceeds being otherwise, we'll say s underscore proceeds of MSG dot sender equals zero. So we're going to reset the proceeds to zero, right, we're going to do this before we send any proceeds. And then we're going to do our traditional way we send payments, so bool success equals payable, message dot sender call value is going to be proceeds all blank here. And then we
could do require, you know, we could do require success, or we could say if not success, reverts revert with Aleksey marketplace, transfer failed. And then we'll make this a new air, air NFT marketplace transfer failed. Put a semicolon here. And we're looking pretty good. Now we even have a way to withdraw. So we have our five functions here. Awesome. Let's just create a couple of getters. So maybe we'll do we even copy this. Paste it here we'll say getter functions like so. And we'll do functio
n maybe we'll do get listing. Take an address, NF T address, the utilities X token ID, external view, which returns a listing in memory. And we'll say return s underscore listings of NF T address token Id like so. And also function, get proceeds of address seller, external view returns, you went to the desex return s underscore proceeds of the seller. So we'll get how much money somebody is owed. And then any listings and let's run a little compile here, yarn, or hit Compile or hh compile just t
o see where we messed up. Oh, we did a mess up. Wow, that's great. And now, guess what? You have successfully created a minimalistic NFT marketplace that's completely decentralized. That is pretty wild. And that is incredibly powerful. And you should feel really excited for yourself. Very cool, very good job. But you know, we're not done, we got to write some deploys and some tests. So let's jump into that. Now since we've done this a couple of times, I actually encourage you to pause the video
here and try writing your own deploy scripts and your own tests. And then go ahead and come back and follow along with us and see if you did it correctly, we're going to create a new folder called deploy. Of course, we already have the hard hat deploy in our hard hat config. So we know we're good to go here. So let's go ahead and create a one. Deploy NFT marketplace.js. Now once again, you've seen a lot of this before, so we're going to spare the details do const network equals require hard hat
to constant development chains, equal equals require dot dot slash help our hard hats config, which we should have let's see. Do we copy paste it over? No. Okay, so we didn't copy paste over Are helper Hardhead config from the last project, let's go ahead and grab it. Or we can grab it from the smart contract lottery and paste that in here. And we really only need this file for the development chains here. Right for hard hat and localhost, we're going to grab the development chains from that. An
d then we'll also grab const. Verify, equals require, get this from utils. Verify, right? Do we have utils, we have verify. Fantastic. Now we'll do module that exports equals async. an async function where it's gonna take get named accounts and deployments. From the hard hat input parameter, and then we're gonna do const. Deploy comma log equals deployments. And then const, Deployer equals await, get named accounts. Which, of course, we're getting from our heart head dot config. We have named ac
counts, we have a Deployer. And we have a player or whatever you have in here from our last project. And now does our entity marketplace have a constructor? Construct? Nope, no constructor. So we know args is going to be blank. And then we can say const NFT. Marketplace equals await, deploy. And if T marketplace, say from Deployer, args is going to be args. Log will be true. And then wait confirmations will be network dot config dot wait confirmations or one, two, this is going to be block on fo
r patients, we'll go to the config, just make sure that those are in here. I'm sorry, I didn't add them in here. So we'll do block confirmations is going to be six for all of our networks. So I actually grabbed this not from the last project, it looks like I grabbed this from the hard hat starter kit. So I'm just going to add those block confirmations in there. And now we're good to go. Now we're gonna say if we're not on a development chain, not development chains that includes network dot name
, and process study and be done ether scan API key, then we're gonna go ahead, we'll do log verifying. And then we'll do a weight verify. And if the markets place dot address with arcs, and then we'll do like log a whole bunch of hyphens here. And then finally, module that exports dot tags equals all and then NFT Mar good place. And we can test this deploy function with yarn Hardhead deploy. Tada, we did it. Great. So now we have the deploy function, we can verify we have our contract, what else
are we probably gonna need to do. Since this is an NFT marketplace, we're probably going to need some NF Ts. So what we can do is in our contracts, and we'll create a new folder for tests got a new file in here called Basic NF T dot soul. And in here, we can add that basic NF T from our last project. Or you can just go to my or you can just go to the GitHub repo associated with this course, go to contracts, test, basic NF t, and then just copy paste. That works too. So this basic NF t that we'r
e using is just pointing to the pug as the basic NF T for us to use just to test this out. So now that we have a basic NFT we're gonna need to create new file, oh to deploy basic NF T dot j s, and we'll borrow a lot of the boilerplate from over here. So we'll copy all of this actually paste it in. We'll say const args equals blank, and we'll say const basic NF t equals await deploy basic NF T. From Deployer. args is going to be args. Log is going to be true weight con confirmations is going to b
e network dot config dot block confirmations or one and then we'll verify this with if not develop meant chains dot includes network dot name and process dot EMV that ether scan API key that will say log or To find dot A dot await there if I basic NFT dot address, and arcs, module dot exports dot tags equals all, and basic NFT. And we can test both of these with yarn, art had deploy. And fantastic. Both of these have been deployed. Again, you don't have to pause. But it is a good way to really h
one in to really sharpen those skills on doing all this. And repetition is the mother of all skill. So repeating this stuff yourself and thinking through these problems yourself and trying to code these things yourself, are really what's going to make you successful at this. All right, awesome. Now that we have our deploy Betson, it's time to write some tests. Now, if you go to the GitHub repo associated with this course, and you go to the test folder, the tests and here are some of the robust,
we've actually written out of all of our projects, there's a lot of tests in here. Now, pretty much everything in here, we've already learned about and you already know how to do you have the ability to do it. So I'm just going to go ahead and get you started off, and we're going to write one test together. And then I highly recommend you going back in, you tried to write some tests yourself, to get that code coverage to get that test coverage to be 100 percent. So let's go ahead, we'll write on
e test together, then you should pause this video and try to write some tests yourself. When you're done writing tests and you think you've hit 100 percent, feel free to compare back to the test that we wrote. So let's create a new folder called tests. Test. And in here, we'll do a new one called unit. And if you want to write staging tests later on, you absolutely can we will not. We'll create a new file in here called NFT marketplace.test.js. And we'll start some tests. So we'll do const. cert
, expect equals require Chai const. Network deployments, ethers, equals require hard hat const development chains equals require dot dot slash dot dot slash helper, hothead config. And we're gonna do the same setup we've been doing. We'll say bang development chains dot includes network dot name, question mark, describe dot skip. Else describe. And if NF T marketplace tests, comma async function, excuse me, this is just gonna be a function. Scrabble oval is just a function, not an async function
, like so. Great. Now let's get some variables and do a before each. So we'll say NF T marketplace, basic NF T, we'll create a constant price. So we're just always set the price of all of our NF T's to the same thing. This will be ethers dot utils dot parse ether 0.1. We'll say const token ID for now will always be zero. And then we'll do before each will be an async function. And we'll get out and we'll also get Deployer. Say deployer equals await, get named accounts. We're gonna need to grab g
etting into accounts from hard hat as well wrap this all up dot deployer Excel and then we'll also in our heart hat.config.js. Under get named accounts, we also have something called player. Now I didn't talk about this too much. But we're going to have a second account which is defaulted to the first index, right? So we can do at the top to come up player. And we can say player equals await get named accounts dot player. Now we have a player and a deployer account will do await deployments, tha
t fixture. All will just deploy all of those contracts will run through everything in our deploy folder. We'll get our NFT marketplace. We'll say NFT marketplace equals await ethers dot get contract and ft. marketplace. And then we'll do basic NF t equals await ethers dot get contract. Basic NF T. The way ethers dot get contract works is it defaults to grab thing, whatever account is that account zero, which right now is our Deployer. If we want to call a function on NFT marketplace, with the pl
ayer being the one calling the function, we would have to say, entity marketplace equals await and empty marketplace dot connect player like this. And now whenever we call a function, we would use the player instead of the Deployer. Sometimes what I like to do and you'll see this in my code, is I'll do let NFT marketplace contract. And then let NFT marketplace, and then I'll do NFT marketplace contract equals await ethers dot contract. And then I'll connect and set that to the NF T marketplace.
Yes, we can do, we can automatically choose who to connect by placing whoever want to connect to write and get contract. But sometimes it's really nice to be kind of explicit. So it's really up to you. I'm going to undo all that, I just want to re show you that to make sure that you knew that's how you kind of switch around with the different accounts and the different users. Now that we have an NF T, we're probably going to need to mint the NFT so that we can actually place it on the market. So
we'll do await basic NF T dot meant NF t, and then we'll approve to send it on to the marketplace. So we'll do a wait. Basic NF T dot approve and T market place dot address token ID, which is going to be zero. And just like that, the NOC marketplace remember, it can't call approve, because it doesn't own that NF t. So we need to have the Deployer. Call approved, right. And remember, since we're not we need to put basic NF T in here. Since we didn't tell ethers who to connect this to it just aut
omatically connected it to our Deployer because that's what's at account zero. So it's the deployer calling minting it and then the deployer approving to send it to the marketplace. Only after this approved function has been called canned the NFT marketplace called transfer from all those NF T's. Now we're just going to do one test here. We're gonna say it lists and can be bought. That's it, and this will be an async function. And we're just gonna list the NFT and buy a weight entity marketplace
.if We go to our energy marketplace, what are we doing, we're listing it right, we want to list the item or with the address token ID and the price. So we'll do dot list item. Basic NF T dot address, token ID is zero, which we've defined right here. And then price we've hard coded up here as well. So we're listing it. So the deployer owns the NF T, the player is now listing it, now we want to buy it, let's have the player be the one to buy it. So what we're going to do is we're going to have to
connect the player to the NFT marketplace. So we can say const player connected NF T, marketplace equals and ft marketplace dot Connect. Player. And then we can buy the item by saying a weight player connected and ft marketplace.by item. It'll be the basic and if we look back at the end of the marketplace, what does buy item need, needs the NFT address and the token ID. So basic NF t that address and then the token ID and after this bot, we should check to see that the player actually does indee
d own that NF team. So we can say const new owner and we check to see if that owner is indeed updated. We can say basic NFT dot owner of because NF T's have an owner of function, token ID and then we also want to see that the deployer actually is going to get paid. So we can say await and if T marketplace dot get proceeds of Deployer. So now we can do assert new owner dot two string equals player and we can assert deployer proceeds.to string equals price.to string because they should have been p
aid that price. And that's right, it's actually a little bit easier. instead of grabbing players from getting named accounts. It's a little bit easier just to grab it right from ethers. So we'll do const accounts equals await get signers. And then we'll save player equals accounts of one just because when we connect it's expecting it type of account and then the the get named account is a different type. So Oh, it's just a little bit easier to actually connect like this. So now we'll connect to
the player like so just know that player and deployer are now different types. So you'll see a little bit differences there. To me, this is ethers that gets signers. And then when we buy the item, we're of course gonna have to pass a value, it's gonna be price, of course, we're going to need to pay the price of the NFT. And then of course, this needs to be player dot address. And that's the difference right now we got to do player that address whenever we want the address of one of the ethers ac
counts. And then this new owner, of course, should be in a wait. And now we can run this all. In Tada, we see things pass. So our NFT marketplace is able to facilitate the buying and selling of an NF T with arbitrary humans. This is fantastic. So we just ran the single test to show a little bit of the oddities when working with NF T's and some different accounts. But 100 percent If you feel up for the challenge, take this time, pause this video and try to write some tests. Remember, the goal her
e is for us to do yarn hardhat coverage, and see what our coverage is and try to get it to be 100 percent coverage. If we run it right now, we'll see Oh, my goodness, we are missing a lot of coverage. Here, we have a ton of uncovered lines, on top of uncovered functions, branches, statements, etc. Try to write some tests to get this to 100 percent and then come back. Okay, welcome back. Hopefully now you've written some tests. And when you run your tests, you can get some of them, I look like th
is, right. And these are my tests, these are the tests that I wrote, you could do more you could do last. And let's see, when I run yarn Hardhead coverage, I even missed some lines. And I could I could test a little bit more. So make your tests even better than the ones that I made. So these are the tests from the GitHub repo associated with this. Now that we've written some tests here, let's just write a couple of scripts. And the reason we're gonna write a couple of scripts is we're gonna need
these a little bit later. So we'll write some scripts to mint, some amount of teased by some NF T's etc. And we'll need this to fiddle around and play on the front end a little bit later. So to create a script, again, we've done this perform, let's do a script called mint, and list dot j s. And this will be to mint at NFT. And then immediately listed on the marketplace. So let's create an async function called mint, and list. And down below, we're going to call mint and list I'm going to copy p
aste with that same script thing that we've been doing. Obviously, instead of Maine, though, we're calling this mountain list. Now in this mountain list, where it's a constant, NFT mark, and of tea market, place equals await ethers dot get contract. And ft marketplace. And right we're going to import ethers from hard hat. And then we'll do we'll grab basic NF t. So we'll say const. Basic kind of T equals await ethers dot get contract. Basic NF t. And then first we'll mint a basic NF t. So we'll
do console dot log, maintained at the top. And we'll do a weight or actual we'll say const. Mint, TX equals await basic NF T dot mint NF t. And then we'll do await min TX dot Wait, wait one block. And actually we'll say const. Mint TX receipt. So that equals that. And in this receipt, here's another reason why events are so good. When we met this NFT. We're omitting the token ID in an event in this document ID event. So we could say const token ID equals mint TX receipt dot events of zero. That
args dot token Id like that. And now we have the token ID. And now that we have the token ID and the basic NFT. minted we can now call on our NFT marketplace list item. So now we'll say console dot log. Approving NFT right, it's gonna be real similar to our tests here. I'm gonna say const approval TX equals await basic NFT data prove NFT marketplace dot address token ID and then we'll do a weight approved TX dot wait one and we'll do console dot log listing NF t.at that and then we'll do const T
X equals await and if T market market place that list item and we'll do NFT marketplace that address So can Id do await TX dot wait one, console dot log listed and cool. And we can try this out by running yarn hardhat node, which is going to run through our deploy scripts, right, it's going to run to these deployed scripts here. And then in a new terminal, we'll run our script, yarn hard hat, run scripts meant and list dash dash network localhost. And we missed an argument, oh, we need a price a
s well to list our entity. So we'll create a constant price equals and we'll say ethers dot utils dot parse, ether 0.1. And we'll pass the price and to the list item. So oops, and sorry, it's not the marketplace that we're listing, the basic NF t that we're listing, of course, so run that again. And Bada bing, bada boom, got some listed events. And we can see here, we're doing some listing and awesome. So now we have a script. Alright, so now that we have a script, and we're going to be writing
a couple other scripts a little bit later, we essentially have a really solid repo here are our totally decentralized, NFT marketplace, this is absolutely massive, and you should be incredibly, incredibly proud of yourself. Now, of course, this is all code. And people can interact with this, if they're software developers, which is great. But we're going to want to allow anybody to be able to interact and list their own NF t's on our marketplace. So what are we going to do? Well, we're going to
want to build a front end for this. And now we're gonna get into the second part of this lesson. So on lesson 15, we just finished the backend. Now we're gonna move on to the front end, we're gonna start with this morass code. The code for both of these is pretty much nearly identical. But we're going to start with Morales, and we're going to teach you how to do both of these. And we're going to teach you the difference between the Morales and the MoGraph. And kind of why we're even using them i
n the first place, we're going to start with Morales. So if you want to follow along with this next section, all the code we're going to be working with, is going to be in here. So you excited, I hope you are because this is going to be a phenomenal session, we are about to build one of the most sophisticated front ends that we can using the tools that we have. And like I said, we showed you a little bit earlier what this is going to look like. So let's do a quick refresher here. So here's what
our front end is going to look like. But what we can do is we can connect with our little connect button, we hit Metamask Metamask pops up, we'll go ahead and connect. And now that we're connected, we can see the different NF T's in here. And if we're on an address that's owned by us, it will say owned by you. And if we switch addresses, are you I will go ahead and update, connect there. And now we're owned by a different address. Now if it's owned by us, we get this little hover that says Updat
e listing. And right now it's worth 0.18. That's what it's listed for on our marketplace. If it's owned by us, and we click it, we can update it to a different price. Let's update it to 50 eath, or whatever your layer one currency is, we'll just save new listing price. We'll go ahead and confirm. And I'll say the listing updated, please refresh, what we can do them. And we'll mine some blocks on the back end, and boom, now we see that it's worth 50 here. Now if we switch to a different account,
now we can see owned by Baba blah, and the hovered now says by me enough is selected as a different user, I'm going to get this transaction to actually buy it. Now go ahead and confirm that I'm going to buy it, I get a little pop up. This is item bought successfully. Now if I do a little refresh, we'll now see that that NFT is gone from the marketplace since we bought it right and it's no longer available to be sold. Now what we can do then is we can come over to sell NF tees. And at the bottom,
we'll see a withdraw proceeds. So whenever somebody buys an NF T, the NFT marketplace actually keeps the proceeds that actually keeps the result of the sale. So if we switch back to our address that had the NFT listed, we can now see Withdraw 50 proceeds because we know that we have 50 eath, because we just bought that for 50. So if we hit withdraw, Metamask is going to pop up, we can go ahead and confirm, wait a little bit as transaction populates, and boom once it goes through, and we'll see
now we have zero proceeds. Right? We withdrew everything from here. So what we can do now is we can relist that NFT. So if we come back, go back to the one who just bought that at a T if we know the address and the token ID of the NF t and we own it, we can go ahead and relisted you're gonna place the address in here with the token Id give it some sort of price. We'll submit we'll approve giving the NFT marketplace access to our or NFT, to our little doggie. And then we'll go ahead and actually
send the transaction to actually list the NFT on a marketplace that we get NF T listed successfully. After we move some blocks in the backend, we can go back to the front end. And we now see, it's owned by us, instead of the original owner, right and set for 10 ether. And then we can of course, switch back to a different user, and we can have them actually buy. Alright, so now that we have the contracts, we know what this looks like on the contract side. So now let's figure out how to do this on
the front end side. So let's jump into our code editor. And begin if we're on our hard hat and my NFT marketplace Free Code Camp folder. That's great. But we're going to create another folder, we're going to CD down and directory. And we're going to make a new directory. I'm going to call it next Jas and if T marketplace dash FCC. Now you can do next Jas marketplace dash mirallas FCC if you want. Again, we're starting with mirallas CD next Jas NFT marketplace FCC. So now that we have this folde
r, will do code dot will open up a new VS code, or you can do File Open folder and open this new folder. And we can begin working in this new folder in here. Now that we're in our new project, we're in our new folder, we're gonna do exactly what we've done before. Yarn create next app, period. Okay, we've done our setup here. Now, I don't like es lint. So once again, I'm just going to go ahead and delete that. And what we're going to add in instead is our prettier stuff. So prettier, ignore pret
tier RC. Again, some people may strongly disagree with me on that, but to each their own right, this is what I like to do. So this is what I'm going to do. Now we have a minimalistic react project, right? If we run yarn Dev, we open up our UI on that site, copy this, or Command, click it. Tada. Welcome to next. Jas Yeah, we've got an x js application. As we know, we go to pages, we go to index.js. Let's delete everything in here. Bom will leave the stuff and head if it comes with stuff and head
will write Hi, exclamation mark. We'll save we'll come back. And now we see Hi. And I'll zoom in a whole bunch. Boom. So now we have some minimalistic reacts minimalistic next, Jas. Now, I know we already started the project here. But let's jump to the readme that's given to us. And let's talk about how we want to do this what we want this to actually look like. Well, we're going to want to make a homepage. And in this homepage, we'll say we'll have it show recently listed, NF T's homepage will
show recently listed entities that will say if you own the NFT, you can update the listing. If not, you can buy the listing. So we'll have that. And then we'll have a sell page. And in this page, you can list your NFT on the marketplace. So these are going to be our two main pages, we're gonna have a homepage and a sell page. Now we're going to have a ton of components, but we're really only going to have two main pages. So if we go back over to Pages, right, right now we have our apps dot j s,
which serves our app, which is cool, which everything runs through. And then we have our homepage. Let's also create right now, our sell page or selling of T dot j s. And then in here, we'll just make this really minimal, that we can copy most of what's in here, we can actually just copy paste this whole thing, paste it in here. And instead of high, we'll say sell page. We'll save that. Now if we go to our localhost do debt slash sell. And if T oops, we gotta run. Run the front end again. With y
arn Dev. Sorry, we'll run yarn dev again. Now we refresh. And now we can see sell page. So sell pages that slash sell page, and then home is just going to be high. Okay, cool. So we have our two pages. Which one should we work on first? Well, let's work on our homepage. So we're going to be in our index.js. I'm going to keep this front end bit running, we're going to hide it oops, that's the opposite of hiding it, push it down, we're going to hide it like that. And let's go ahead and let's start
building this. So we see in our index js, we have some head stuff here, I'm going to change this to NFT. Marketplace. Description is going to be just an empty marketplace. Like so Fabcon looks great. Now if we do a little refresh, now it says NFT marketplace up at the top here, which is good. That's what we want. Well in our index page, what's one of the first things that we're always going to need to do? You guessed it, we're going to need a little connect button right? We're going to need our
users to be able to connect to to web three to connect to a blockchain. So same as we've done before. Let's go ahead let's create a components folder. And we'll create a header component component Nance folder and we'll create a new file The header digests. Now remember, since we've done this before, with our front end lottery code, we can always refer back to the lottery code as well when we're building this, okay. And of course, we have all of the code for this on the GitHub repo. So you can
use that to what I'm not going to have you all do is last time, we did that manual header thing, right, where we had to do all the local storage and do all that crazy stuff, we're not going to do that. This time, we're going to just do it the easy way, we're going to just use the web three UI kit. So to use this connect button, we're going to do yarn, add. And we're not going to do dash dash Dev, because this connect button is a necessary component for the front end, yarn add web through UI Kit.
This also means we're going to do Morales and react mirallas. I said, and this is where it might be a little confusing. I know I said in here that we have both a Morales and other graph edition. So we're still going to use the Morales package in both of them. The only difference is we're going to use a Morales server as well in our Morales edition. And we're not going to use a morale server on our the graph edition, they're both can use the Morales package because all the open source hooks and
tools are still incredibly powerful, even if we don't use the Morales server. So we're still going to use the Morales package even when we're going to be using the graph. Great. So now that we've added those all, we're going to do exactly what we did before on our last next Jas process. So in order to use our web through UI component in our app, dot j, s, and do import mirallas provider quotes and without sorry, and curly brace, it's from react mirallas like that. And then we're going to wrap ou
r whole component thing in a morass provider. So we're gonna do return, little open parentheses, close parentheses here. We're gonna do rounds provider. And then we're gonna do in if she allies on Mount is going to equal false, because we're not going to use the server yet, or else provider. Okay, cool. Now that we've wrapped our app in a Morales provider, and go back to our header, we're gonna say Export default function header, we're going to grab our Connect button from what through your eye
kit. So we'll do import connect button from web three UI kits. And then in here, we're just gonna say return. The next button. Now what we can do back in our app, J. S, is we can do import, import, do header from dot dot slash components header, and we have our header, we'll just put our header right above the component. And we're going to add some stuff to the header in a bit. Let's just make sure that we're importing the header correctly. Let's go back to our UI here. And okay, boom, we have o
ur connects button. If we click it, you know, we'll get this little pop up. And I'm way zoomed in. So I'm going to anway zoom in. Now, what else do we want to put in our header? Well, we're probably going to want to like give this like a name and make this look a little bit nicer, probably going to want to a link as well to our cell NF T page. So let's create a navbar. So instead of just returning the connect button, put this in parenthesis and we'll have a return some other stuff too. So we can
use this nav tag, which usually defines like a nav bar. So it's really similar to a div, it's just another tag. Right, so now we'll put everything into this nav tag. And in next Jas, we can actually make links using the next Jas link tag. So what we can do in this is link allows us to basically connect to different links or URLs in our application, like so. So we can do import link from next slash link. And in here, let's say if we want it to go to the homepage, we can make a link. And we'll sa
y h ref equals slash equals slash. And inside of this, we would wrap this in an a tag to make it clickable. And then we could just say something like NFT marketplace. Now if we save that, we go to our front end, we now we see have a NFT marketplace button that we can click and since we're already at home, we're not going to go anywhere. But if we copy this link section, paste it below, and we make another one for cell and f t. And we title this cell NF t. Now we save we go back to our front end,
we now have NFT marketplace and sell NFT if I click sell NF t we now get to the sell page right we'll go back to the homepage sell page flip back and forth. Awesome, very exciting. So now we have have an incredibly minimalistic header obviously looks terrible. So let's do just a little bit of formatting. And oftentimes you'll do the formatting last. But while we're here, we might as well do our formatting we're going to use what if you guessed tailwind? You guessed correctly. So remember, tailw
ind with. Next. Jas, you can always just follow along here. And we'll grab, we'll do the exact same thing we did before we'll do yarn, add dash dash Dev, that stuff right there. And then we'll run a knit after these finished installing. So we'll do yarn, and then paste that in. And there we go. So now we've got our post CSS config, we've got our tailwind config. We're going to grab tailwind.config.js. Paste it in here. And then we're going to grab Global's dot css and open up Global's dot css, p
aste that in there, and cool. Now we have tailwind in here. Now that we have tailwind, we can do some tailwind stuff to our header here. Let's let's create a div for all of these for everything here, we'll create a little div for all the stuff here, we'll make like a big section for almost like a big sign saying, Hey, you're at the NFC marketplace, h1, which stands for header one, and we'll give it a class name of padding y of form. Padding x of four, we'll do font bold text will be three XL, an
d then it'll just say NFT marketplace. Now we have this NFT marketplace, which is nice bolt. Awesome. If you're on your server you're going to kill it's going to kill it with Ctrl C, and then we're going to restart it. And that's going to pull in all the tailwind stuff. And now if we refresh our local main, we should now see okay, and if T and F c, r gets place, right, we now see this and big and bold, which looks a lot better. So let's keep going. Let's give our whole nav a class name. Equals w
e'll give it padding of five, border bottom to flex flex row justify just if between n items center. We'll see how that looks. Haha, looks a lot better. We're now kind of like setting this up with a bottom border kind of stick and some stuff like this, that looks much much nicer already. Let's go down here. Let's make our buttons have a class name equals lax lax row items center. And like I said, this is not a styling class. So we're not really going to go over exactly how we're styling this. An
d that is okay. But that's going to move that over make that look a little nicer. We'll give our link here, a class name equals Mr. For P six. And we'll give both of these the same class name both these links, give them some padding, so they moved away from each other some margin to the right, so they're away from each other. And oh, I forgot to do this Morales off equals false. We need Morales auth equals false so that we don't automatically connect to a Morales database or try to connect to Mo
rales database, when we connect, we want to just connect with our Metamask. And we'll change this to home instead of the marketplace. But otherwise, that looks pretty good home selling of T Connect button. And we can adjust the formatting of this to make it look a little different. But I think for the most part, this looks much better, right? Alright, cool, much, much better looking header. Here, we have our app.js setup with the mouse provider headers components. Let's now move on to our index.
Let's now move on to showing these NF T's showing all the NF T's in our marketplace. And here's where it's going to already start to heat up and get really interesting. And actually one more thing, we're going to grab this headpiece in the index if you haven't. And we're just going to have it be in the app JSX. So yeah, and our app.js we're going to put that header up at the top, and just put a little, little div, Div. div, like so wrapping around this whole thing. This goes here. And this way,
no matter what page we're on, we're always going to have this as our header. And we don't have to define it each one of our little our things here. So we'll do a refresh. And it says head is not defined. Sorry, that's because we're going to need to copy import head from next slash head. Paste it into our app that Jas import head from next head. And now we can see we're going to empty marketplace no matter what page we're on, because we're defining it at our app level. We have the header in here
, we have this stuff in here, index almost has nothing in it now. Let's do this. So what do we want to do? We want the homepage aka our index to show recently listed NFT. So the question is, how do we show the recently listed NF Ts. How do we do that? Well, let's go back to our contract. We go back to our hard hat NFT marketplace So we're looking at at the marketplace, what do we have in here? How do we actually see where NFT is stored? Well, they're stored in this listings mapping. However, how
do we see all of the listings that are in here? Well, this is a mapping, which means we have every single address on the planet in here, we can't loop through the mapping, we'd have to loop through every single address on the planet, which is some insanely large number that you and I could never fathom how many addresses there are. So what are some solutions that we can take to this problem, right? Because we're obviously not going to loop through everything. So what do we do? What's what's kin
d of the first approach, one of the first approaches would be like, alright, Patrick, well, why don't we just create an array, an array of listings instead, and this might be a good approach. But what if then later on, we also want to get some other weird data, maybe we want to get all the NF t's a user owns NF t's a user owns, there's no array of NF T's that a user owns. Again, that's just a mapping. But what if we want to query some other weird data, or query some other weird data, or what if
an array will be very gas expensive, which it is, if we make this an array to loop through, it'll be incredibly gas expensive. So we don't want to have to go back and change. So I'm going to I'm going to type this out. Because this is important. We don't want to change our protocol for just the website, we don't want to change our protocol for just the website, or we don't want to much change our protocol for the website. Because if we were to make this an array, it would become incredibly gas i
nefficient. And it would become much harder to use this NFT marketplace because it would be so much more expensive. And as you build more and more complex protocols, you're going to realize that having an array for every single mapping you have isn't feasible. This is one of the reasons where these events come into play. So every single time we list an NF t, we call this list item function. And we omit item listed, this item listed event is stored in a data structure that's still on chain, but j
ust smart contracts can access it. However, guess what can't access it off chain services can access these events. So what we do in this case, is what we're going to do is we will index the events off chain and then read from our database. So what we're literally going to do is we're going to set up a server to listen for those events to be fired, fired. And we will add them to a database to query. So yes, we're literally going to take every single time an item is listed, we're going to index it
in a database for ourself. And then we're going to call our centralized database to start and we're going to call that database to do that. Now the question then becomes Whoa, isn't that centralized? Hey, Patrick, we're talking isn't that centralized? What the Hickety heck, and the answer to that is, it's not necessarily. So the graph is a protocol that does exactly this. It's a protocol that indexes events off chain, and sticks them into this the Graph Protocol. And it does it in a decentraliz
ed way, Morales, the way we're going to show you first does it in a centralized way, Morales is going to do it in a centralized way, which might be the route that you want to go for speed for extra bells and whistles, so that you can do local development, which is what we're going to be focusing on here, or any of the other functionality that Morales comes with. Because Morales does a lot more than just that. That's something to keep in mind too, is even though we are adding a centralized compon
ent, or logic, our smart contracts, the real bulk of this application is decentralized. And you can verify all your interactions are working with this decentralized smart contract, we've actually been using a lot of protocols that are centralized, like ether scan, like open see, and some of these centralized protocols are really important to this space. So we're showing you Morales to get you familiar with working with one of these centralized servers, in case you optionally want to make an appl
ication that provides a centralized service. And there's a ton of tools in the space like opens up and defender tenderly and more, that are centralized, but give us massive, massive benefits. We as a community are bringing more and more things to being decentralized. And sometimes we need some training wheels to get there. And then the graph is going to be the decentralized way, which is a bit of a longer process to go main net, but we'll explain all that when we get there. Let's learn how we ca
n list the most recently listed NF T's and Morales in the graph. Both have some really solid videos, I'm going to leave some links in the GitHub repo associated with this. So if you want to learn more, you should definitely watch both of those because they are absolutely fantastic and will help you understand this event stuff better. So normally, when we read from the blockchain, we do something like contract dot get, get listing, you know, and then we put it whatever our input parameters are. C
ontract double blah, so instead, so we're going to read from a database that houses All the mappings and an easier to read data structure. Both Morales and the graph do this. We've been using the morass, open source packages and tools. However, Morales also comes optionally with a server back end to give your web three applications more functionality. However, there's a ton of stuff that we're not going to cover that Morales can do to help build your web three applications. So instead of me cont
inuing to talk about Morales, and what it can do, we have Ivan here to give a brief overview of some of the other things that Morales can do take it away, and my name is Ivan, I'm from rallis. And I'm here to tell you how you can speed up your development by 10 times and I'm not over exaggerating, when you're building something, you want to ensure that is scalable, because your DAP may go global, it may get viral, it may go mainstream, it can happen. And if it happens, you don't want to start fr
om scratch, you want to use tools and services that allow you to go fast, and also to go big. And that's exactly what mirallas provides. At mirallas. We create tools, we create infrastructure for developers in a way that you have a single workflow, and they will soon explain what it means because this is what saves you time. If you have a single workflow for doing things. And workflow in web three really means that you have to have a smart contract, whether it's a token, the game, some kind of s
taking some kind of marketplace, some kind of defy, it will be on chain, but at the same time, you have to connect it to your back end. Because when something happens on chain, you need to monitor that. So you can create web hooks, you can create email, you can create a push notification, you can run some custom code, you can run some calculation, you can save something to the database, everything on chain at the end of the day needs to go into our back end. And when something is in your back en
d, it needs to go to the front end. So for example, you change the UI when something happens on chain or you change the UI. If your user receives a transfer there is above a specific threshold. Or if your user has this NFC, you can allow them access into some kind of chat or some kind of exclusive piece of content. So at Morales, we provide you with a full stack suite of tools that is used by over 100,000 developers, it's really becoming one of the most adopted tech stacks in web three. And it a
ll starts with Morales identity, which ensures that you get one piece of code, you write one piece of code and you can log in your users across different blockchains across different wallets. And in your morale is dashboard, you will get the user profile, and you will get a web session. So mirallas allows you to manage identities because a user profile can have many different wallets from many different chains connected to it. And all of the transactions will be synced from that user, all the re
al time transactions will be synced about that user. And also, you have established web session between your front end whether it is a game, whether it is a web website, we ensure that you have secure authenticated web sessions, and we provide you with session management. So in case you have your own bike, and then you have mirallas session identity management, you can invalidate sessions, you can log in users and do all of that great, all of these great things with one line of code. That's very
important. Number two is Morales real time I already mentioned a bit of it. But basically when you have a user, you know exactly what's going on in real time. You can run custom code, whenever a user does a transaction, you can run custom code or do a web hook or email or push notification whenever a user interacts with a smart contracts or when a smart contract simply emits an event. This can be an trade in an NFC marketplace, this can be ERC 20 transfer, you can be very flexible by setting fi
lters. So you can say only give me alerts only give me web hooks when the user transfers more than 10 NFCs. Or when this token transfer is above $1,000, and so on so forth. This is morale is real time very, very powerful things. Next are mirallas SDKs. So whether you're building a website, whether you're building a game where full integration with game engines, whether you're building for some other platform, we have extensive SDKs that are easy to use that allow you to do all of this that allow
you to connect to Morales and do this very, very easily. And if you go to our documentation, which I highly recommend you to do, you go to Morales, Doc's dot morales.io, if you go to Doc's dot, Marisa Yo, you will first and foremost understand what mirallas is in depth. So you can think of it kind of like Firebase, but for crypto, basically, it's a managed backend, that you can connect your front end. Also, you can connect it to your own back end using no GS SDK, it's very, very easy. But what
I wanted to show you here is cross platform. So for each thing we have, let's say you want to get nfts for your user, we'll show you how to do it in simple JavaScript, vanilla JavaScript, how to do it and react, how to do it using a web request. Let's say that you just want to use a raw web request. Let's say you're using some kind of language that we don't have SDK for you still can use Morales just that you have to call the raw HTTP request. And we'll also show you how to do it in Unity using
C sharp in Unity game engine. So we're very, very clear cross platform. And we are cross chain. So this means for example, when you log in the user, you can create the user profile where you have the lambda address, let's say your user uses Solana then they can easily connect Aetherium, they can easily connect Binus chain, the end, we're gonna add more chain soon, they can easily connect L Ron, to one user profile. And then you have all kinds of different wallets, different chains, and you have
one single user profile one single user ID. This is, by the way, how it will look like in your database. As you can see, you're going to have a user user table right here, you're going to have all of their accounts. So in this case, I only have eath. But if I have Solana, if I have other types of blockchains, it will all be right here. And this is a database that also has all my transactions. This is a database where I can set up different listen events or smart contracts. So for example, open s
ee I can watch open see smart contracts or something else. And it's very, very variable, because this is MongoDB. This is MongoDB, you can run MongoDB queries, it's very, very variable. So in that sense, mirallas gives gives you a nice, nice dashboard with everything you need to know about your users, their sessions, their permissions, and so on, so forth. And of course, you can connect to your own back end using the Node js SDK. So this is Morales SDKs. And finally, when we're speaking about th
e workflow, the final thing is the API's, which I also already showed you, but the API is that you can do RAW requests from any programming language from any kind of architecture. So using this workflow, you can easily achieve anything you want very, very quickly. You really have to try Morales it is it will change your life. I can explain here all I want, I have limited time. But as you can already see, by this presentation, you're very curious, as you already can see, by this presentation, you
want to try this as you already feel by watching me here, you are very, very excited. We have to get your hands dirty. So go, number one, two dogs, authorize the sale, and go here getting started connector SDK in vanilla or react and go through all of this. See the magic for yourself. And if you want practicalities, go to youtube channel and go to morality Oh, slash projects, guys, you all in the community. Using Morales, you will succeed using rallies, you will achieve your goal. And you're go
ing to do sooner than you expect yourself. You're gonna surprise yourself. But don't let yourself down. Go to morales.io sign up, get started, you guys. Now that I've explained all of that, what does this look like? Well, this is where we're actually going to start using mirallas with its server capabilities. And we're going to sign up for a server here. And we're going to use Morales as our back end for our application. So to get set up with Morales, we go to morales.io. We can go ahead and sig
n up for free. We'll put our email in, we'll create some password. Why are you here? Other please specify Patrick's amazing hardhat video, you don't have to write that. But if you want to write that you can. What did you hear about Morales for the first time? Well, you all heard about it on YouTube, because you heard it from me, and then pick your roll, I'm going to be a developer, we'll hit next, I don't want to subscribe. But I'm going to not be a robot and create your account. And it even giv
es us a little property or create your first server. So our back end is going to use a server to do any stuff on the back. So we'll create a server. And if we were going to do a main net or a testament, we choose one of those. But for now we're going to do a local dev chain server. And again, this is one of the advantages of Morales is it allows us to work with our local dev chain. For indexing events, we can actually index our events from our local hard hat node, which is incredibly, incredibly
powerful here, so check your email, and we'll have an activate my account thing, email, we'll hit activate your account. And it'll bring us back here and we'll recreate and we'll do local dev chain. Alright, so now we're going to create a new local dev chain server. So we're going to call this NFT marketplace, we're going to select the region, whatever region you want, I'm in the eastern United States. So I'm going to choose New York. But whatever location works for you, we're gonna do local de
v chain, and we're going to do eath, local dev chain. And again, if you're building for polygon, if you're building for avalanche, if you're building for Phantom, if you're building for any of these EVM compatible chains, again, your eath local dev chain, it's going to work exactly the same. So we're going to add instance now. And we're going to create a new application here. So we're going to close now we have the server here, and it says ganache, but it's really hard hat. Don't worry about tha
t. Now that we have our server up, we can go to the Morales documentation, what we're looking for is events, we're looking to sync with events. So we can even do a little search in here for events. And we see smart contract events platform Automatic Sync, and even tells us a little bit more about why do we need to sync and watch smart contract events. So basically, this server our database is going to be looking for these events to be emitted. But before we can do that, we need to hook up our ap
plication to our server and if you go to the React Morales GitHub right at the top And you'll probably see saw this before, when you have this Morales provider in their docks, they actually pass an app ID and a server URL. And this is how we can actually connect directly to our servers on mirallas. So what we're gonna do is right, now we're gonna go back to our app that Jas and originally we've been saying initialize on Mount equals false. When we say this, we're saying, Hey, we're not going to
use a morale server, we're just going to use the open source morass tools that y'all provide. Now, we actually do want to use their server, right, we do want to use all these bells and whistles that Morales comes with out of the box. So we're going to change that. So instead of saying initialize on Mount equals false, we're just getting ready with the app ID and the server URL. So we're going to delete this. And just like it says, in the documentation, we're gonna give it an app ID and a server
URL. So we're gonna say app ID equals, and this is where as a string, we'll put our app ID. So if we go back to our Morales database, we can go to view details. And we see all this information in here. And we can grab our application ID, we can copy it, paste it in here. And then we'll want to grab our server URL, which is at the top. So this is the URL of our unique custom morale server. So we'll say server, URL equals and then paste that in there like that. Now, if you've been following along
with these tutorials, you might be thinking oh, we're we're kind of just hard coding that stuff right in there like that, how that seems kind of that seems kind of bad. Well, if that's your intuition, that is fantastic. So instead, we're actually going to put these into environment variables. So we're going to create a new file, a dot env file. And this is where we're going to put all of our environment variables. Now next, Jas comes with built in support for environment variables, which allow y
ou to do the following use dot env, dot local to load environment variables or those environment variables to the browser by prefixing. It with next underscore public. So there's a couple of different environment variable paths we can use. We can do dot env, dot local, we can do dot env, dot this dot that that the other thing, we're just going to do dot env, to keep it simple here. But in order for our front ends, to read environment variables from our dot env file, we have to do next underscore
public underscore, and next Jas will look into our dot env file for variables that start with this and only stick these environment variables into our application. If we were to just do like Morales server equals blah, blah, blah, it has no idea what this is because we need to do next underscore public underscore. And if we do that, and we'll do a console dot log, look here, process dot env. Next public morale server and we actually need to kill it and restart it. And then we go back, we do a l
ittle refresh here, it'll say Look here as a do bla bla bla, because that's what is in the dot env file with that next public. So we'll grab our app ID, we'll copy it. And then our dot env will do next public app ID equals and we'll paste that in there. We'll grab our server URL, we'll go back to here. We'll do next public server URL equals, we'll paste that like that. And now at the top, we'll say const. App ID equals process dot E and V dot next, public app ID. And then we'll say const. Server
URL equals process dot E and V dot next public server URL. Now that we've had these variables, we'll stick them in like this. So this is how we can connect our application to our morale server. Now, of course, we haven't done anything yet. But we're getting started, right? This is how we're going to connect to it. Now that we've signed in, well, I told you that our morale server was going to be indexing our events. And if you go to this Dashboard button, this is our entire database. Everything
in this browser tab is what's in our database right now. And as you can see, right now, there's not a whole lot of anything, if we had any events data in here, it would be in here. So we need to tell our server, hey, you need to start listening for events. So we can show the most recently listed entities. So morale server, you need to start listening, you need to create a database entry for every single one of these item listed events. And whenever somebody buys an item, right, whenever somebody
buys that item, or cancels an item, you need to remove that from your database. How do we start telling Morales to start listening to our events? Well, first off, well, first off, we're gonna need to connect it back to to our blockchain. And then we're going to say, which contract which events and what to do when it hears those events. So we need to connect it and then we need to tell it what to do when it hears those events. So how do we connect our mirallas server to our hard hat blockchain?
And right now, we're not running one. But let's go ahead and we'll start up our hard hat, our local host blockchain. So in one terminal, we're running the front end and another terminal will see the download directory. We'll cd into our hard hat NFT marketplace dot Free Code Camp or Free Code Camp, and we'll do yarn hard hat node. And if we've done everything correctly, it'll deploy our NFT marketplace. It'll deploy our Basic NFT and then it'll start local HTTP web socket at blah, blah, blah. So
that's good. So now that we have that Node running, what we can do is we can go to view details, and go to dev chain proxy server. So this dev chain proxy server is going to be how we actually tell Morales to listen to our locally running hard hat node. Now, to do this, what you're going to need to do is we're going to need to download this what's called a reverse proxy. And I have a link to this in the GitHub as well, depending on what computer you're running on will tell you which one of thes
e we actually need to download. And then there's some troubleshooting tips down here if you ever get lost, and if you're really, really confused, what we can do what Morales FRP to download, do a quick search on this. We even come right to the documentation, connecting ganache to Morales note for Mac users download FRP dot Darwin dot bla bla bla for the nosh proxy server. So I'm on a Mac. So I'm going to download this Darwin AMD 64. And for look at the releases, that's the first one at the top,
Darwin AMD 64. So this is the one that I'm going to go ahead and download. I'm gonna click it, I'm going to download it. Once I have it downloaded, we're going to open it up, and we're gonna get a folder and we're gonna get a folder that looks like this. The main things that we need are going to be f RP and FRP C dot ini. F RPC is going to be the executable it's going to be what we're going to run to connect our blockchain node to Morales, and F RPC dot ini is going to be basically the config fi
le to do this. Now, again, this is one of the sections where downloading this is going to be one of the hardest steps here. So if you get lost, please ask questions in the GitHub, please ask questions in the Morales forum, there is a Morales forum as well, where you can ask a ton of different questions. And please check out the troubleshooting as well. But what I'm going to do is I'm going to create a new folder in here new folder called F R P. And I'm doing it in here just to make it a little e
asier. But you could really put this wherever you want, and then always refer back to it. And what I'm going to do is I'm going to take I'm going to copy these two files, and place it into this FRP folder. So now I have FRP C, and F RPC that ini if you click on the F RPC, it's going to be like, hey, it's binary, you can't really look at this, don't click that, it'll just be a whole bunch of nonsense, but the F RPC dot ini looks like a pretty typical config file. And this is what we're going to a
djust. If we even go back to our morale server, it'll give you what you need down here. And we're using hard hat. So we're going to copy everything here. We're gonna go back to our F RPC dot ini, and then just paste whatever is in there in here. And that's how we're going to tell this F RPC thing that we need to connect. I haven't tried this out for users using WsL. So if you're using WsL, let us know in the full blockchain solidity course, Jas, make a new discussion, if you haven't seen it alre
ady, saying, Hey, I'm using WsL for the F RPC. And here's what you need to use. And then at the bottom, it says, run and enjoy. I'm running on a Mac OS, which runs Linux commands, so I can just copy this, I'll create a new terminal. And what I'm going to do is I'm going to cd into that FRP folder. And I'm going to paste that thing that I just that I just copied from Ross. So we're running that F RPC executable dash c, which is dash config, F RPC dot ini. If I hit Enter, it's gonna say log into s
erver success, get run ID, blah, blah, server, UDP port, and then a whole bunch of other stuff. If you're seeing success stuff here, that means you did it right. And you can hit CTRL C to cancel because we're not going to keep running it. Now, if you want to just run this, you absolutely can. But I'm going to show you another way to do this. And this is using the Morales admin CLI. So everything that we're doing here, all these buttons that we're pressing, Morales actually comes with this thing
called the Morales admin CLI or the command line interface. So this is a way for us to connect and run all these buttons and stuff that we're pressing right from our terminal and right from our shell. So I'm going to show you a couple of commands on how to work with the admin CLI. And we're going to be working with a lot of admin CLI commands. But all we're going to do is npm install dash g Morales, admin CLI or for us yarn Global Add. So we're going to grab that will do yarn, Global Add routes,
admin CLI like that. And now we should be able to run Morales admin CLI and see a whole bunch of stuff like that. And if you ran routes, admin CLI, we have all this stuff. And one of the big ones, one of the important ones that we're going to be working with is this connect local dev chain. So running this F RPC dash c dash f RPC ini. That's going to be the same as running this connect local dev chain. Now what I like to do is jump into our package dot JSON. And we'll create an additional scrip
t in here for us to just run yarn, whatever the name is that we want, and just to do that, and just to make it a lot easier for us to connect our local dev chain so underneath lint, I'm going to do a calm Ma'am, I'm going to create a new command. I'm gonna say Morales sync. And we're going to run the Morales admin CLI version of this f RPC dash c thing. So what we're going to do in here is we're going to say mirallas admin CLI, connect local dev chain, dash dash chain, hard hat, dash dash mirall
as. Capital sub domain. This is where we're going to put the subdomain of a morale server, which if we go to, we go back to our routes, admin data servers, we can go back to server details. So it's going to be not the HTTPS, it's just going to be from here all the way to the.com. So not even the port, we're going to grab that we're going to paste that there. And then we're going to do space dash dash f RPC path is going to be dot slash F RPC, slash FRP slash F RPC. Now if we save this, and we ru
n it, it's not going to work though. So if I run yarn with our new script, Morales sync, it's gonna say specify Morales API key, it's going to give us this prompt. And in our dashboard, we have our API key, which we can copy, we can paste it, and then API secret, we can copy and then paste it. And then we'll say starting connection to hard hat, which is great. But that's really annoying. And I don't want to have to do that. So we're going to Ctrl C, we're going to kill that. And what we can do i
s we can go into our dot env. And we can actually add those as environment variables that Morales is expecting. So when we run this Morales admin CLI, it'll check our dot env file for Morales API key, which we can copy right here. And then Morales API secret, which we can copy, and paste right here. Now, the reason that these aren't capital and doing next public, these are not going to be part of our front end piece. These are keys that we're using on the back end to test and for our local dev c
hain connection. So we don't need to do next public, we're just going to leave it like this. But now if I hit up and run yarn Morales sync, again, it's not going to prompt me this time, it's just gonna say starting connection to hard hat. And if you see this, this starting connection to hard hat bit, we can come back to our servers, we'll go to dev chain proxy servers, we'll hit this disconnected button and refresh. And if you see connected, you've successfully connected our heart add node, whic
h is running here to our Morales server, which is awesome. And in fact, if you sit on your heart had no terminal, you'll see the actual RPC calls to our blockchain here. And you'll see Morales is consistently calling f block number to make sure it's up to date with what it has. So how do we tell a morale server to start listening for events? Well, there are two ways we can do this. The first way is with the user interface. So we can go to view details, we'll go to sync. And right now it says no
sync services installed. So we'll hit Add a new sync. And we can see sync and watch address and sync and watch contract events, we can watch the address for transactions or we can watch some address for any events. And we can manually add all our information here, you can select the chain description, decide if we want to optionally sync historical, we could put the topic of the event, the ABI of the event, the address of the event filter, and then a table name. Or we could do all this programma
tically, which is what we're going to do, we'll create a little script that we can run, tell our morale server to watch for those scripts. And we'll see our database get upgraded to listen for those events. So back in our code, we're going to create a new file called add events that Jas now we have one terminal that's running our front end one terminal that's running our blockchain one terminal that syncing our blockchain with morass. And now we're going to do another terminal. For anything else
we want to do like run little scripts become the Morales docks, and you click connect with SDK, there's a ton of different ways we can actually connect with the SDK, we've already learned how to connect with react by using React Morales. Now we're going to connect with no JS since we're going to run a little Morales script. And here's like a little example of what it looks like in the documentation. But I'm gonna go ahead, so I'm gonna say const Morales, equals require oralis slash node. And we
're going to import the node extension of the Morales package into our script here, we're going to require dot env dot config, which means we're going to need to install dot env yarn add dash dash dev dot env. And now we have to tell our morale server all the same information that we would need to tell it on the user interface. So one of the first things that we're going to need is the address of our contract. We're gonna need to say const contract address equals and this is where we go oh, well
, how do we how do we get that contract address? The easy way to do this is we just go back where we're running the blockchain And we'd grab where that NFC marketplace is deployed. And similar to our smart contract lottery where we created an update front end script, we're gonna do the exact same thing here. So back in our heart hat, NFT marketplace, and if T code, we go to our deploy script or deploy folder, we're gonna create a new file called 99 Dash update, front end dot j s, and we're gonna
create a little bit of our deploy process that will automatically update our front end. So we can just grab the network address from a file that is programmatically created. So we're gonna do module dot exports equals async function. And now we'll say if process dot EMV that update front end, then console dot log, updating front end so that in our dot EMV, we have update front end equals true. And that will be how we decide whether or not we actually want to update the front end. And then we'll
create a function called up date contract addresses, which we will await. And this will update the contract addresses of our front end. So let's make that function. Do async function update contract addresses, make sure those are spelled the same. So we'll say const NFT, market place equals await ethers dot get contract. And then yes, we need to import const ethers equals require hardhat, we'll grab the NFT market place. And then we're going to want to write our files in here to someplace in ou
r front end code for us, we're going to do in a new folder constants. And we're going to create a new file in here called network mapping dot JSON. And we'll have this just be a JSON object which keeps track of all of our deployments. So if we deploy something to rink V chain will keep a list will keep a list of it will say NFT marketplace will keep a list of all the addresses of the IoT marketplace, comma basic NF T, right, and then I list of all those right now we don't have anything deployed.
So we'll just have it be an empty JSON object. Now back in our deploy script in the hard hat NFT marketplace project, we're going to keep track of that location. So right at the top, we're gonna say const. Front, and contracts file equals, and we'll place where it is according to your file setup. So if I do cd dot dot slash, next JS NFT, marketplace, free code, Camp constants, network mapping dot JSON, this is where mine is. So you're going to want to put it wherever your location is in relatio
n to your heart at Mt marketplace Free Code Camp, it's my front end contract file, it's going to be right here. Now that we have all that we're going to get the chain ID. So we're gonna say const, chain ID equals network dot config dot chain, id.to string. And we're going to need to import network from hard hat as well. And then we're going to want to read from this network mapping file to see what's currently in there. So we'll say const. Contract addresses equals and we're gonna do a JSON dot
parse Fs dot read file sync, front, and front and contracts. File comma UTF, eight. Now here's what we're gonna say, if chain ID is in contract. addresses, let's say if this list of contract addresses doesn't include the marketplace, then added on, we're gonna say if contract addresses of chain ID of the NFT. Marketplace will say dot includes NF T, market, Mar get place dot address, then so we'll say contract address says chain ID NFT marketplace, dot push NFT marketplace dot address else we're
gonna say contract address says of chain ID of NFT marketplace, which is going to be a new entry now equals NFT. Market market place dot address. So now we've updated our contract addresses object and we just need to write it back to the network mapping. So now we're gonna say Fs dot right file sync front and contracts file comma JSON dot string five contract addresses and then at the bottom we'll do module dot exports dot tags equals and we'll say all or front end. Now what we can do is we can
run just this update front end script with yarn hardhat deploy dashed dash, network localhost. And we only want to do this update front end script. So we say dash dash tags front end, and we run this, and I ran into an error FS is not defined, oh, I forgot to do const Fs equals require Fs stride again, cannot set properties of undefined NFT marketplace. Oops. And that's because this line is off instead of this line, sorry. Basically, right now, what it's saying is, it's saying, hey, this NFT mar
ketplace thing doesn't exist. So we need to make it exists. So now we'll say contract addresses of chain ID equals a new entry of NFT marketplace and adds its first parameter, it's going to be NF T, Mark gets placed dot address, like that. Now we can run it, and updating front end looks like it's done. So if we go back to our front end, we now see we have an entry for localhost with NFC marketplace with the address in our network mapping dot JSON. So if you did that correctly, you should get thi
s. If not, if you're having a hard time with that you can, of course, just go ahead and hard coded in but I do highly recommend you do it programmatically, because your life is going to be a lot better. So cool. We have this update front end script that works now, so we can put this back off to the side. And let's keep going. So we now have this network mapping file with contract addresses based off of the chain ID. So what we can do is we can pull that in as well, we'll say const contract, addr
ess says equals require dot slash constants, slash network mapping dot JSON. And now we can get the contract address based off the chain ID. So we'll say chain ID equals process dot E and V dot chain ID, or 31337. So in our data and V, we'll make a new entry called Chain ID. And for now, we'll do 31337. And now we can get the contract address by saying contract address equals contract addresses at the chain ID of n, f t, Mark get place of zero. So we're going to go into that network mapping, go
to the chain, Id go to the NFT marketplace and get the most recently deployed NFT marketplace boom. So now we have the contract address contract address says Excuse me. Now in our add events, we'll create a new function kind of similar to what we're doing, we'll do async function main. And this will be our main function. And then of course, we're going to copy paste that main script thing we've been doing this whole time domain dot then catch blah, blah, blah, we go back to the morass documentat
ion, though, we can see we're going to need to grab our server URL, app ID master key, and then start it up. So we're gonna do the exact same thing. So once again, sorry, before we even get into our main, you can do it in your main function, if you want. We'll say const server URL equals, and we can just grab this once again, from our web. So we'll say process web dot next public Morales server URL, we'll get the app ID equals process Studien v dot next public Morales app ID, and then we'll say
const, master key equals process study v dot master key. So we don't have a master key in here yet. So we'll create a new one called master key. We'll go back to our Morales front end, we'll close out of this, we'll hit View Details. And we'll grab that master key. So we'll copy that, go back to our code editor and paste it in. And now we have a master key in our web as well. We don't want our master key on our front end. So we're not going to put next public like that. Now, the first thing we'r
e going to do in our main function is we're going to do await Morales dot start server URL, app ID and master key as the input parameters for this will do a little console dot log, working with contract address, contract address. Now we're gonna go ahead and add all those same pieces that we see on the UI. So what are the events we want to listen for? Well, if we go back to our code here, so we have our NFT marketplace, where just type in event we have item listed item bought an item cancelled.
So we have three events we want to listen and a Morales, they have this add new events synced from code, which we're basically going to be following. To do this, we need to obviously start and then create our options for the event. We have the chain address topic, abi elimite, table name and sync historical and then we just do Morales dot Cloud dot run, watch cloud event options use master key. And that's pretty much it. So we're going to follow these documents here to do our code. So let's star
t with item listed. Let's create some options for our IDed listed event. So we'll say let item listed options, or we could do const if we want to, but I'm just gonna do let item listed options equals. And first we're gonna need the chain ID, which we have, because we're getting it from Morales. Now the first thing to point out about chain ID is that ralis understands a local chain is 1337. So even if you're on 31337, if you're doing a local development, you got to switch it to 1337. So we're goi
ng to make another variable called Morales chain ID. And we're just going to say, let Morales chain ID equals chain ID equals 31337. Question mark 311337. Otherwise, chain ID but we're saying since Morales understands that any local Dev is going to be 1337, we're going to say if chain ID equals 31337. Then have Morales chain ID equal 1337. Otherwise have an equal whatever whatever our chain ideas and in our dot env we can decide okay, if we want to do rink B, localhost main net, etc. We're gonna
say Okay, chain ID morass will do your Morales chain ID, comma, we'll say what else do we need? We did the chain ID, we're gonna skip description, a sync historical. So hit sync historical allows the node to go back throughout the blockchain, grab all the events ever emitted by that contract. Since this is a very small local blockchain will just say sync historical is true. Like that. Okay, what else do we need? Okay, we need the topic, the topic is going to be your event information. So to get
the topic, go back to our event code, and the topic is just gonna be the name of the event, plus the type of the parameters. So we're gonna go back to our code, we're gonna go back to here, we're gonna say, topic is going to be item listed, and it takes an address, an address, an address, you went to 56, and a UNT 256, address address, you interviewed six, YouTube and six. Those problems seem like that, we also need the API of just the event, which again, we can find we go back to our hard hat
project, we go to artifacts, we go to contracts. And if the marketplace dot soul NFT marketplace dot JSON, our ABI starting from here is going to be the ABI of the whole contract. And we just want that item listed event. So we did Ctrl F, and we found it here. And we're going to grab from right after it says type event, we're going to copy we're going to scroll up to write up to anonymous false, right, so this bit describes the ABI of the event. So we have internal type, address, name, seller ty
pe, address, and if T address token ID price item listed, right, so this is going to be the ABI of our just our item listed event, we can take that and we just stick it in here, hit save, and mine auto format it to get rid of the parentheses. Okay, what else do we need, we have the topic, we have the ABI, we already have the address, we're not going to do a filter. And then we need a table name. So we're going to do a new line, we'll say table name, it's going to be item listed. And this is goin
g to be the name of the table that we update in our database. So we're gonna get a new table in here called item listed, and it's just gonna be filled with information about the item listed event. And that's it right and we would hit confirm if we were doing this on the UI. And since we're doing here, we'll just hit save, this is one of our events, we want to do this for all of our events. Let's do it now for item bought. So we'll say let's, item bought options, equals and we'll repeat the proce
ss, some of the stuff at the top is gonna be the same, the chain it is gonna be the same sync historical is gonna be the same. So we can just grab those two, paste them down here for item, but the topic is going to be different. The topic is going to be item bot is the name of the event, it's going to take an address, an address, a un 256 and a un 256. The ABI is going to be different. Once again, we're gonna go to our Hardhead NFT marketplace, we'll look for a bot, you'd find this event here. W
e'll copy this, go back, we'll paste it in here, we now have item bot, we'll give it a table name of item bot. And then one more then we have let item cancelled options equals and we'll do chain ID that's going to be rouse chain ID gonna be the same boilerplate from the top address. Contract address topic is going to be different. The topic for this it's called item cancelled, and it takes an address, an address and a UNT 256 will say sync. Historical will be true, historical is true. And then w
e need the ABI. Once again we can go back to our hard hat, compile information we can look for item cancelled, grab that ABI of that event. Copy that. Come back to our running code pasted in. Oops and I didn't give item canceled. Let's give item canceled the table name, which will be item canceled. So now if I zoom out just a hair, I now have item cancelled options, item bought options. And item listed options are telling Ross Hey, listen for these events, whenever you hear an item canceled even
t, stick all this stuff into a database. Whenever you hear an item bought event, stick all this in a database, whenever it emits an item listed, stick all this in in a database so that we can read from it. So we're indexing these events so that we can query them much easier. Now to send them up to our our server will say const listed response equals await or Alice or Alice dot Cloud dot run, watch contract event will pass the item listed options. And then one more comma, and then we pass an obje
ct in here where we're just gonna say use master key is going to be true. And we'll do the same thing we'll say const bot response or passing the bot item options. So we'll say bot response equals await or else dot Cloud dot run, watch contract, event, comma, item bought options. Comma, use master key that's going to be true. And then finally Kant's canceled response equals await oralis dot Cloud dot run, watch contract event, comma, item canceled options, comma use master key is going to be tru
e. Now this Morales dot Cloud dot run API call to our server that we're making is going to return a response. And let's look at the docs to actually see what that response looks like if it worked out. Well. In the terminal, you'll see success true. So this is the return we're getting from the API. So just to make sure everything goes well, I'll do an if listed. response dot success, we're getting that success object from the rails server, we'll just do a console dot log success database updated
with watching events. And then else we'll say console dot log, something went wrong with a duck. And of course, we're not just looking for let's say response dot success to be true. We also want canceled response that success and bots response is successful. Then say hey, you did it. Otherwise say hey, something went wrong. So this is how we're going to programmatically tell our server our database to listen for events. So we just do await Murata Clodagh, run, watch contract events, we pass it t
his object with all these parameters and flags in there. And then that's it. And then we can send them is because I put next public Morales server URL. And in my DMV, I just have next public server URL. So let's change the name here. Looks like our server URL was wrong. And our app ID name is also wrong. So let's fix that next public app ID master key looks correct. Okay, cool. So let's know things right? More Alice, like cada run, Rasta cloud run, when we run this in our database, if we hit ref
resh, right now, we don't see those tables in here. But once we run this, add events.js, we should call our server and we should tell it hey, you need to add these tables. And you need to start listening for those events. So in a new terminal, we're going to run this add events such as, so I'm going to make the terminal nice big. And this is where if something goes wrong, it can be a little frustrating to figure it out how to fix this. So if you run into an issue here, if something's not working
as expected, please use the GitHub repo associated with this course. And also the Morales forum is here for you, and Stack Exchange Etherium. So we're going to run Node, add events, dot j s, and we'll hit enter. Okay, boom, now we see success database updated with watching events. Now, if you ran into an issue, and you rerun it, and it gets something went wrong, there's a chance that it could still be correct, right, because it returns false. It returns that there's an issue if any of these alr
eady have the table in there. So if we go back to our database here, and we hit refresh, I can now see item bought, item canceled and item listed in my database. And again, you can see them by hitting the drop down on your server and hitting dashboard. We also see event Sync Status. And this is how our database knows that it needs to be listening for some events, and it's got all the information about how to listen for our events in here. So cool. So now we are listening for events. This is fant
astic. So now what this means is our database is now listening To our blockchain node, and it's listening for events in here it's listening for these item listed item bought item, cancelled events. So let's go ahead and test this back in our hardhat NFT marketplace Free Code Camp window. We have some scripts in here. One of them is mint and list. So we went to New NFT. And we listed on the marketplace when we list an NF T, well, our mirallas database should hear that item listed event and go ahe
ad and stick it into this item listed table that it made. So for us to test this out, let's open up our terminal in our Hardhead NFT marketplace repo. And we'll run Minton list for our localhost before we actually run it, just be sure that our hard hat node is synced up with our Morales server in order for your database to actually grab that event. Your local hard hat node needs to be connected. So we'll do yarn, hard hat run scripts, mint and list.js dash dash, network localhost. Let's enter. O
kay, minting, approving listing listed now if we flip back to our database, after a quick refresh, what do you know, we see that there's an indeed an item listed events in our database, we can see information about a tool we can see there's a block hash, a timestamp, we see the token ID that was listed, we see the price of the listing the transaction hash, we see all this information about our event. And now it's in this database for us to query. So if you have reached this point, you have succe
ssfully set up an indexer with the Morales database. And you should be super pumped because this is really powerful. And now we're getting advanced, we're starting to do some advanced stuff. So if you've made it this far, huge congrats. This is already really cool. Now, some other troubleshooting help here that I've run into many times myself, let's say I've left this project, and I've killed my heart hit note, I'm going to kill it right now. If I stopped, my heart had node and I come back to my
Morales admin, I'm going to view details dev chain proxy server, I'm now disconnected. And if I hit this little refresh, I'm disconnected of course, because I'm not running my heart headnote anymore. If I restart my node, my note is now restarted. My connects local dev chain command is still running. If I re fresh it, it'll now say connected, which is great. However, if I go back to my blockchain, or if I go back to my hard hat, NFC marketplace script, I run yarn, hard hat script, mint and list
again, network localhost, I go back to my database now, and I do a refresh, we don't see that item listed in here. So our mirallas server is looking to make sure that that the blockchain we're working with is the same one. So if we reset our blockchain, like we did, right, we canceled it and we reset it, our database is gonna get really confused. So what we have to do is we have to hit reset local chain, reset local chain, we want to make sure that our new local chain is running, and that we're
connected here. So we'll hit reset local chain, and this will tell them Ross, hey, we reset the chain, it's okay, please continue doing so. And once we hit reset local chain, we're not going to see that item listed in here. However, if we go back, and we rerun mint and list network, local host with this reset local chain. Now, if we go back to our Morales database, we hit refresh, we now see that new one has gotten in anytime you stopped your hard hat note, anytime you reset your hard hat node,
the takeaway is you're going to need to go to View Details dev chain proxy server and reset local chain. Now you can do that programmatically as well, we're not going to go over how to programmatically do that. But that might be something you want to add to your hard hat deploy. The other thing to note is that it didn't clear out our last event, right, the last event. And if I go one minute and list again, after completes, we'll have another event in here. Okay, this is great. So all of this is
being said, the reason we're doing all this in the first place is so that in our index.js we can start listening for events. How do we show the recent listen entity. So now we have a database of listed entities. So what we could do, we could just query this item listed table right and grab everything in here. However, we have an issue here, what happens if someone buys an NFT, if someone buys an NF T, the item listed event will still be in our database. But technically it won't be on the market
place anymore. It'll be gone, it won't be listed. So what can we do, there's a number of architectural choices we can make to get around this problem to solve this problem. But one of the things we can do is actually we can use mirallas Cloud Functions. So Morales cloud functions allow us to just really add anything we want our front end to do from the morale server. And these are functions. These are scripts that are going to run on a morale server whenever we want them to. So we go to our serv
er hit the little drop down and we hit Cloud Functions. Now this is where we can write somewhere else stuff to run on our server whenever we want. And we are going to set up our Cloud Functions in our IDE by hitting this little drop done to actually sync up our Visual Studio code with our Cloud Functions, we can just run this command here, and it will add whatever cloud functions we have in some cloud folder to here. So what we can do back in our VS code, let's make a new folder, new folder call
ed Cloud Functions. And in here, we'll create a new file called Update, active items.js. So in here, if we were to write something like console dot log, hi, we can actually have this automatically saved on a morale server. And the way that we do this is by running this command. Now, we want to make it so that it's a lot easier for us to run this command than just always having to run this massive thing. So what we're going to do is we're going to open up our package json, and we're going to make
another Morales script here, right below here, we're going to make another Morales script, we're gonna say Morales Morales cloud, and we're going to have it, run this command. So we're going to copy this command here, paste it into our package json. So it's going to be Morales admin CLI, watch cloud folder, we don't need the Morales API key, because it'll grab that from our environment variables. We don't need them rouse secret, because it'll grab that from our environment variables, we do need
the morale subdomain autosave one. And then the Morales cloud folder is going to be that new Cloud Functions bid that we made that slash cloud functions, functions. Now, in a new terminal, if I run yarn, more Alice cloud, which is going to be same as running this huge function here, I hit enter, it'll say compile, you know, version, blah, blah, compiling, blah, blah, changes uploaded correctly. And if we go back to our front end, we can see this console dot log ky and our front end being update
d. And if we continue to run this in our update active items at Jas, we could also write console dot log, you'll save it. And if this is still running, it'll automatically upload it. And now we can see if we do a little refresh on our front end Cloud Functions, we can see it's been uploaded here. Now at this point, if you have a ton of this stuff running, you might see CPU 100 percent, you might see this little thing pop up and the server might start going a little bit slower, we're starting to
use a lot of network activity here. So I'm going to close my yarn Morales cloud for now. And I'm just going to upload it once when I need to. Because we're connected, we have it listening to events, we're having it doing more and more stuff here. And it can start to put a lot of load onto the server. So we're just gonna go ahead and we're going to cancel that out. And now the CPU is a lot lower. But if we go back to Cloud Functions, we can see it's still in here. And anytime we update our Cloud
Functions, it'll update our server with those cloud functions. And we'll just run that darn morass cloud once we're all done here. Anyways, so right now we're trying to figure out, Okay, we have item listed, but if someone buys an item, technically, it won't be listed anymore. But our item listed table will still have it listed. So what we can do is we can create a Cloud Function that runs whenever we want. And like I said, we can have these run whenever we want. We can call these whenever we wa
nt. But we're going to create a Cloud Function that only runs. Whenever one of these events are synced item listed item cancelled or item bought, we're going to create a new table called active item, an active item is going to say, okay, anytime it's listed, it will be active, but when it's bought or cancelled will remove it from the active item list. So we're going to create a new table. So let's go ahead and do that. We started off with more Alice thought. And then if you're IT auditors that y
ou don't need this, we don't need to import Morales here, because we're going to upload it as a Cloud Function. And our server already just automatically injects mirallas into our scripts. So we're gonna say Morales dot cloud, that after save, and there's a whole bunch of stuff you can do with your Morales cloud. And again, you can find these all in the documentation. The after save keyword means that anytime something gets saved on a table that we specify, we'll do something. And it takes two p
arameters. So it takes what table that we want to do something after it's saved. And we're gonna say item listed. So we're saying anytime something is saved to the item listed table, we'll run some async function. And we'll put request in here. Because anytime something gets saved, it comes with a request. So anytime an item listed happens, we want to add it to our active items list. And our requests come with this is flagged called confirmed. So we'll say const confirmed because every request,
every event actually gets triggered twice. So once a transaction goes through, it triggers a save and then once again, once that transaction is actually confirmed, we actually only want to update our active item when the transaction is actually confirmed. So we'll say const confirmed equals request dot object dot get confirmed. Screening, get the confirmed attribute from that request. And then we're also going to make A logger will say const logger equals oralis dot Cloud dot get logger. And you
'll see why in a second, we can actually write logs to our Morales database with this logs thing. So any logs we can add into here, and I'll show you that in a minute. So console logger Morales dot cloud, get logger. And then we'll just do logger dot info. Looking for confirmed x, and we can actually test this right now. Right, we can actually test this right now. In our logs. We should see looking for confirmed TX Once an item listed and saved now to test this out just to test that our logger i
s actually working. Let's run yarn, yarn Ross cloud just update active items to our to our morale server changes uploaded correctly. Okay, we'll kill it now. And now in our where we have our Minton, lists script. Let's run Minton list. And we should see on our server we should get those logs. Now if we go to our server, we do a little refresh here. And if we look at our logs now we can now see looking for confirmed TX in our server logs. Now in our logs. Here we see we only see that looking for
confirmed TX once and I just told you, it actually triggers twice once when the transaction is first sent. And then once when the transaction is confirmed, aka has block confirmations. And additionally, if we look in our database at the item listed, and we scroll all the way to the right, we can see confirmed equals false. So we only want to count this item listed event interactive items when confirmed is true. So what we want to do actually is we want to update our scripts to add one block conf
irmation on top of our local Hardhead blockchain so that these can be changed to confirmed now to get around this. What I usually will do in my mentalist script is I'll add a new utility. So I'll go to my utils, I'll do new file, and I'll create a move blocks.js. And this will be a utility that I use to actually move the blocks. So when we run our own heart hat node, we actually have complete control over what we want our heart hat node to do. So what we can do is we can actually manually mine n
odes and actually move blocks ahead so that Morales knows Oh, okay, this transaction is confirmed, right, because we're mining the block with the transaction. And that's it, and Ross is just going to forever be waiting for the next block. So we want to add some functionality to our scripts, where we just mine a block after it's done. Now, keep in mind that if we mined like 1000 blocks or a ton of blocks really quickly, Moorehouse might have a hard time indexing that. So we really want to just mi
ned one at a time and give me enough time to index each block that we mined. So we're actually going to build a little script, we're going to manually mine using this EVM mine RPC method that comes with our heart hat blockchain. So we have this new move blocks script. And let's go ahead and make this. So instead of this being our script, we're going to have like a main function at the bottom, we're just gonna have this be a utility that we're going to import into other scripts. So we're not goin
g to need a main function here, we're just going to need to make this an async function. And we'll call it move blocks. And then we'll say amount, which is going to be the number of blocks, we want to move, we'll also put a sleep amount and default it to zero, this sleep amount is going to be an optional parameter. If we want to move blocks and sleep maybe a second between blocks to resemble a real blockchain, we can have that in here too. So we can have it resemble a real blockchain by sleeping
every time a block is moved or just kind of waiting every time a block has moved. So in our move block scripts, we'll do console dot log, moving blocks, dot that dot, and we'll say for let index equals zero, and we'll do a for loop around the amount and call that EVM. Mine in this for loop index is less than amount index plus plus a weight network. And then we got to import network oops, we got to import network from hard hat here, await network dot provider dot request. And then we're going to
request the method e v, mime, comma params are going to be empty. And this is actually the same way we can make raw calls to our blockchain nodes. We don't do a lot of this because ethers abstract this under the hood, but we're making a raw call to EVM mine. Obviously, you can't call EVM mine on a real blockchain because you can't just tell a blockchain node to mine the next block. Since this is our local hard hat node, we can call the VM now we're gonna say if sleep amount is greater than zero
, or just if sleep mount, then we're also going to have this script sleep or wait a short duration. So up at the top, we're actually going to create a new function called sleep, which is going to input a time in milliseconds. And this is going to return a new promise, right? Because remember, in order for us to wait for some time we got to use promises, which we've learned before. And this promise is going to take a function with resolve as an input parameter. And we're just going to say, set ti
meout is going to be resolve, comma, time in Ms. So the way we can sleep in JavaScript is we return a new promise. And we just call this set timeout function, which basically just weights the time in milliseconds. Now to actually sleep. We'll say console dot log, sleeping for sleep amount. And then we'll do await, sleep, sleep amount, and this is going to be in milliseconds. So since sleep returns a promise, we can call it with await to say, okay, wait for this sleep function to finish. And the
sleep function is only going to finish when the time in MS in time in milliseconds finishes. So now we have a function called move blocks, which will actually mined blocks on our local blockchain, so that Morales can get that block confirmation that it's looking for now at the bottom, we'll just do module dot exports, move blocks, move blocks, and then we'll also export sleep as well, because why not? Equals like that. Now, what we can do back in our Minton list, up at the top, we'll say const,
move blocks equals require dot dot slash utils slash move blocks. And then we'll also import network from ethers network. And the down in our script. Just right at the bottom, we'll just say if network dot config, that chain ID equals equals 31337 await, move blocks, we'll say we'll move to blocks and then we'll also do sleep amount equals 1000. We'll wait one millisecond between each block that we mined. So sleep mount equals 1000, which is going to be one millisecond. Now let's even just comme
nt all this out for a second. We'll just run this script with only this live. Right we'll pull this up the yarn hard hat, run scripts, mentalist dash dash network, local host, we'll just move the blocks move back to our front end, we'll refresh, we'll go look at item listed. We'll scroll all the way to the right, and now we see confirmed is true. And now if we were to look in our logs, we would see that logging item happened twice. Alright, so Let's uncomment this and continue. Now that we have
this now that we're learning about logging, now that we're doing all this stuff, we can say If confirmed, we're going to do some stuff. If confirmed, we're going to create a table called active item and add this to the active item table. So we're going to do a little logger dot info bound item. And we'll create a new table and a new entry in this table. So we'll say const active item equals more Alice dot object dot extend ACC active item. This we're saying if active item exists, great grab it i
f not create it. So we're going to create this active item table if it doesn't exist, if it does exist, great, grab it. And we're going to say const active item equals new, active item. So we're going to create a new entry in this active item table that we're creating. And we'll say active item dot set. And we can set any of the columns we want for this new table that we're creating. So let's give it a marketplace address column. So we'll say market place address. And this will come from the req
uest dot object dot get address all of these requests from events come with the address that they're coming from, which for us is going to be the marketplace address, we'll do active item that set and if T address which these events saved come with all the parameters of our event. So we'll say request that object dot get NFT address will get the price will say active item dot set price is going to be request dot object dot get price will get the token IDs will say active item dot set token ID re
quest dot object dot get token ID and then we'll get the seller will say active item dot set seller is going to be request that object dot get seller. So we're getting all of this information from our event. And this event update from Ross automatically always comes with the address that the event was omitted from. So we're gonna grab all that we're going to create this active item table. We're going to add all these rows. We're going to add this one row with all these columns in it. Awesome. No
w we'll just do logger dot info just to do a little print out. We'll say adding address. We'll do a little string interpolation we'll say request dot object dot get address period token ID with request dot object dot get token ID. And I need to close this off here, better. And then outside of the logger dot info, we'll just say logger dot info, saving. And then we just run await active item dot save. And now we have cloud function that's going to create a new entry in a new table called active i
tem anytime item listed happens. So after item is called the trigger for our cloud function, and there are a whole bunch of different triggers for different Ross Cloud Functions. If you go to the Morales docs, we look for trigger, we can find a list of all these different triggers in here, like after save for Save. After save, before delete, after delete, before save file, there's all these different triggers to trigger this cloud code. Now, if we upload this new script to our morale server with
yarn morass, cloud changes uploaded correctly, okay, great, we'll kill it. Let's go to our cloud server, do a little refresh just to make sure that it's not still processing that update. Okay, CPUs low enough. Okay, great. Now in our database, we don't see an active item table in here. But if we go back to our Hardhead script, and we call mint and list, since now we have a Cloud Function that says okay, anytime an item listed event happens, update that active item table, we should see active it
em update. So let's run this. And remember for all of this, we need to have our heart head node running connected to Hardhat. And if we reset our local chain, we need to click that reset local chain button. So we went ahead, we ran this. Now if we go back to our database, we give it a little refresh. And right now I actually don't see anything. So if I go to my logs go to info, I can see any errors or issues in here. So it looks like after save failed for item listed for user bla bla bla, looks
like there is an issue cannot read properties of undefined reading extend. And that's also in the info, I made an issue. I didn't quite write all my code, right. And if we go back to our update active item, I can see where I messed up. It should be Morales dot object with a capital O dot extent. So what I'm going to do, then run yarn morass cloud again, now that I have this correct, we're going to cancel that, we're gonna run our mminton list again, now that we've fixed our script. And now that
we've fixed our script, go back to our database, we'll give it a little refresh, I can now see we have an active item entry in here. Now at this point, there are going to be times when you don't want to leave and go get a coffee, right, or go to the bathroom or go get some food. And you're going to want to stop your terminals from running. So let's actually practice restarting everything and re getting into this local development environment. Because it can be a little weird and a little tricky.
So let's practice this. So once again, let's come over here. And what do we need to do? Well, we're going to Ctrl C, we're going to kill our blockchain Ctrl C, we're going to kill our connection to our Morales server. And if we're running a front end Ctrl C, that too, now if we go to our server, we go to view details. Dev chain proxy server, if we hit status, this reset button here will still we will be disconnected now. And now everything has been disconnected. Now if we want to restart everyt
hing, if we're on our heart hat NFT marketplace will run yarn Hardhead node, and that will spin everything up again, we'll run yarn Morales sync to sync back with our routes connection, we can go back to our server will do view details and we should be connected now. Connected. Since we restarted our local blockchain, we now need to remember to do reset local chain, we'll go ahead and run that. Great. If we want to restart our front end, we can restart our front end like so now the thing is, our
database will still have even when we refresh it even though we reset the local blockchain, it'll still have all this stuff in it. Now these entries in here are entries from a blockchain that no longer exists. So what I often will do is I'll click this button up here, and we'll just delete all rows in this class. To confirm we do active item, read the name of the table. And let's do it for item listed too. We'll select that edit, delete all rows, item listed. Yes, delete. We'll do a little refr
esh. Now everything is zeroed out here. Now we have an empty database for these events in our after save here. And now that we've added that little weight in our script, let's go back to our hard hat NFT marketplace, we'll run yarn, RT hat, run scripts, mint and list dot j s dash dash network, local host. This will mint it approve it listed and then we mined two blocks to give Morales time to index our event and then on a morale server. We go ahead and refresh we now see item listed as one and a
ctive item is One all at the same time. So that is how we're going to make sure that Morales always indexes whenever we call a function, we're just going to mind one additional block to tell Morales Hey, that transaction has indeed been confirmed. So really exciting. And we got to practice closing and restarting and doing all that good stuff, too. So now this is fantastic. Now that we have this additional functionality to make it a lot easier for someone else over okay, awesome, we can check act
ive item. Well, we're not quite done yet, right? Because what if somebody buys an NFT, or sells an entity we should have active item be removed? Right, right now there's one item listed in one active item. But if we buy an item, active item will still show that that item is active. So let's go ahead and let's update our cloud function to also say, okay, anytime an item is bought, we remove that item from being active. So let's create another after save. Let's first built this for canceling the i
tem. And then we'll build one for buying the item. So to make another after save to make another trigger, we'll say mirallas dot Cloud dot after save, we'll say item cancelled. And this will be an async function that takes the request as an input parameter again, and we're going to do the same thing. We're gonna say const confirmed equals request that object dot get confirmed, we'll say const. Logger equals routes dot Cloud dot get logger, like so. And then we'll do logger. Oops, lowercase L. An
d then we'll do logger dot info, marketplace, the little pipe object and then just request dot object. And then we'll do the same thing. If confirmed. If this transaction is confirmed after one block, we're going to remove it from active item. And we're going to be using a query to first find that active item that's getting cancelled. And you can learn more about basic queries in the Morales documentation here. So we're going to get that table by saying const active item equals more outlets that
object for the capital O object dot extend active item. And we're going to create a new query. So we're going to query our table before we actually set or save anything. So we're gonna say const, query, query equals new Morales dot query of active item. So we're going to query our Morales database to find an active item that's in there, that's going to match the request here, so we can cancel it. So we'll say query dot equal to marketplace address, comma request that object dot get address, we'
re looking for an active item where the marketplace address is going to be the same as the address of the item cancelled. We'll say query dot equal to NF T address, comma request dot object dot get an F T address will say query dot equal to token ID, comma request dot object dot get token ID. And that should be it right? So let's look again at our contract here. And what is the item canceled give us it gives us a seller NFC address and a token ID seller and ft address and a token ID. And we're l
ooking for NFT address and the token ID, we don't need to look for the seller, we just need to look for these two. And then of course, the marketplace address. So great. So now that we have those two, we can say logger dot info, and then we'll just print out marketplace type query. And then we'll just print out this query that we're running. And then we can say const, cancelled item equals await query dot first, we're going to find the first active item in the database that has the same marketpl
ace address and a T address and token ID that just got cancelled. So we're going to find that first cancelled item. We'll do a little bit more logger information, we'll say logger dot info, marketplace, pipe, cancelled item. And then we'll just do some string interpolation. And we'll print out that canceled item. Cancelled item and we'll say if cancelled item. So if the query doesn't find anything, it'll return undefined. So we're saying if cancelled item which will return true if it found somet
hing. So if cancelled item, then we're gonna say logger dot info. Deleting and then we'll do request dot object dot get token ID at address, request dot object dot get address address space since it was canceled, so we're going to do a little print little logging here. Take the leading that thing since it was canceled and then we're going to run a wait canceled item dot destroy and that's when we remove it from the active item. And then we'll just say else. Logger dot info, no item found with ad
dress, request dot object dot get address, and token, Id request dot object, dot get token ID. So cool. So now we have this after save here, it looks like my terminal automatically added this require in here, which we don't want. So I'm just gonna go ahead delete that. We can upload this to our Morales server by running yarn, Morales cloud and great changes uploaded correctly. And now to test this test that this is working, let's create a new script in our hard hat NFT marketplace called cancel
item. So we'll go to scripts right now we have mentioned list, we'll do new file, we'll call it cancel dot Jas. We'll do cancel item, Jas. And this will be a script. So we're going to use that that main thing here, but we're going to call our function cancel. So we'll do async function cancel, and then at the top, we'll say const token ID equals Now let's go to our active item list. And let's find a token ID that's in here. Okay, token ID zero. And so we'll use this as the token ID that we want
to delete. So we'll use token ID zero. So in our cancel item.js script, we'll say const token ID equals zero and let's cancel it. So we'll say const NFT. Marketplace equals await ethers dot get contract. And yes, const ethers equals require hardhat. And ft marketplace will say const basic NF t equals await ethers dot get gets contract. Basic NF team do const TX equals await NF T marketplace dot cancel listing basic NF T dot address token ID. And we're going to call cancel item should be cancelle
d listing we call the cancel listing. So cancelled listing Yep, like that. And it takes the address of the NFT and the token ID. So the basic NF T dot address and the token D Okay, great. And then we'll do a weight TX dot weight one. And then we'll do console dot log NFT cancelled. And then we'll say if network dot config dot chain ID equals equals 31337. We'll go ahead and we'll do a wait move blocks to two and then we'll say sleep. Mount equals 1000. And then we'll just say const. Move blocks
equals require dot dot slash utils slash move blocks. Okay, cool. That looks really good. So let's go ahead and run this yarn hardhat run scripts cancel item.js dash dash network, local host and ft cancelled moving blocks sleeping. Okay, great. Our node is running. Awesome. We're connected to our mirallas we've uploaded our cloud function with yarn Morales cloud. Now if we go back to our database, do a little refresh. Looks like I have an issue here. I go to my info it says after save failed for
item Cancel for user blah blah, blah. Here's the login information. Morales dot cloud apt get latar is not a function. Uh huh. Well, that makes a lot of sense. Get water. Let's do let's make this get logger. Shall we get logger to let's re upload them. Changes uploaded correctly. And now I'm going to have to manually go to active item I'm gonna have to manually delete this one will have a delete this row. Yes, delete, do a refresh. And the reason I have to do that is because it's already been s
aved. And we're doing an after save. So because I messed up. If you spelt that right, you probably did, right. But because I messed up, we're gonna have to rebuild a new one. And then delete that new one. I'm going to run yarn, hard hat run scripts, mint and list network localhost. And we just meant to add a new one. Let me check the Morales database, we'll do a refresh. I can see it in here, I can see it an item listed. It has a token ID of one. So let's go ahead and cancel that now. So I'm goi
ng to change my token ID and cancel item to one. And now we'll run that script Barnhardt at run scripts cancel item, network, local host run this NFT cancelled moving blocks. Now we'll go to the front end, we'll do a refresh. And we can see it's been removed from active item programmatically, which is great. So this is where these logs can be really helpful. Now it can be a little scary to do things wrong on purpose, but learning how to use information like the logging and learning how to debug
effectively is going to make you a lot faster of a coder because guess what, you're not going to be perfect. You're going to run into issues understanding how to use The Log Understanding how to read the errors is going to make you much faster developer. So now we have something for cancelled item, we're also going to need something for what? Well, you guessed it for buying the item. So let's make another one of these murales to cloud that after save. And we're going to be using most of this sam
e exact code for item bought that we use for item cancelled, we probably should turn it all into a function. But for practice, we're just going to go ahead and do it one more time, we'll do Morales dot cloud. And then my VS code keeps sticking this in for some reason. I'm going to undo that Morales dot Cloud dot after save. Item bot is the event. There'll be an async request little arrow function here, say const confirmed equals request that object dot get confirmed will get whether this transac
tion is confirmed. We'll get the logger I'm just going to copy paste so I get it right this time. So I'm going to copy and paste those two lines const logger equals Morales dot Cloud dot get logger logger dot info. And we'll say If confirmed const active item equals Morales dot object dot extend active item const query and for this query, I'm actually just going to copy these lines because this is going to be exactly the same. We're going to look for the NFT address and the token ID and the mark
etplace address. And if we look in our NFT dot soul and up to marketplace dot som alright and bot event as the NFT address. And the token ID which is what we want to find are listed and of team. So we'll run that query. We'll do const bots item equals await query dot first, and we'll do exactly what we did before. If bots item then logger dot info, deleting request dot object dot get object ID await bought item dot destroy logger dot info deleted item with Open ID request dot object dot get open
ID at address request dot object dot get address. And then if we don't find it will say else. Logger dot info, no item found with address request that object dot get address and token, Id request that object dot get token ID. Cool. So that looks good. Let's go ahead and upload this to the cloud. So do yarn oralis Cloud changes uploaded correctly. Let's go make sure it looks good on our server. So we'll give a morale server a little refresh. Go to Cloud Functions here. I can see the item cancell
ed in here still. And now I can see the item bought after save perfect. Looks like I'm at 100 percent capacity. So we're gonna give it a second just to cool down thinking give it a little refresh and looks like we're back down after our cloud function has been uploaded. Okay, cool. To test out that this part is working. Let's go ahead we'll write another script here. Do new file by item dot j s. And we'll do the same thing right now. On our database. We don't have any active items. So we'll just
run real quick. We're on mint and list. Mint a new one. We'll go check our database we'll do a little refresh. Looks like active vitamins in here with a token ID of two now. So we'll do is we'll buy that token ID so we'll say const ethers network equals require arhats const move blocks equals require dot slash utils slash move blocks const token ID equals to async function by item const NFT marketplace equals await ethers dot get contract NF T marketplace const basic NF t equals await ethers do
t get contract basic NFT coms listing equals await and ft market place dot get listing basic NF T dot address and the token ID will say const price equals listing that price that to string and we'll say const Tx and this is us going to actually buy it equals await and ft marketplace dot buy item basic n f t dot address, token ID, comma. And then the value of course is going to be the price. Do await TX dot wait one, console dot log bots NF t. And then if network dot config dot chain ID equals 31
337, then await move blocks to comma, sleep amount equals 1000. And then this is a script of course, so we're going to use the same stuff we're using for cancel. But instead of cancelled, it's going to be called by item. So we have the item inactive item here, we run yarn, art hat run scripts by item.js Dash network, localhost. Now we can test buying this item. Okay, Bob, the NFT looping blocks, we'll do a little refresh on our database, and boom, we can see the active item is gone. And we can s
ee, the item has now been bought. Awesome. We're almost done keeping our active item, just a table of active items. But there's one more thing we should do. We're not going to test this here. But if you want to test it, we can we actually in our NFT marketplace, go to marketplace dot Sol, we actually have an update listing function as well, that also admits an item listed. So we also want to check to see if item listed is coming from update listening. So back in our item listed Cloud Function, b
efore we actually start saving stuff, we want to check to see if it already exists. So we're gonna say so we'll say const query equals new mirallas dot query. And sorry, I keep sticking the sin of active item. And we're going to do exactly what we've been doing. We're gonna say query dot equal to NFT. Address, we're gonna look for the NFT address request dot object dot get and ft address, query dot equal to token ID, request that object dot get token ID, query dot equal to marketplace, address,
comma request dot object dot get address query dot equal to seller requests dot object dot get seller will say const already listed item equals await query dot first. And then we'll say if this item has already been listed. Then we'll go ahead and say logger dot info. Deleting already listed request dot object dot get object ID. And we'll do a weight already listed item dot destroy. And then do logger dot info, deleted item with token ID request dot object dot get token ID at address request dot
object dot get address since it's already been listed, if the object has already been listed, we know that it's coming from this update listing function. So we're going to delete it first, and then we'll resave it with its new price. So and let's just go ahead, and let's upload this to the cloud yarn Morales cloud. upload this to our server changes uploaded correctly. Let's go check our server, give it a little refresh. We'll go check Cloud Functions. And it looks like our item listed query for
deleting is now in here. But with all that, we now have a way to constantly have this active item table only be the items that are actively on our marketplace without having to spend any additional gas in our application. And this is going to be way better for user experience because they're not going to have to pay extra gas to keep all these entities and maybe an array or some more data structures. If you've made it this far. This is easily one of the hardest parts of this course, because we'
re working with a ton of technologies. We're working with a smart contract, we're working with Cloud Functions, we're working with a back end database. Now if you've made it this far, you should be incredibly incredibly proud. So now let's just go ahead, let's mint and list one more NFT. So we'll do we'll run yarn heart at run scripts, mint and list network local hosts will meant it will list it or sleeping. Let's go check our database. We'll do a refresh. We see the active item in here. And now
let's learn how to call all of the objects in In our active item database here, let's do it. And remember, if you ever reset your local blockchain, you're gonna have to come in here and delete all the rows in the support tables. With all that being said, it's time to finally come back to our front end, and come back to our index dot J. S and answer this question. How do we show the recently listed NF Ts, we only want to show the active NF t's on the marketplace. And now we have a system for get
ting only the active ones, only the ones that are currently on the market, because we're indexing these events. Now, I'm going to delete all these comments here. And let's do this. So what we're going to do is we're going to do this thing called use Morales query. So if we go to the React Morales docks, there is a hook called use Morales query. And this allows us to fetch and make queries to our database in a React context. Back in here, we're going to say, import, use Morales query from react m
irallas. Now, if you look in the docs here, use mouse query returns data error is loading. And this will automatically run this query the instant our index pops up. So to get the data from the query to get all of our active items from our database, we'll say const data, and we'll rename data to listed and fts. And then we'll also check to see if this query is still fetching. So we'll say is fetching and then we'll rename that to fetching listed NF t is equals use Morales query. And inside here,
this takes two input parameters, it takes the table name to do the search on and then it also takes a function or the query. So the table name that we're going to be looking for is going to be active item. And then the function for the query is going to be we're going to say query dot, we'll limit it just to 10. So we'll say only the first 10, we'll do it in dot descending order, based off the token ID. And then if we wanted to do different pages, we could do this thing called dot skip with page
numbers, we're not going to do page numbers here. So we're just going to leave it like this for now. And that's it. So we're saying, okay, great, grab from our database on the active item table, grab just the first 10 in descending order of the token ID. Now it's going to save the result of this to this listed NF TS section. Now to see if this is working. Let's just do a little console dot log listed NF t's just to see what this using Ross query actually returns for us. And now we have our loca
l blockchain Node running, we have our connection to our Morales server, and we have our front end running. So let's go to our front end, we'll do a little refresh here, we'll right click and hit Inspect, we'll go to the console. And we see we have this array being spit out here. Now the first time it console dot logs, it's empty. This is because when it initially loads listed out of T's hasn't returned yet. And it's so it's actually just going to be an empty array. But when it finishes loading,
we're going to get an array of size one, we get an array of size one, because active item only has one enter right now. So we get this array of size one, and we can see it index zero, we have class name active item, we have the item ID, we have all these attributes, which are going to be created at the marketplace address. And if the address the price, the seller and the token ID this is exactly what we see in our database here. So Perfect. That's exactly what we want to be able to show these N
F t's on the front end. So how do we actually show this NFT and list this NF T. For people who aren't developers and aren't going to go into the console dot log? Well, what we're going to be doing is in this return here, we'll put some parentheses around this. First, we should check to see if we are fetching those listed NF T's. So we'll do some JavaScript stuff. And we'll say fetching listed NF T's and we'll do a ternary operator. So we're gonna say if we are fetching those NF T's, let's add li
ke a little div div that just says loading that that done, we'll put a little colon here. And if we're not fetching, we'll do we'll say listed NF TS dot map. So dot map basically loops through and does some function on all of the listed entities in the function we're going to want ours to do. And it's going to take each NF t as input parameters. So we say we're going to basically loop through each NF T. And we're going to say, console dot log and F T dot attribute attributes with an S. And then
inside of these inside of this attributes are the different pieces that we want. So we're going to get those pieces we'll say const we want to show the price. The NFT address, the token ID in the marketplace address, which of course is just gonna be this one, and then the seller, that's all this information that we're going to want to show on the front end will say that equals NF T dot attributes. So we're going to pull these out, and we can see price seller token ID, etc. We're going to pull th
ose out of NF T dot attributes. And we can show those by in this function here, we'll say return. And then we'll return some HTML, we'll do like div div. And then we can say like price, price, price, period, and f t address and ft address, token ID, token ID seller, then added this for some reason. So I'm going to delete that add $1 signs before all these for some reason, delete those, save. Now if I go to the front end, I can now see information about our NFT from our database is listed here. T
hat's fantastic. We see the price we see the address, we see the token ID we see the seller. Now if we go back to our NFT marketplace, our little our little hard hat MC marketplace, let's mint another one. Yarn hard hat run scripts mentalist Dash network localhost, we're going to run that it's going to mint one more. If we go back to our Morales database, we do a little refresh on that active item table, we now have a new item in here. So if we go back to our front end, we give this a little ref
resh. And boom, now we have two items in here. So this is awesome, we now have a way to actually show the most recently listed NF t's on our marketplace, plus ah. Now, of course, you might be saying to yourself, hey, Patrick, that's cool and all. But that looks really ugly. And I would agree with you. But 100 percent agree with you. So we should come up with a component to show our listed entities that looks a lot nicer. So when instead of returning and just printing out the raw information, we
probably want to show the image, right, we want to show the image, we want to make everything look a lot nicer. So we're going to create a new component that we're going to return in here to format all of our NF T's appropriately. So we're gonna go to components, we'll do new file, and we're going to call NF T box dot j s. And this is where we're going to grab all the information on how to show what our NFT actually looks like. So let's get started working on our entity box, we're gonna set this
up, the way we've been setting all these up would do export default function, and ft box. Now something that's a little bit different for this one, though, is that in our index, we have all this information. So we're gonna need to pass all these variables to our NFT Box component. So to do that, we'll add them as input parameters for our component here. So we'll say price, and if the address, token ID, marketplace, address, and seller. So right now on our front end, we just have a whole bunch o
f text, and we even have this gross warning, we're gonna get rid of that tip. And as we know, tokens have their token URI, which points to an image URI or an image URL of what the actual token looks like. So what we're going to want to do is we're going to want to call that token URI, and then call the image URI to show the image. So we're going to actually have to wait those two API requests to get the actual image. And we're going to save that image as a state variable on this component here.
So as you already know, we're going to work with use state to keep track of that image URI. So we'll do import, use state from react like this. And in here, we'll say const, image, Uri, comma set image, URI equals use state. And we'll start it off as a blank string. Now let's create a function, we're going to call it update UI to update our UI and grab this token URI and the image URI. So we'll create an async function called Update UI. And in order to get the image first, we're gonna need to ge
t the token URI, and then using the image ag from the token URI gets the image. So first thing we're gonna have to do is get the token URI. So we know how to do this with use web three contract. So we'll do import, use web three contract from react Morales. And as we know, use web through contracts is going to need some parameters. So we'll say const run contract function, get token URI, equals, use web through contract. First, we need the ABI of the NFT because we're gonna need to call token UR
I. So to get the ABI we're gonna need to once again update our front end. So let's comment this part out. We'll go back to our hard hat piece. And let's look in our deploy scripts. We have this update front end right now. All this is doing is updating calm object addresses. Well, that's good. We're also going to want to add API's to our front end as well. So let's create another function in here called Update API. And we'll pass the API's as well. So we'll do async function update API. And we'll
give it both the basic NFT API and the NFT marketplace API, because we're going to need both of them. So we'll say const NF T, marketplace equals await ethers dot get contract. And f t marketplace, we're going to write the ABI to the front end API location, we have the front end contracts file. So let's also do a const. Front and ABI location equals, and we'll do dot dot slash next, Jas, and if T marketplace dash FCC slash constants, and instead of actually just giving the file name, we can jus
t give it the front end API location. And then we'll actually have it generate that file for us because we're just going to overwrite the ABI file anytime we work with it. So now that we have the marketplace, we'll just do Fs dot right file sync, and we'll do front and ABI location, and ft marketplace, dot JSON. And ft marketplace, dot interface that format ethers dot utils dot format types dot JSON. So we're also going to want to do that for the basic NF t. So we'll say const basic NF t equals
await ethers dot get contract basic NF T Fs dot right? file sync, it's going to be that exact same place right here. Except for it's going to be a different location, it's going to be basic NFT dot JSON. And of course, we're gonna do a comma basic NF T, that interface dot format ethers dot utils, dot format, types dot JSON, you can find this NFT marketplace that interface in the Hardhead documentation. And you can find this in the ethers documentation. So now we have this update ABI function. Le
t's also add this to our module that exports so we'll do a weight up the ABI like that. There's a hyphen here that shouldn't be here. And we'll run just this part of our hardhat front end, run yarn, hard hat, deploy dash, dash dash tags, the tag here is front end, front end. And now it's had nothing to compile updating front end, it's done. So if we go back to our front end, now, we go to our constants, we now see two objects in here, which are going to be API's, the basic NFT, and the NFT. Mark
etplace. Awesome. So now that we have that, we can import those into our front end. So we can say import, and if T marketplace, abi from dot dot slash constants slash NF T, marketplace dot JSON. And we can also get the NF T API. So we'll do import NF T, abi from that the slash constants slash basic NF T dot JSON. Now in our run contract function, our token URI function is part of the NFT API. So the API will be the NFT, abi, the contract address is going to be the address of the NFT, which we're
passing in as a parameter. So we'll pass an NF T address, the function name is going to be token URI, and the params are going to be the token ID, which is getting passed as an input parameter to this function to this component. Right. And we can double check. We're good to our basic NF T dot soul, right? We scroll down, we have this token URI that we're overriding. And this is the function we want to call takes the token ID. So this the function we want to call takes the token ID. Okay, great.
So in our update UI, first, we'll say const, token URI equals await token URI. Now let's do a little console dot log token your eye, just to see what this returns to make sure that update UI is called, we'll add it to a use effect, we'll say use effect. And this takes an input parameter of a function to do, we'll just say Update UI. And then we'll only have this run anytime is web three enabled changes. So we want to run update UI, but we want it to be dependent on is web three enabled. And the
n we'll say if it's web three enabled, then update UI. So we need to add use effect as well. So we're using use state, we'll do comma, use effect. And now we should at least be reading our token URI off the blockchain. We're not going to set the image yet, right, because we're going to get the image URI from the token neuron. Let's add this NFT box to our index to see if it's working well so far back in our index Next, up at the top, we will import NF T box from dot dot slash components slash NF
T box. And down here, while we're returning this will add our NF T box component will make sure to pass in all the parameters it takes. So the price is going to equal that JavaScript price. And ft address is going to equal the JavaScript entity address. The token ID is going to equal the token ID, marketplace address is going to be marketplace address seller is going to be the seller. And you saw that warning where it's saying, hey, all the components need to all the things in the mapping need
to have their unique key. So we'll say key, we'll give these all a key as well. We'll say key equals this, we'll do some string interpolation, we'll just say the NFT address, combined with the token ID can be the key. So if we save that, go back to our front end here, do a little refresh marketplace address is not defined market place address. So let's make sure we spell things right, let's go back to the front end, we'll give it a refresh is what three enabled is not defined. Oops, excuse me in
the NFT box, we need to grab that from us Morales, so we'll import use Morales. And in our ponents here we'll say const is web three enabled equals use Morales. We'll save that. And one thing I noticed actually is this needs to be wrapped in squigglies. Sorry, I forgot to do that. Our component actually just takes a props, props input parameter. And we would need to do like props that token ID to get token ID. But instead, we just extract it out by doing putting the little squiggly brackets her
e. So put the squiggly brackets there. Great, we'll do a little console dot log token, your eye, or index.js has everything updated. Here. Let's do a little save. And we can even say if is web three enabled up the UI. Like that we'll save we'll go to the front end, we'll do a little refresh. We'll see if everything's working as expected. And as long as we're on that hard had localhost and our meta mask. And again, you can ignore this error, this warning that's up here for now. And if you click t
his, and you have your IPFS and brave or your IPFS companion, we can now see we're getting our token URI, which is perfect. The piece that we want now is this image bid. And for this one that I'm using it is an HTTPS, which technically isn't decentralized, right, we would need it to come from instead of HTTPS, we would need to come from IPFS colon slash slash but but actually having it as HTTPS ipfs.io. For now was good, we'll explain why in just a second. Now that we are getting the token URI,
we can call this URL, and we can get back the image that we want to actually show on the front end. So in here, we'll do a little console dot log, the token, URI is string interpolation, like this, and then we'll say if token URI, we're going to need to now grab this token URI, and get the image from it. And this is where we're going to get a little bit funky. And we're going to cheat a little bit. Now for our application, not everybody is going to have IPFS companion, not every browser is IPFS
compatible. So we're gonna have to actually cheat a little bit here, we're actually going to change the token Uriah from its IPFS edition to an H HTTPS edition. And this is known as using an IPFS gateway, which is a server that will return IPFS files from a normal URL. So we're going to use an IPFS gateway, which we can just make regular HTTPS calls to, and it will return those IPFS files. So technically, are we making the centralized doing this? Yes. And is that ideal? No. However, until the wo
rld adopt IPFS, and until the world adopts the standards, it's kind of what we have to do right now. Because otherwise, the front end will just show up as blank to them. And we can't have that we don't want that. So we're gonna say const request URL equals token URI dot replace IPFS, slash slash with HTTP s, HTTPS. slash slash ipfs.io/ipfs/so. We're saying, if you have a token URI that starts with IPFS, that's great. But we're going to switch it to using an IPFS gateway. It's really use the IPFS
gateway provided by the team that builds IPFS. So pretty reliable gateway is is kind of a cop out. Yes. Are our files still on? IPFS? Yes. So it's not the end of the world. But this is just going to make calling these API's a lot easier for us. And we're going to say const token URI. Response equals await. And this is going to be a little weird. We're going to do two awaits. await a weight fetch request, URL dot JSON. So fetch is a keyword you can use in JavaScript to fetch or get a URL fetch k
eyword is essentially doing the same thing as pasting this into the browser, like so. And getting this JSON response. So we await to get the response. And then we await to convert the response to JSON. And that's how we get the toggle response. So we now have this object in our JavaScript, which is perfect because this object has this image attribute that we want. So we're gonna do the same thing we did here, we're gonna use the IPFS gateway, this one's already using HTTPS that ipfs.io. But if i
t wasn't, we would still want to convert it. So now we're gonna say const. Image URI equals token you are i response dot image. So we're gonna get the image tag of this response here. And then we're going to say const. Image URI URL, is going to equal to, and we're gonna do the exact same thing that we did up here, we're going to use the gateway image URI dot replace IPFS, colon slash slash with HTTPS ipfs.io/ipfs. And now, and that's how we get this URL right here. And so we can finally do set
image URI, to that image URL. And now we have our image URI is going to be that image right here. Now, is this a little bit wonky? Yes. Are there better ways that we can do this? Yes, there's actually a number of better ways that we could do some of this, we could actually, since we're using Morales, we could render image on our server and just call our server, what else could we do well, or test nets and maintenance routes actually comes with a bunch of hooks like us NFT balance that will show
us an F TS show us how many NF T's shows all this information about NF T's but it only works on test nets and main net, we'd have the world adopt IPFS. So we don't have to do this wrapping. Unfortunately, it doesn't yet so such as life. But now that we're setting the image, alright, we have this image URI, we have what this actually looks like, we're going to have this and if we click on this, we use this in our browser, it returns this dog. So now we have the image URI in our website, we can fi
nally use it to show what this is going to look like. So finally, we can create a return in here. So down below, we'll do return to a little div. And then we'll do another div just because I want to. And we can do some JavaScript, we can say if if that image array exists, we'll do some stuff. Otherwise, we'll do some other stuff. So if it doesn't exist, maybe we'll do a div for now. div that just says loading dot the dot. And if it does exist, for now, we'll just say, just do a little div, close
the div. And we'll just say found it. Now if we go back to our front end, let's see if we're good here. Uh huh. If I do a refresh, we see found it for both of these NF T's. Okay, cool. So how do we actually show these NF T's, we finally have the URL that we can use to show the NF T's. But we want to actually use them next. Jas actually comes with a component called the image component that we can use to render images really easily just by using a URI. Now, because we're going to use this image
tag, and because it does some optimizations on the back end, that means that this website won't be able to be deployed to a static to a static site, like IPFS. Because now our website requires a server technically, requires a server just because we have Morales. So that might be another reason, we might not want to, since we're using this image tag, we can't deploy this statically to something like IPFS is we're going to up at the top, we're going to import image from next slash image. And we're
gonna down here we're going to say, instead of founded, we're gonna go Image, we're gonna close it off here, too, we're gonna give a loader of just a blank function that just gives us the image URI. Don't worry too much about loader. For now, we're gonna say the source of the image is going to be the image URI. And then we'll give it a height of maybe 200. And then we'll give it a width of also maybe 200. And if we did this right, after we save, we should see the image on our UI. So we'll go ba
ck to our website, and oh, my goodness, we can see the dogs holy cow. This is getting really exciting. We can see the puppies, we can see the images, we're definitely doing something right here, which is really exciting. Now I know I said this before that this isn't a CSS. This isn't a formatting tutorial, because that's definitely not my expertise. However, let's make this look a little bit nicer. And we're going to use once again, the web three UI kit, because the web three UI kit has a whole
bunch of tools that are really, really helpful for us to use. So if we go to the web three UI kit, we can go to that live storybook Another interactive bit, and we can scroll down to the section that has called card. Or we can make these little clickable cards and we can display some information about our nfts. So let's go ahead and at the top, we'll do import import card from web three UI kit. And now instead of just showing the image, we'll wrap the image in a card like this. We'll save that.
Now back on our front end, give it a little refresh. Now we've got this kind of clickable section that looks a little bit nicer. We'll even label it. And we can even label it with a title and description. Now we can grab the title and the description from the token URI response. So up at the top, let's go ahead, let's grab the title and the description of the token UI as a state variable. So we'll say const, token name, set token name, equals use state, start off as blank, the const token descri
ption, that token description, equals use state. Start off as blank to download, we do this update UI bit, we'll call set token name. So we'll say name is token, your response dot name, we'll say set token description, which will be token, your response dot description. And then we'll use those descriptions and title in the cart. So we'll say title equals token name, description equals token description. Save that. We'll look at our front end here. Give it a little refresh. Oh, and now we have t
he name of the NFT. And its description on our front end. Okay, cool. Let's keep going. What else do we want on this? Well, we probably want who it's owned by. So we'll put a little div inside the card, say div, maybe we'll even put the token ID we'll do a little number. With the token ID. We'll do another little div, and then we'll make this italic. We'll say class name equals italic. And then text is going to be small. And we'll say owned by, and this is where we can get the seller that we're
passing in as an input parameter. And then maybe underneath the image, we want to put the price. We'll do a little div here. And then we'll say price like this. However, we're probably don't want it in way we want it in human readable units. So we'll import ethers, we'll say import ethers from ethers. And then instead of just showing the price, we'll do a little, little JavaScript and here we'll do ethers dot utils dot format, units, price, price and ether. And then we'll do space eath. And then
we'll make this be class name equals font bold, so we can read how much it's listed for on our marketplace. Let's go back a high we can now see, this is token ID number four. We can see who it's owned by we'd see the price of it and then more information about the dog. Yay. Now let's format all this stuff in here a little bit nicer. So let's wrap everything in a div in one more div. And that will say class name is going to be flex. And this is going to help format everything, we'll put everythi
ng in a column items and get to. And now if we look back there, kind of like in a column now, wrapping one more div, give them some padding, last name equals P to say a little bit padding has been added. Okay, nice. And then we'll go back to our index, and we'll add some formatting to our index here. So our main one, we're going to remove styles dot container, we're just gonna say container. MX auto, we're going to make an h1 in here, class name, equals, I form E X for font bold text to XML. Thi
s is we're just gonna say recently listed, then we're going to do another div. Class, name equals flex, flex wrap. We're going to end this div around our JavaScript here. And let's look at our UI. And let's see what that does. Okay, cool. Let's go back to our index. Let's remove all this stuff. Since now we're adding that to the card. Let's save. Now it's looking a lot better, we finally able to start listening our NF Ts and then have them show up on our marketplace like we see here. Fantastic.
Okay, if we go to the readme homepage show recently listen to empties. Oh, my goodness, this is a check we're done here. Now, and I know what seemed like a lot of work, but a lot of it was setting up that morale server correctly. And because we have our own back end, now, we have some back end services that we needed to configure. But now that everything's set up, the rest of this is going to be easy St. Now we are only going to want this to show if we're connected to web three. Right? Now, if w
e click this, this still shows up. So we're going to have to update this a little bit. And in our index.js, we're now we're checking to see fetching. Listen, NF T's right before that, right? Before we do that we actually want to see is web three enabled. And this is going to be a little bit of nested tertiary operations. If web three is enabled, then we're going to do all this fetching, listed NF T's stuff here. We're gonna do everything in here. So if it's not enabled, let's do like a little di
v that says web three, currently not enabled. And of course, we're going to need to grab is web three enabled. So we're going to say, for the top we'll do const is what three enabled equals use oralis as we've been doing, and we're going to grab use Morales from react Morales, we'll save that go back to our front end, give it a little refresh. If we're connected, we'll see the marketplace. If we disconnect, we see web three currently not enabled, which is what we want. Perfect. So what is next i
n our readme. If you only NFT, you can update the listing. Let's first let's figure out if somebody actually is the owner of these entities. Let's make it really easy for the people on this website. Well, first we can get the person's Metamask by grabbing the account from us mouse, so we'll do a comma account. So then we can easily just do const is owned by user equals seller equals equals equals account. So the seller we're getting from the contract, the account we're getting from whoever's con
nected here, if the seller equals the account, there is no seller equals equals equals undefined. We'll just say they're owned by you. And now instead of saying owned by seller, we can say const, formatted seller address equals, and we'll do the ternary operator will say if it's on by you, then we'll just say you instead of seller. Otherwise, we'll say seller. Now we'll say owned by formatted seller address like this. So if we go back to our front end, we do a little refresh. depending on who's
connected, you might see owned by blah, blah, blah. Now if I go to my Metamask, let me go ahead and switch account to account three, let's go ahead and connect our account three, we now see owned by you instead. Right, and we can even switch again, we'll switch accounts again, we'll switch to account one, we now see owned by blah, blah, blah, like so since when we switch back and forth, the diameters of this actually change which is really annoying. So maybe we want to go one step further. And w
e want to truncate this seller address make it a little bit smaller. So we want to make a seller a little bit smaller. So let's create a new function. And we can create this outside of the export default function because this is going to be a function that doesn't depend on anything inside our app. It's just going to be kind of a raw function. So we're going to create we'll call it const truncate string, and this is going to be a function that takes a full string, and a string length as paramete
rs. And we're just going to pass the seller address and how long we want to make this string. So this is going to be an arrow function we're going to do here, and we're gonna say, if all string dot length is less than or equal to str Lang, return full str. Otherwise, we'll say concept ra torx equals three little dots. And we'll say, Let's separate Tor length equals Sep. Ra Tor dot length. To make con separator length, we'll say const chars to show is going to be the the string length minus the s
eparator length, we'll say const. Front chars or front characters is going to equal math dot ceiling chars to show divided by two const back chars is going to equal math dot floor, chars to show divided by two. And if you don't understand this math here, don't worry about it. And then we're gonna say return full string substring of zero to front chars plus the SEP IRA tour plus full STR dot substring. of full STR dot length, minus back chars. And now what we can do is we can grab this truncate S
TR this truncate string and for is formatted seller will say if it's you will still do you but otherwise we'll do truncate string of seller or blank if there's no seller, and we'll have it be size 15. And now if we save that, go back to our front end, if it's owned by you, it's still gonna say on by you. But if we switch accounts, and now says owned by, you know, blah, blah, blah, dot the dot blah, blah, blah with a truncated address. And then these sizes don't actually change, which is a lot ni
cer than them getting bigger and smaller. So awesome. So now we have this formatted even better. Okay, now what do we want to do? Well, now that we know who owns the NFT, NF T, and it's formatted pretty nicely, we need to figure out a way to update the listing. So what we want to do is, once again, if it's owned by us, and we can switch back to the account, it's owned by if it's owned by us, when we click on it, we want to be able to update the listing on the marketplace. So to do this, we're go
ing to create a new component called Update listing ngModel. So we're gonna create a new component, new file, update, listing ngmodel.js. A ngModel is something that like pops up. So for example, this little pop up here is known as a modal. And this is what we want to build. If it's owned by us, when we click this, we want it to pop up this modal thing. So to get started, we'll do the same thing we've been doing for all of our components here, we'll do export default, function, update, listing n
gModel, like so. And we're probably going to want to pass it these parameters from the entity box, probably gonna want to pass these parameters. So the ngModel knows what function it needs to call in our NFT marketplace. The way we're going to update listing is we're going to call this update listing function where we need the address token ID and then some new price. So we're going to at least need those. So we're going to need the NFT address, and at least the token ID to make this little pop
up, we're not going to code it ourselves, we're going to once again, use the web three UI kit, web three UI Kit has this nice pop up section, where it has some code to work with a modal. So we're going to import that will do import ngModel from web three UI kit, like so here's what it looks like we have modal and then we have all this stuff on working with the modal. So we'll do our return, do a little modal, like this. One of the key things in a ngModel is whether or not it should be visible. S
o it has an is visible tag, which we're actually gonna have to grab, we're actually gonna have to grab from the empty box. So we're going to pass a little is visible here as well, in our NFT box, we need to tell our ngModel when it's visible. So we'll we'll make that code in a little bit. Right now, it'll just be blank. And inside of our ngModel, we're going to want to give an input field for how to update it. So I know we've done some regular inputs before, since we've been working with web thr
ough UI kit, let's just use the input that it has as well. So we'll do a little comma input here. And inside of the ngModel we'll create a new input. So on our input field, we'll give this a label which is going to be update listing price in L one currency. And we'll just do eath. For now we'll just hard coded as eath name will be new listing price, and type is going to equal a number we'll do Little backslash here, oops, we'll do a little backslash instead of like that. So cool. So when this mo
dal pops up, it's gonna have this input in here. And we can actually test to see if this is working. We can import this into our NFT box, we'll do import, update, listing ngModel. From that slash, update, listing ngModel oops, and sorry, this doesn't need parentheses, and at the top of our return here, right before our card will add it in. So we'll just add another div though. So that these two can be in the same react. But we'll add another div, we'll say Update listing ngModel, like so with a
little backslash here. And right now we just have to pass is visible. And then for now, we're just going to say true. So now with this listing ngModel on our front end, we do a little refresh. And we get this little box like this update listing price and one currency. And we have to close two of them. Because technically we right now both modalities are true, right. So if we do a refresh, we get this little input pop up this little modal and we close it twice, because we have two NF T's if you h
ave a ton of NF T's here, you will have to close a ton of those. So we change it to false, we go back to the front end, we do a little refresh, and boom, now it's false. So true, save, run, and it's there. Gross, delete, delete, false, save front end, it's not there anymore. Okay, cool. So we're gonna have to tell this ngModel only to pop up when somebody clicks this and have tea that they own. So to actually toggle this and actually make this work, we're going to update our card. So whenever we
click our card, we're going to create a function called handle card click that handle card click is going to update a variable for whether or not we should show this ngModel. So we're going to do is we're gonna say on click of the card, aka, once we click our dog, we're going to call some function. So we're gonna say on click, equals handle card, click, animal card, click, and we're going to make this a function, we're gonna say const, handle card click equals a function, we'll use some Arrow s
tuff here. And then we'll just say, if it's is owned by user, if it's on by user, we'll show the ngModel. Else, we will call the by item function, since we want our whole UI to rerender. Once we change, once we change the variable to show the ngModel, we're going to do this as a US state. So we'll say const, show ngModel. Come a set, show ngModel equals use state. And then we're going to start it off being defaulted to false. So by default, we are not going to show them on down which is what we
want. But if it's owned by the user, we're gonna say Set Show ngModel to be true. And then else right now we'll just put console dot log, let's buy will actually update this to bind the item a little bit later. So now instead of having is visible be false, we'll have is visible equal to show ngModel. Or show ngModel. Variable. Okay, great. So now if we save that, we go back to our UI, we right click, we hit Inspect, if we own it, and we click it, the ngModel will pop up, and we can click it out,
click another one, but that will pop up if we don't own it. So if we switch accounts, Connect will switch. We click it, nothing happens. And if we go to inspect, we go to the console, we click it, we should see let's buy pop up, which is what we do see, we'll do a little refresh here. Click we see let's buy pop up, click again, let's buy click let's pilots pilots, why? Great, cool. So now we have a word for that ngModel. To actually show up correctly, let's switch back to the person who actuall
y owns this NFT we click it, we want to be able to when we hit OK, or submit, we want to send a transaction to update the price of our NFT here, so what we can do is in our input will have a label called on change equals and this is the function that will call whenever this updates. So we're gonna say on change event is going to be a function. And we're going to create a function called set price to update listing listing with event dot target dot value. So we want to keep track of whatever we'v
e put in here. So when we call the function to update the price, it'll just already automatically have it. So we'll create this function and event dot target dot value is going to be whatever's in this input box here. So we'll create this set price to update listing with will have this be a use date because we are going to want to change the UI based off this so we'll say const price to up date listing with comma set price to update listing with equals use state and then we'll have this be zero
to start or blank. And so now, whatever is in here is going to get updated with this. So now I can do like our console dot log price update listing with Get back to the front end, oops, we need to import use state import, use state from react. Go back to the front end, we click this, we right click Inspect. By type one, we can see 114, we see 14. So let's remove the console dot log now. Now what we can do in here is we can create field called on okay, this is going to be the function that we cal
l when we hit this, okay here, so on. Okay, it's going to be equal to a function, we're going to use a little arrow notation, and we're going to call that update listing function on the blockchain, we're going to need to grab that function so we can use it. So once again, to use that function, we're going to import use web three contract from react mirallas. And as a new hook, we'll say const run contract function called Update listing, equals use web three contract. And this is going to be a fu
nction that we're going to call on our NFT marketplace. So ABI is going to be the NFT marketplace API, which we can get by doing an import, similar to what we did over here. And we actually just copy paste from our NFT box. So we'll do import NFT marketplace API from dot dot constant send it to marketplace that JSON, we're gonna need the contract address, which is going to be an input parameter to our update listing ngModel. So we can even do a comma market place address, copy this place that he
re, that means in our NFT box, pretty soon, we're going to have to pass all these variables to it, but we'll save that in just a second. So NFT marketplace address marketplace address function name, is going to be what it's called Update, listing in our smart contract, and then the params. So if we go to this, we have update listing takes the NFT address token ID and new price do NFT address, which will be NFT address, we'll say token ID is going to be token ID and the new price your price will
get from price to update listing with but will convert it from human readable to ethers. So we'll import ethers from ethers. And the new price will be ethers dot utils dot parse ethers or ether price to update listing with or just in case it's blank, we'll just say or zero. So we have the NFT address the token ID marketplace address in our NFT box, we're gonna have to pass those parameters in here. So we have is visible, we're also going to have token ID, which is going to equal token ID, market
place address is going to equal the marketplace address. And the NFT address is going to equal the NFT address. And as we code and test this something that's going to be really annoying, because it's really annoying for me right now let's refresh our website. And if we click it, this thing pops up. But when I hit X, and I click this, again, nothing shows up. That's because technically show ngModel is still true right now, even though we've exited out. So what we want to do in the NFT box is in o
ur update listing ngModel we're also going to pass it in on close, and we're going to pass it a hide ngModel variable that we're going to create, and right under Show ngModel Set Show ngModel we're going to create const Eid ngModel. And this is just going to be a function, that's just going to say set, show modal. to false, we're going to pass this function to our update modal listing. So we're going to do comma on Close. And in our modal here, we're going to say, on Close. On, cancel, we're goi
ng to do, we're going to call that on close function, or on Close button pressed, we're also going to call that on close function. Now if we refresh our website, click this modal pops up, we click X, click it again, it'll pop back up, because now we're properly setting it to false and then resetting it to true. Now to actually send this update listing function, we're going to pass this another thing, another variable, we're going to pass it on Okay, which is going to be a function as well. It's
just going to call update listing that we just created. Now, it's always a good idea to add an On error. We'd say on error, take that error as a function and console dot log. The error and this needs to be in squiggly brackets like that, but contract address is wrong. So we'll make this contract, con tract address and spell that correctly. Spelled correctly. Now let's go back to the UI, we'll give it a little refresh. Click, this will add one. And we see Metamask pop up. So this is working out p
erfectly. Now I'm going to cancel it, and our apps gonna freak out and stuff. But that's okay, we are doing fantastically okay app popped up like that, which is good. We have this little error handling, which I like to add for all of these run contract functions. Let's also do an on success. So let's say when this does go through successfully, we'll call a function called handle update, listing success. And this will be a function that we'd call when this goes through correctly. So at the top, l
et's make this new function, we'll say const. Handle update, listening success is going to be a new function using the arrow syntax here. And we'll have this setup a new notification for a web application. So for us to do notifications, we're going to use web three UI Kits use notification, this is going to be that same notification service that we used in our last one. So up at the top here, we'll import it, use notification. And then we'll say, right in our component, we'll say const, dispatch
equals use notification. And since we're using notifications back on our app.js, we have to import it in here. So we'll do import notification provider from web three UI kit. And inside of our Morales provider, we'll add the notification provider around our header and our component, so that we have context for this. Now in our handle update listing success, inside this function will say dispatch, say type is going to be success. message will be listing updated, title will be listing updated, pl
ease refresh, please refresh and move blocks. And then position. Top right. And then we'll do on clothes, and on clothes. And we'll say set price to update listing with back to zero. I also I'm editing this a little bit in the future. And I realized that I actually forgot to add the TX to a lot of these handle functions. So on these, whenever we call one of these run contract functions, like we've been saying they have this on error in this onsuccess. Now this onsuccess automatically passes the
result of the call to whatever callback function is there. So for example, up the listing returns a transaction, and we'll pass that transaction to whatever you add to the onsuccess. So now in here, you can actually have it have a transaction as an input parameter. And this would be the transaction that's going to go on the blockchain to you know, update the price. So we actually want to change it from a regular function to an async function. So we can actually do await TX dot Wait, one, because
we don't want to say, hey, success, you know, listing has been updated before the transaction actually goes through. So we want the transaction to go through first. And then we want to pop the dispatch up saying, hey, it's gone through so and then additionally, when we actually call these modells on the on, okay, on the onsuccess, we pass them in just by referencing the name of the function. So we don't do this arrow syntax, anymore like this, we just say, hey, the onsuccess is going to be this
, go ahead and pass your results to it. So that's how we actually call it down here. If you look at the GitHub repo associated with this, you go to components, and we go into these. So in this video, I forgot to add the await TX dot wait one. But in the GitHub repo, we have these. And when I'm demoing things in the video here, the dispatch, it's gonna pop up before the transaction actually finishes going through. So just want to let you know, and back to the video. So now we have a little succes
s thing that'll pop up when we're successful. And the other thing is, when we call this, we are going to omit an item listed inside of our Morales dashboard, the price should actually update in our active item because of our Cloud Functions. So we're going to put this all together now. So we're on the front end. And if the marketplace owned by you will click it. Update listing to 25. We're gonna hit OK, meta masks is gonna pop up. We're gonna go ahead and confirm and ran through an error because
we need to click Metamask I need to reset my account. So I'm going to do settings, advanced reset account. Okay, now let's go ahead Metamask has popped up again, we're gonna go ahead and confirm it closed, the pop up modal, and we got our little notification there. And we can see an activity we have that transaction has indeed completed So now if we go to active item, we give it a little refresh. Right now we see our item listed event. But the issue is that it's not confirmed yet. So what we're
going to need to do is we're going to need to move our blocks by one. So in our NFT marketplace, we're just going to create a new script, a new file called Mind dot Jas, just to move our blocks once, and we're going to say const, move blocks, equals require dot slash utils, slash move blocks, we'll say const blocks equals to const sleep amount equals 1000 async function mine, do await move blocks will do blocks as the parameter and then sleep sleep amount will equal sleep amount. And this will
be a script. So we'll add our copy paste our that same syntax we're doing here just with mine. And now we want to just mine these two blocks. So we'll run yarn, art hat run scripts. Mind that Jas dash dash network, local host. So we're going to mine those two blocks. Now if we go back to our database, we go back to active items, we can see it's been updated because now in our item listed, that 2500 event is now a confirmed transaction, and we get to confirm their excellent. So that means since i
t's confirmed back in our front end, we'll give this a little refresh. We can see the pup is now worth 25 eath. Awesome. So we're updating ngModel is working perfectly. Excellent job. So now let's go to the readme. If you own the NFT, you can update the listing. That's a checkmark. Excellent. Next, what do we want it to do? If you don't own it, you can buy the listing. Okay, so let's go back to our website, let's switch users to a different account, we're probably going to want an account that o
wn some money. So let's go ahead and send this other account some money transfer between my accounts, we'll send 100 eath to account one, confirm on our hard hat chain here. Alright, great. Now we can go ahead and switch to account one, and we have 100 eath. Okay, great. As these pops, each cost less than 100 eath. So that's gonna be more than plenty for us to test this out. Let's go back to this box. Because I think somewhere we said, we did a little handle card click, if it's owned by the user
, have the modal pop up. If not, let's do the by functionality. So to do the by functionality, we're gonna go ahead and do another run contract function. So we'll do const run contract function, we'll call this one by item. And this will equal use web three contract. And this is going to be the ABI for the NFT marketplace. API, the contract address is going to be the market place address. The function name is going to be by item, the message value is going to be the price of the NFT. Because we
need to send that amount to buy the item. And then params are going to be NFT address, which is going to be the NFT address. And the token ID, which is going to be the token ID now that we have this by item on handle card click, we can say okay, said show ngModel is true. Otherwise, we're gonna call by item. And we're going to do on air. Air is going to be a function where we're just going to console dot log the air and onsuccess. It'll be a function where we call handle by item success. So we'l
l create a new handler for this right underneath handled cart click the const handled by item success equals a function. And for this, we'll also have this do a little notification. So once again, we're going to import we're going to import use notification from web through UI kit. We're going to say const. Dispatch equals use notification. And then in handled by item success. We're gonna say dispatch type, success. Message. Item bought. Title will also be item bought. Then pole position will be
top right That's it. So handle card click, if they own it, we're going to show that update listing ngModel. If they don't already own it, someone's gonna buy it. So let's go back here. And I'm currently on an account that does not own these NF T's. Let's go ahead and click it. Our Metamask does indeed show up for 25 eath. That's crazy expensive. Let's go ahead and confirm item has been bought, we'll go ahead and click that little x, we go to our meta mask, the transaction is pending. And it's g
one through. This is fantastic. Okay, our homepage is done, we can show recently listed NF T's if not, you can update the listing. If not, you can buy the listing. And now it's time for our cell page. So the last thing that we need to do is our cell page, let's get this cell page, let's get this done pages, we have our cell NFT page, which right now does a whole lot of nothing. And on our front end, we go here, there's not a whole lot here. And actually, you can list your NFT in the marketplace,
we also needed to add withdraw proceeds. So I didn't add that. But that's probably going to be something we're going to want to allow people to do as well. So let's get started here. So we can remove this head stuff now that we're adding that in our main page. And for us to submit a new NFT, we're probably gonna need a space to add the address of the entity that token ID of the NFT and all this other stuff. So we're gonna need a form to do this, which guess what, we can also grab a form from th
e web through UI kit as well. So we're gonna go ahead in our cell NMC page, we're going to import form from web three UI kit. And we're going to create a new form in our cell page. Now, the parameters we can add to our form, again, you can find them in documentation here, or we're going to add with one of the main pieces is going to be this data piece, which is going to be an object that has a list in it, of all the different fields, we can put in our form. So maybe we'll do our first one have a
name of NFT address. That's gonna be of type text, excuse me, and these are all going to be this is a list of list of objects like that. Now, if we save that, we go back to our cell page, we can now see an empty address and a little Submit button. That right now does a whole lot of nothing. So we have an NFT address, it'll take a text, maybe we'll also do in foot width of 50 percent will have the starting value be blank. And the key of this will be NFT address, what else do we need, we're going
to need to give it the token ID so we'll say name, token ID, type is going to be a number value, we'll start off it's blank. And then the key for this will be token ID. Next, we're going to need the price. So we'll say name will be price. In eath. type will be a number value will be blank. And the key will be price. And we don't need to have to form tags, we'll just delete that second one and have it auto close with one tag. And then in here, we'll do title equals sell your NF T ID equals main
form. So cool. So now we can take an empty address, a token ID and a new price with the title of cellular NFT. Great, that looks really nice. Right now our form doesn't do anything, we probably want to give it the functionality to actually do stuff. So we'll say on Submit, and we'll have to create a new function to actually list our NF T's. So we're going to create a function called approve and list we have to approve our marketplace to pull the NFT from our wallets. So we're going to create a n
ew function, a sync function approven list, which is going to take a data input parameter on our form, when we hit on submit, it's automatically going to pass this data object to our approved list function. So that's how we're going to get the value of the address the value of the token ID and the value of the price. So in our async function approven list, do console dot log, approving the contract, the NFT address is going to come from this data object. So it's going to be data dot data at inde
x zero, or zero with object here is going to be our address that input result. Our token ID is going to equal data dot data. One because again, this one is going to be our token ID that input result. And then the price is going to equal that ethers dot utils dot parse units of data dot data have to the input result, comma ether.to string. So we're going to get the price in eath. In human readable form, we're going to convert it to Aetherium readable form. And then we're going to pass it as a str
ing because this returns a big number, which we don't want. So we have the NFT address, the token ID and the price of the new listing, what we can do now is we can say const approve options equals a little function here, the ABI which is going to be our NFT abi, which we need to import, we need to import both ethers from ethers. And we also need to import the NFT abi, for its NFT ABI from dot dot constants slash basic at A T dot JSON, I just copied and pasted from the NFT box, the contract addre
ss is going to be the NFT address, the function name is going to be approve params are going to be two, the marketplace address, which we're going to define in just a second, and then the token ID will be token ID. Now the marketplace address in our NFT box, we're getting this directly from index, an index is getting it from our database. Now we want our app to be smart enough to be able to grab the NFT marketplace itself, the marketplace address. And if we go to our constants, right now, we act
ually have it in this network mapping. So we're going to want to grab it right up at the top by saying const marketplace address equals network mapping, network mapping of what of the chain ID of the entity marketplace address at the zero with index. So network mapping of the chain ID, which we're going to get honest chain ID equals us Morales. Now chain Id actually comes like we said it's a wax hex form for Morales. So we're gonna have to convert the chain ID to its string readable version. So
we'll say const, chain string equals chain ID. And we'll do a tertiary operator, if the chain ID exists, will parse int of the chain id.to string. So we'll parse it from its hex to a more readable version, and then do.to string. And then otherwise, we'll just say we're on 31337. So chain ID string. So in the network mapping at the chain ID string, dot NFT marketplace at index zero, that's going to be our marketplace address. So we got the marketplace address, this is all we need to call the appr
oved function on our NFT we can now call running contract function for a proof. So we're actually going to do this a little bit differently. We're just going to say const. Run contract function equals use web three contract, you could import just run contract function, and then pass all those options to it like what we're gonna do here. Now we're just gonna say await on contract function. Because this is an async function await run contract function, we're gonna say params are going to be approv
e options. And we're gonna say onsuccess, we're going to do something, I'm going to say on error, we're also going to just do error, little arrow function, console dot log error. Now on success, once we send this transaction, after the Approve goes through, we're going to want to call the list function right underneath this will call async async. Function, handle approve success. And this is going to take the NFT address, the token ID, and the price is it put in parameters. So once this run cont
ract function goes through, we're going to call of handle proof success. And we'll pass it the end of the address, token ID and the price, which will say console dot log. Okay, now time to list and we'll do the same thing. We'll do const list options, equals and this is going to be all the options for calling the list function API is going to be on the marketplace this time. So NFT market place abi, which again, we're going to have to import so I'm going to go back to NFT box. We're gonna copy t
hat line here, paste it in the top. That's going to be the API for that contract address. It's going to be the marketplace address, which we already have. function name is going to be list item. And the params are going to be NF T address of the NFT address, token ID of token ID, price of price. And now we have those options, we can do await, run contract function with params. Of list options, will say onsuccess arrow function, handle list success, which is a function we haven't made yet. It wil
l say on air error. And we'll just say console dot log error. Okay, so let's make this handle list success handle one spell handle correctly handle the success, this will be an async function. And this is also going to call dispatch and make a little notification. So we're going to grab that from web three UI kit, use notification. We'll say const dispatch equals use notification. And now down in handle the success say dispatch, type success. Message NFT listing, title NFT listed position. top b
ar, and cool. And we're also gonna have to grab us Morales from react Morales. So do import us Morales from react or else. So let's import this network mapping. Import network mapping from dot dot slash constants slash network mapping dot JSON. Because I spelled contract address wrong again, good our front end we'll give it a refresh us web three contract isn't defined. Let's get that from react moralss. Well save that refresh our front end. And tada, we're good to go here. Alright, now to test
this out, we're going to want to do is we're going to want to create another script here. So we're back in our heart at NFT marketplace, we're looking at our scripts. And we're going to create a new file just called mint.js. So we're not going to list this time, we're just going to mint it just going to mint an NF t so we can list it ourselves on the UI. And actually, we can just copy our mminton list code, paste it into here, and just remove the approval and the listing code. Boom, remove that,
remove this, remove this. And that's all we need. And now we'll just change the name to mint. Well, we can remove price as well. And we'll change this to mint. And that's it. Now we have a script that we can call, well, we'll just mint an NFT, we can also get rid of the NFT marketplace. Actually, we will probably want the token ID so we can know what it is. So let's do const token ID equals. So let's actually get the receipt we'll do const mint TX receipt, but the receipt, I can there equals th
at. And then I'm just going to copy this from the mminton receipt. Cons token ID equals this, paste it into our mint.js and then a console dot log. Got token ID, string interpolates token ID, hard hat, run scripts, mins dot j s dash dash network, local host. And we're going to mint an NF T. Got token ID six means we know m token ID six, we can list this entity. Let's also add the address. Let's do console dot log NFTL. And if the address is going to be we'll do string interpolation. And you know
what? Let's make this again. Mint dot j s okay cool. Got token ID seven and if the address this so what we can do now we'll grab this NFT address. So from account one, let's go to Account three because that's the account that I've done my imports on now when you switch accounts, we're going to want to refresh the page as the address seven 0.6. Submit Metamask pops up. Give permission Yes. Okay, now it's time to list you now have one pen, okay. Local host list item. We can see all the data and e
verything. Okay, let's go ahead and confirm NFT listed Okay, okay. Okay. Okay. So this is good. Now to get Morales to catch up to speed back in our node. Let's just go ahead and run yarn, RT hat run scripts, mine dot j s dash dash network, local host. We're going to mine those two blocks. And now if we go to our item listed, we'll give this a little refresh. Go to active item. We can see there's a new item listed for 0.6 eath. In our database. This is fantastic. Now that we've listed this, if we
go back to now let's make And let's move on to one more. Let's list the second one, just to see that it's actually working. Okay, token ID eight. Let's grab this address. Let's give this a refresh. paste this in token ID eight. We'll do 0.999. Let's submit. we'll approve this. Yes. Then we'll send it. Yes. Okay, now let's go ahead and mine two blocks. So I'm just going to hit up and go back to mine will run the mining, moving blocks. Okay, great. Now, if we go back home, we'll see there are thr
ee NF T's now listed, we have the original one, that we have those two that we just listed eight, and seven for 0.6 and 0.999. Listed on our NFT marketplace. This is so exciting. Our listing is working correctly, okay. Now, due to the fact that this lesson is already incredibly long, actually decided to cut the part of that and then withdraw a bit, because we don't really learn anything new there. However, feel free to jump back in to get every bit associated with scores, where we will have that
withdrawal functionality for you if you want to implement it. Otherwise, feel free to skip and move on ahead. This is incredibly powerful. And you should be incredibly excited about yourself. If you've made it this far. This is awesome. You just made a decentralized marketplace and then built a front end on top of it to allow anybody to interact with your marketplace. Easily. Huge, huge. Congratulations here. Oh, this is a perfect time to go take a break and celebrate. And this is a great time
to ping me on Twitter to ping me on Twitter saying hey, Patrick, I just completed the NFT marketplace. Full Stack front end part of your Free Code Camp course, I now know how to build full stack front end on top of my smart contract applications. And be so so pumped with yourself because this is so awesome. I can't understate how excited I am that you've made it this far, you are learning and working with a ton of technologies, solidity smart contracts, and front end you are doing full stack you
were doing a lot of stuff here. So you should be really proud of yourself. huge congratulations, be sure to absolutely give yourself a pat on the back. And then get ready to continue to our next section. Now that we've done all of this using our Morales back end, I'm about to switch it up on you, instead of indexing all of our events with a centralized server. Now we're going to learn how to build this using the graph, which is a decentralized event indexer that we can use, a lot of the code is
going to be exactly the same. So instead of us starting from a new, what we're going to do, first of all we can we can close all our local stuff, we can close all of these things, we can close all of our terminals finally, which is really exciting. And in this folder, what we're going to do is we're actually just going to copy everything into a new folder. So I'm going to CD down a directory, we're going to make a new one called next Jas. And if T marketplace, the graph, dash FCC, and all the c
ode for this section is going to be here for front end the graph indexer we're gonna have to make another repo and we'll get to that in a little bit. For all the changes, it's going to be in this section here. So what we're going to do is we're going to make this new folder, and we're going to do copy dash R. Next, Jas and ft marketplace FCC into next Jas NFT. Marketplace, the graph FCC. So we're going to copy recursively, everything that's inside that folder we just created into this new one th
at we're going to make a lot of adjustments to. And this might take a little bit of time to run because we've got a lot of stuff in this folder. And Alright, once we've done that, we can cd into this next Jas and ft marketplace, the graph FCC and do code period and open this up in a new code editor. Or as always, you can do File Open folder to open it like that. Now that we're in here, we're going to learn how to do this exact same project, instead of using mirallas. But using the graph, one of
the things that we're first going to do is we're actually going to deploy our contracts to rink B. So we're going to grab our marketplace, that soul, pull this over, we're going to grab our hard hat marketplace dot soul project, pull it over. And first, we're going to run our deploy script on rink v. So hopefully, you've got all your deploy stuff set up correctly, so that all the arguments can go through correctly for rink v as well. So we're gonna go ahead and run this yarn, hard hat deploy das
h dash network Rinkeby. And to make sure that it's going to work for Rinkeby. Let's check our hard hat config. Okay for networks, looks like I have my Rigby stuff in here for networks. Okay, I've got my RPC URL, which I'm getting from my environment variables. If I have a private key, I have a private key, which I'm also getting from environment variables, I have a chain ID block confirmations and save deployments. So let's go ahead and run this. Now we're going to go ahead and be deploying the
NFT marketplace to the Rigby network. And our deploy script also has an ID some verification. So we can verify this as well, you can't really follow along with this section without deploying a marketplace to rink be here. So deploy to rank B, or whatever test net is recommended in this lesson 15 section, and go from there. Alright, great, we've deployed our NFC marketplace. Now we're gonna go ahead and deploy our basic NFT. And once these are done deploying, we can start updating our front end c
ode to work with the graph instead of mirallas. Okay, we've verified everything to which looks great. Now we're going to verify our basic NFT. And we've have it verified. Awesome. So now we have an NFT marketplace deployed to ring P, and a basic NFT deployed to rink B. And both of them are verified. So be sure to take note of those, because we're going to need them when we're moving over to our the graph section. So now let's grab our code editor titled next Jas and ft marketplace, the graph. An
d let's get going. Now, we just deployed that to rink B. But we forgot to add some code in here to update our network mapping. However, if we go back and we open back up code dot dot, next Jas NFT marketplace, FCC, in the network mapping in here will now have a new entry for rink B, if we did it correctly, let's copy this network mapping and paste it over in our network, our next GS and ft marketplace, the graph section, or you can just manually add your new entry. Right. So you want to add netw
ork ID for network marketplace. And the address of that network marketplace that you just deployed, is we're going to delete this Cloud Functions bit. Goodbye, because since we're not working with the server anymore, there's not gonna be any cloud functions or any back end to run. So we're gonna move that to trash goodbye. Next, we don't need FRP anymore, because we're not going to be connecting our local blockchain to the graph, we're only going to be working with the test net here. So let's go
ahead and delete that. Goodbye, what's next in our pages, and our app dot j s. Right now we're connecting to a Morales provider like this, we're going to switch this back to initiate allies on Mount, this is going to go back to being false, we're no longer going to connect to our Morales database like this, we're just going to use the hooks again. Now with that the only thing that's going to change is our index.js. Right now, in our index.js, we're getting our list of NF TS from our Morales que
ry. So we're going to change this, let's update our readme. So we're gonna say instead of reading the events from ralis, we will first off we're going to index them with the graph. And then we're going to read from the graph. So the question is, what is the graph. So the graph is going to be a decentralized layer for storing event data. So there are all these blockchains and all these different storage networks. And the graph is and the graph is a network of different nodes that read from blockc
hains and index this data, and it exposes an API for us to call we can read that data. Rather than just myself. We actually have nattered Abbott, who can explain it a lot better than I can take it away. And at. First, I'd like to thank Patrick for creating such a wonderful educational resource and inviting me to be a part of it. My name is Nadia dabit. I'm a developer relations engineer working with the graph. The graph is an indexing and querying protocol for decentralized networks like Aetheri
um IPFS, dozens of other EVM compatible networks, as well as near and then the future cosmos and Solana. Using the graph developers can build and publish open API's called subgraphs that they can then use in their applications to enable better querying capabilities of data stored on these networks, including features like filtering, sorting, relational data, and full stack search. subgraphs live in between the blockchain and the UI providing an important piece of software infrastructure, a flexi
ble performant and decentralized API layer, and the traditional tech stack databases, servers and API's query filter, sort paginate group and join data before it's returned to an application, usually via some type of HTTP request. These types of data transformations are not possible when reading data directly from Aetherium or other blockchains. Before the graph teams had to develop and operate proprietary indexing servers. This required significant engineering and hardware resources and broke t
he important security principles required for decentralization, how we interact with and build on top of blockchains it's much different than what we are used to in the traditional tech stack. In a blockchain data isn't stored in a format that can be easily or efficiently consumed, or retrieved directly from other applications or front ends. The problem is that you need to have the data indexed and organized for efficient retrieval. Traditionally, that's the work that databases and web servers d
o in this centralized tech stack. But that in indexing layer was missing in the web three stack. Let's take a look at a couple of other examples of indexing in the real world. Search engines like Google crawl the internet indexing relevant data making it available for users to search via their web interface and other API's. Without this indexing layer, it'd be hard for us to know where and how to find relevant information across the web. Another similar analogy is a library. Using an indexing sy
stem like the Dewey Decimal System, we know where to find the book that we're looking for without having to go through book by book looking throughout the entire library. The graph serves over 2 billion queries per day to many different types of web three applications, including apps in the defy gaming and FC space. Before we dig into any code, let's take a look at how to build a sub graph. To get started, you would go to the graph.com and create a new sub graph and the graph user interface. You
would then use the graph CLI to scaffold out an empty sub graph boilerplate that you can then update with your own contract information. In your subgraph configuration, you would define things like your data model, the network, the contract addresses and other configurations that are specific to the data that you would like to index. For our data model, we use Graph QL, schema definition language defining top level types as well as fields within those types. When we're ready to deploy our subgr
aph, so we can begin testing it out and using it in our application, we can use the graph CLI running the deploy command. Once the subgraph is deployed and the data begins to be indexed, we can start testing it out using the graphical interface directly in the graph dashboard. When we're ready to start queering, our sub graph from our application, we can use the API URL that's been given to us by the graph along with any Graph QL query. If you'd like to learn more about the graph, check out the
graph.com as well as Graph Protocol, Twitter, the docs at the graph.com/docs, or our Discord at the graph.com/discord Thanks matter. And now that we have a better idea of what the graph is, we can actually start building with it. Now if we were to try to run this app as it is, it obviously would fail, right, because index.js, right now is reading from mirallas instead of from the graph. So like it says in our readme, first thing we're going to need to do is we're gonna need to index from the gra
ph, and then we can just this project to read from the graph. So let's go ahead and learn how to build our sub graph. In order for us to tell the graph network to start indexing the events from our contract, we're gonna go to graph.com, we're gonna go to products. And we're going to go to sub graph studio, if you go to products, the first thing you see is the Graph Explorer, these are already existing sub graphs. And if you go through here, you'll see a lot of incredibly popular decentralized pr
otocols all have different sub graphs, hosted service is going to get discontinued at some point. So we're going to skip there. So let's go to sub graph studio, this is going to help enable us to create a sub graph for other nodes to start indexing our events. So we're gonna go ahead and connect our wallet with meta mask. And I'm going to choose account one here, next connect, and we're going to want to switch off of Hardhead. Local, over to the Rinkeby test network. And I'll go to Account one h
ere. And we're going to get a signature request from the graph summary to the website that we just built. The subgraph website has some signings functionality with a database on the back end. So we're seeing in real life, exactly the methods that we just used. So instead of signing with Morales, they're just have their own custom sign in here. So we're gonna go ahead and sign in so that the graph website knows that it can interact with us. And we can go ahead and enter our email if we want. I'm
gonna go ahead and skip. And you'll even get a little notification here saying only subgraphs indexing Aetherium or main net or Rigby can be created in subgraph studio. So let's go ahead and create a subgraph. So we're going to pick a cerium Rigby and the subgraph name is going to be NFT marketplace. We'll go ahead and hit Continue. Now, this is going to be our dashboard for creating our sub graph. And there's a ton of instructions over here and documentation that we can view to get started, I'm
going to add this documentation to the GitHub repo associated with this course. So this NFT marketplace sub graph is going to need its own git repository itself. So what we're going to do back in here is we're going to CD down, we're going to make a new directory, and we're going to call it graph. And if T marketplace, FCC, we're going to open that up as well. So code graph NFT, marketplace, FCC, or file open graft code marketplace FCC, and in this window, we're going to build our subgraph. Loc
ally, we're going to build our subgraph and push it up to the subgraph studio. And in here, there's a whole bunch of instructions that we can follow along with to go ahead and install. The first thing that we need to do is install the graph command line interface. And we want to install this globally. So I'm going to copy this part here. Come back to my terminal Oh, yarn, global ad and paste that in. It's this command line that's going to help us build a graph and build instructions for the grap
h to actually start indexing our events. Now that we've installed the globally, we can initialize our graph code. So we can copy this line. And we'll run graph a knit dash dash studio NFT marketplace and hit enter. The protocol is going to be Aetherium, or subgraph. Slug will be NFT. marketplace. We want the directory to be here, but it's saying directory already exists. So we'll just give it NFT marketplace. And then we'll move it after this. And this is on the Rinkeby. Test net. And now we wan
t to give it the contract address. So we want to grab that address that we just deployed. And it should be now in our network mapping. So we're going to grab that contract address that we just deployed, and paste it in here. Like so. And since we've already verified on ether scan, it automatically grabs the ABI for us from ether scan, we'll give it the contract name, which is the NFT marketplace. And it's going to give us a whole bunch of boilerplate code in this NFT marketplace directory. And t
his might take a couple of minutes. Alright, awesome. So now that it's done, we see subgraph NFT marketplace created in NFT marketplace. Now, I don't want it to be in the seller folder. So what I'm going to do is I'm going to move it down a directory, but you can leave it where it is, if you want, I'm going to say move, I'm going to say move NFT marketplace, star to dot slash. Now everything inside of NFT marketplace will be in this current directory. And then if the marketplace will be empty. S
o with that, I'm gonna go ahead and delete. And if the marketplace. Alright, great. Now let me walk you through exactly what's going on here and what these files are that we just created. So our first folder is going to be API's. In order for the graph to index and read our contract index our events, it's going to need the ABI of our events. So we've got the ABI of our entire marketplace, from ether scan, if we didn't verify an ether scan, we can just create this API folder ourself and add the N
FT marketplace JSON in here. Now we have this generated folder. This is an auto generated file. He even says at the top, do not edit this file directly. You can kind of think of this as the build folder, or where we compile graph code. Node modules, of course, is going to be node modules and dependencies. SRC is going to be where we define and we tell the graph, how to actually map and how to actually work with our contract. And it is a TypeScript file. So for all of you who have been just doing
this in JavaScript, I will have to teach you a little bit of TypeScript just to get through this part. Then we have networks dot JSON, which gives us all of our network information about which networks, what are the addresses, and what are the different contracts that we're going to be indexing, package dot JSON, which of course is just a normal package dot JSON. And it's got some graph scripts already built in schema dot graph. QL is going to be our Graph QL schema. So this is also going to be
how we tell the graph how to actually work with our events and index our events. And if you're familiar, the schema follows the Graph QL syntax. So if you've ever worked with Graph QL, before, it's going to be the exact same way, graph. QL is a query language for your API. And instead of being kind of a relational database, it can query in a more graph type way, I'm not going to go too deep into how it actually works behind the scenes. But if you want to learn more, I'm going to leave some docs
in the GitHub repository associated with this course, the sub graph dot Yamo tells our subgraph how to combine all the files together. So we have data sources, data sources, where they're coming from different addresses, different entities or events, the API's where to grab our files from different event handlers, which we'll talk about in a minute. And then the main file, which is going to be our mapping.ts, we have a TS config, which is a configuration file specific to TypeScript. And then of
course, we have our yarn dot lock. With all this information with all this code, we are now going to update all this code to tell the graph to start indexing our events. So we can read our events from the graph in a decentralized context, as opposed to from a centralized database. And after we build everything, we're going to run through this off and deploy code, which is to authenticate ourselves, and then deploy our code to the graph to start indexing. So without further ado, let's jump in. A
nd let's do this. So one of the first things I'm going to do, I'm going to add a highlighter for these dot Graph QL files. So in our extensions, we're gonna look at Graph QL. And we're gonna stall this Graph QL extension. Now that we've installed it, if we go back to schema dot graph, QL, we've got it with some colors now, which is exciting. So this schema dot Graph QL is going to define what entities we have in our contract if we were to be analogous to mirallas. These are going to be how we're
going to define what our tables are going to look like. And these are going to be our events. plus that active item table that we created. So we're not going to have an example entity though, we're going to have a type active item. And this is going to be an add entity. So these are the different types we have in our graph that we can actually query on, our main thing that we're going to want to query on is same as before, it's going to be our active items. And then inside of our active items,
we're going to tell the graph, what parameters each one of these active item types has, well, it's going to have an ID of type ID. So the variable is ID of type ID. And you can read more about the different types in the graph documentation. And this exclamation mark means it must have an ID. So every active item needs to have and will have an ID, we'll say there's going to be a buyer, which is going to be an address, so that's going to be a byte and the buyer could be blank, right? It could be t
he 0x 000, we're going to have all of our active items have a 0000 dot.if. If no one has bought yet, we're going to have a seller, which of course is also going to be a bytes because it's going to be an address, we're going to have an NFT address. So the address of the NFT, which will also be bytes, we're going to have a token ID which isn't going to be bytes, this is going to be of type big int, and then we're going to have a price, which is also going to be a big int. Now price we're going to
leave as not required for price, we're just going to have price be nullable. So price can be null. So we have an active item. Awesome. What else are we going to need? What what other tables do we have in Morales? Well, we're going to need type item listed. And this is going to be at entity is going to need an ID, it'll have a seller. Whenever an item gets listed, it's going to have a seller right, which is going to be a bytes again. And if the address the address of the NFT, which will also be b
ytes, the token ID, which is going to be a big int, and then the price, which will also be a big end, we're gonna need a type item cancelled at entity which will have an ID seller an NFT address. And a token ID will be a big end. And then last type item bought will be in that entity is going to have an ID ID. It's going to be a buyer bytes. And then of T address a bytes and a token ID again, and then a price of beginnt. And with Justice Information, we've defined what we want our subgraph to kee
p track of wants to keep track of item bought events, item, cancelled events, item listed events. And then we're going to make this new active item table similar to what we did with mirallas. And it's going to be some function of these these other three events. And now we're done with our schema dot graph. QL. Awesome. So what do we do now we're going to need to tell our sub graph to actually listen for these events. So what we can do. So what we want to do to tell it how to listen for these eve
nts, is we're going to go to src mapping.ts. It's this mapping.ts file that's going to tell our subgraph how to actually map and how to actually store all the event information that we have. If you look in it right now, it might even give you kind of a sample event. So it says Export function, handle item event. This is what Maya says right now, it takes as an input parameter event item bot. So this is saying whenever an item bot event occurs, do this handle item bot function. So anytime item bo
t happens do this handle item bot. And we're actually getting this item bot from our generated NFT marketplace from some generated code. In the graph. If we run graph code Gen. This graph code Gen command grabs all the stuff we have in the schema dot Graph QL and puts it in this generated file. Now that I've run graph code Gen, you'll see in here there's an item bot class, you see there's a schema, that type script. And actually we can even find that new active item class that we created in our
schema. So anytime you update schema dot Graph QL, you're always going to want to run graph code Gen, so you can update those types. And if this failed, it means that you messed up something in your schema dot Graph QL. Now in our mapping.ts, we're actually importing item bought item cancelled item listed from generated and if the marketplace and if the marketplace from our generated code. These are going to be our events. And we're not going to need to do anything with the NFT marketplace. We'r
e just going to need our event information. For now. Let's go ahead and just delete everything inside our handle item bot or whatever sample is given to you. So we're importing a or events from our generated code. And then we have this line here, which we're going to change in a second. So again, we have these three functions handle item bought, handle item canceled and handle item listed. Whenever we get an item bought event, we're going to do this function. Whenever we get an item canceled eve
nt, we're going to do this function. And all this code is defined in our sub graph dot Yamo. You can see the different entities here in a bot item cancelled item listed, and the event handlers. So it says, okay, anytime this specific event gets fired with an index address, an index address index, YouTube 36 in YouTube had six call handle item bought, which again, we're getting in here handle item. But so that's exactly how this works. So let's figure out what to do when an item bought event trig
gers. And I think that item bought item cancelled item lists it is a little confusing. So I like to change this to item bought as item bought event item cancelled as item cancelled event item listed as item listed event. So I'm just changing the names of these three that are imported from NFT marketplace. And now I'm going to change event item bot to item bought event. Event item cancelled to item cancelled event and event item listed to item listed event. Okay, great. And we're just going to re
move this line for now. And we also don't need this line at the top at the beginning, we will in a minute, but we'll delete it for now. So here's our minimalistic code here. So whenever we list an item, what do we need to do? Well, we need to save that event in our in our graph. And then we also need to update our active item, exactly as we did with Morales. So first thing that we're going to need to do is either get or create an item listed object. And something that we need to know is that eac
h item needs a unique ID. And we actually need to create that ID. So one of the first things I'm going to do is going to create a function called Get ID from event params. And it's going to take a token ID and here's where TypeScript comes into play a little bit. In TypeScript, we actually need to define the types of our different parameters. So token ID is going to be a big int. And we'll also take an NFT address, which will take in a type of address. And we also need to say what return type or
function is going to give, which we're going to return a string, we're going to create an ID from event params. And it's just going to be a combination of the token ID and the NFT address. The combination of these two will give a unique ID for each one of these types of event. So we're just gonna say return token ID, and token ID has a function called to x string, I'm gonna say plus, and if T address.to X string, like so. And big int an address, we need to import from at Graph Protocol slash gr
aph TX. It already imported big enough for me. So I'm just going to add address in here is the two special types that come from the graph. And then string is built into TypeScript. Now that we have a way to get a special ID for each item in our function here, we have to now either get or create a new item listed. Now right now we have an item. But event we don't have an item bought object. So the item bought object is going to be what we save, the item bought event is just the raw event. So we h
ave to create an item bought object from our item bought event. And in TypeScript, these are going to be two different types. So we have to import these item by objects. So those actually get auto created from generated schema. In here we have active item, we have item, we have an item bought class, we have an item cancelled, etc. So we're gonna have to import those types from there. So we can say, import, item listed, comma, active item, item bought an item cancelled from dot slash, generated s
lash schema. Let's go ahead and get or create an item bot object. So we'll say let item bot equals item bot dot load. And this is how we load an item we load its unique ID by calling this get ID from event params dot load, get ID from event params. And we can pass event dot params. That token ID because an item bot event is going to have a token ID and event that params.nf T address. Now I know we probably should have done handle item listed first but we're doing item bot first. Since we're buyi
ng an item, we probably will also have an active item as well, right? We haven't made yet an item listed. But this is going to be similar to what we did with Morales. So we know that every time we live Certain items will also list an active item. So we'll say let active item equals active item that load. And we're going to do this exact same thing. So I'm just going to copy paste it into here. And even though these are going to have the exact same ID, it doesn't matter because they're the same I
D across different types. Now we're gonna say, if there is no item bot, we'll say item bot equals a new item bot object. And we'll give it an ID, which is going to be exactly our ID giving parameter here, get ID from events, and pass that there. So we're going to create a new item bought here. And now we're going to update all its parameters. So back in our schema dot graph, QL. An item bought has an ID, buyer address, token ID and price. So we're gonna say, item bought, that buyer equals event
dot params dot buyer, item bought.nf T address equals event.params.nf T address, item bot, dot token ID equals event dot params dot token ID. And that looks good. And our active item will be from item listed, and item listed should give it all these parameters, except for it won't have a buyer. So we just need to update the buyer on our active item. So we'll say active item, dot buyer, we'll do a little exclamation mark. This is some TypeScript stuff, saying we will have an active item. Don't wo
rry too much about it if you're unfamiliar with TypeScript. And we'll say that equals event dot params dot buyer. And now similar to Morales, we're gonna do item bot dot save and active item with an exclamation mark again, that save and this is how we're going to save this item bought event as an object in our the Graph Protocol. And also, we're going to update our active item. So this is our full function of handle item bought. Whenever somebody buys an item, we update a new item bought object,
and we update our active item to be a new buyer, we're not going to delete it from our active items list, we're just going to update it with a new buyer. And we'll just say if it has a buyer, that means it's been bought. If it doesn't have a buyer, that means it's still on the market. Awesome. So now that we've done our handle item bot, let's now do our handle item listed, which will hopefully make our handle item bot a little bit easier to understand. So for handle item listed, we're going to
do the same piece here. So we're going to say let item listed equals item listed dot load. And we're gonna do the exact same thing as what we did for all these will do get ID from event params. Like so, get a different event params. And we're gonna say let active item. And this line is going to be exactly the same as up here. So I'm just going to copy paste. So we're saying, okay, great, grab our item listed, and grab our active item, see if those objects already exist. I will say if there is no
item listed, which there shouldn't be, we'll go ahead and create a new one, we'll say item listed equals new item listed. And its ID is going to be from this function that we created are unique IDs. Now, unlike what we did above, we're also going to say, if there is no active item, then we're going to create a new active item, right? Because we're listing an item, it shouldn't be an active item. Now this functionality is going to make a lot more sense here, right? Because if we're updating the
price of an item, active item will already exist. If it's a brand new listing, though, active item will not exist. So we'll say okay, if it doesn't exist, okay, that means it's a brand new listing, we'll say item listed equals new item listed, and then we'll give it an ID. That's the same ID methodology, paste that in. So now all we got to do is update these new objects. So I will say item listed that seller equals event dot params dot seller. And I'm just going to copy paste this line. Because
this is just gonna be active item dot seller now. Oops, see me and then it'll make this active item. active item instead of item listed. And what else comes with item listed? Well, let's go to the schema item listed has an NFT address, token ID and a price. So okay, so let's add those. item listed dot NFT address equals event.params.nf T address. Copy paste this line because it's gonna be the be the exact same for active item. Now item listed that token ID equals event dot params dot token ID. C
opy paste this line. Same thing for active item. Item listed dot price equals event dot params dot At price, copy, paste this line for active item. And then we just say those two. So item listed that save active item. Save. So in our protocol here, if it's already been, if there already is an active item, then we just go ahead and we get that active item. This would be for a listing that we're updating. If not, we make a new one. We update it with whatever came in through the event. And then we
save it to our graph protocol. Okay, perfect. Now we only have one left, item cancelled. So let's figure out how to do item cancelled, it's going to look really similar to item bought. So we'll say let item cancelled equals item cancelled that load. Again, we're going to do this exact same Id get our that we're doing for everything, we'll say let active item equals, and I'm going to zoom out a little bit less active item equals active item dot load. Or do this exact same thing here. Boom. And th
en we're gonna say, if not item cancelled, which there shouldn't be because this should be the only item canceled event here. We'll say item cancelled, equals new item cancelled. And we're gonna give it an ID using the same ID methodology we've been using. Now this is going to look a little bit different. We're gonna say item canceled, that seller equals event dot params dot seller. So far, so good. Item canceled dot NFT address equals event dot params dot NFT Address item canceled dot token ID
equals event dot params dot token ID. And then finally, we are going to change the active item a little bit different than what we've seen. active item exclamation mark again, ignore if you're confused by that dot buyer. And we're going to update the buyer to equal address dot from string. We're going to give it what's called the Dead address. And that's this right here. 0x 1-234-567-8910 1112 1314 producing 718 1920 21 to two to three to 45 to 67 to 8930 3130 230-334-3536 zeros lowercase d, upp
ercase E, lowercase A uppercase D, this is known as the dead address. And this is how we're going to decide if an item is still on the marketplace or not. Or if an item has been bought or not. If we have the dead address as its buyer, that's going to mean that the item has been cancelled. And that's how we are going to be able to tell that an item is on the marketplace or not dead address means it's been cancelled. An empty address, which is what will happen for handle item listed means it's on
the market. And an actual real address means that it's actually been bought by somebody. So the way we can tell if it's on the market is it's 0x 0000000. Because the data address is obviously going to be different than than all zeros. The data address is a commonly used address kind of as a burner address that nobody owns, then we can just say, item cancelled that save an active item that say active item, exclamation mark dot save and perfect. Our mapping file is now completed. We now have three
different functions to define how to handle when items are bought events, how to handle when items are cancelled event and item listed events. And if you're confused, remember all the code for this is available on this the graph section of my GitHub. So you can just follow along with the code here, if you ever get lost or need help. And with that, we're almost ready to tell our subgraph to start listening to our contracts, there's just at least one more thing that we want to do. So in our sub g
raph dot Yamo, we'll see source address blah, blah, blah, this is telling us to start indexing events since the beginning of Aetherium. Now we don't really want it to do that, because it will take a really long time, we want to tell our subgraph Hey, you don't just start from beginning of time, you just need to start from right before our contract was deployed. So we can add what's called our start block to tell it what block number to start deploying. Now if we have our address, which we do rig
ht here, we can copy it, we can paste it on to the rink fee, ether scan, paste it in here, or really any block Explorer, and we'll see what block number our contract was deployed. And it looks like it was this block. So I'm going to copy that address, go back to my code and say starting block, it's going to be right here. Starting block is going to be when it was deployed, minus one. So we're gonna go right before we deployed our contract, we're going to start reading any event that is indexed f
rom it. Now if you just deployed this, it might not have any events in it at all, which we're going to fix in just a minute so don't worry, but with that all the instructions for how to build Our sub graphs are ready to be deployed to the graph, start our indexing and start working with our instructions in a decentralized context. So what we can do now is back in the graph, we actually have the auth and deploy code right here, we can copy this, this graph auth dash dash studio, which is our depl
oy key on how to deploy. And we can run this in our code editor. So we're going to paste that in here, graph off dash studio, hit enter. And we're gonna say deploy key set for the graph. So this is just setting us up so that whenever we push our code, it's going to push it to this sub graph configuration that we've made on their site to help us deploy automatically. Now we can do, we don't need to enter the subgraph, because we've already moved stuff down, is we'll build the sub graph, we'll run
graph code Gen, we can just run graph kojem, which again, is just going to make sure our schema dot Graph QL looks good. And then we're going to run our graph build. And this graph build command is going to compile and run all of our sub graph stuff, everything in mapping that JSON all our generated code. And it's going to put this into a real build folder, the generated folder has kind of like a pseudo build folder. And then we have a real build folder. So the generated is just to build some t
ypings for our TypeScript. And it's this build folder, this real build folder, is what we're going to actually be deploying and sending to the graph. And we can actually deploy our subgraph. Now, with graph deploy dash s studio. And if the marketplace, which we're going to run right now, now is going to give us a version label option, which we're going to give it the 0.0 point one, since this is our first version, and it goes ahead and starts deploying it to the graph, we also get to upload our
sub graph to IPFS. And we have a little hash right here for IPFS for a subgraph that we could look at. But now if you're successful, we now have this build completed thing. And we have these sub graph endpoints for queries and subscriptions. So we can actually start querying and subscribing to our sub graph. But if we go back to our site here now and we hit refresh, we can now see status deployed, we can see that we're sinking. And now we have some nodes that are listening for our events to be e
mitted here, which is incredibly exciting. We can go to logs to see if anything went wrong. And right now it's just indexing, it's listening. It's going through all the different blocks in the blockchain, listening for our events. And then we have a playground here where we can run some queries to see different events and the different responses from our Graph QL, which right now, it's totally blank, because we haven't done anything yet. So once again, let's pull up our hard hat and ft marketpla
ce code, or open it up in a new terminal, whatever you want to do. And let's go ahead, and let's run our mminton list script. But for rink B, so we'll do yarn, hard hat, run scripts, mint, and list item dash dash network Rinkeby. So we're going to mint an NF T, right, this is going to be to transaction, so we're gonna have to wait a little bit, and then we're going to approve the NFT. And then we're going to list it on our marketplace. And once it's listed, it's going to emit an item listed even
t. And we should see now we have an active item and an item listed data in our Graph QL. Now you can learn more about now what you see here on the left hand side is what's known as a Graph QL query. Now, we're not going to go over how to do these, but I'm going to leave some links in the GitHub repository. If you want to learn how to do more of these queries, these are going to be similar to what we saw with Morales. But instead of them being kind of regular table lookups. They're in Graph QL sy
ntax, and the results of our query, end up being over here, we can see more information about our schema all the way to the right over here. But if we look at our code, now, we've made the NFT approved it we've listed it on our marketplace. So now if we go back to the graph, and we run this query, and we do a little refresh on our NFT marketplace, we might have to wait a few minutes for the graph to index these new blocks. But in our playground, we should see the show up as a query. If you don't
automatically get these you can pause the video to write these into your Graph QL playground, right? So after a few minutes, refresh on ether scan, I can see that list item transaction has gone through. This means we've emitted a new event. So if I come back to my playground, and I hit play here, oh my goodness, we can see we have active items. And we see we have item listed. This is fantastic. That means in a decentralized context, we have a off chain service that is indexing our events for ou
r contract so that we can update our front end and we can update people in a decentralized way. This is so exciting. Awesome, so now that we have this all set up, we can finally go back to our next JS project or next Jas NFT marketplace the graph FCC. The reason we did all this is because right Now in our code base for our next Jas NFT Marketplace application, we're reading from a Morales database, which we're not going to do anymore. Instead of reading from a Morales database, we're going to re
ad from the graph, let's go ahead and learn how to update our code our index dot j, s to read from the graph instead. So to highlight this, to show this, we're actually going to create a new page, a new file, and we're just going to call it graph, example, dot j, s. And we're just gonna make this a really minimalistic page to show you how to do a graph query. So similar to index dot j, s, we're gonna do export default graph example. It's going to be a function, or default function, graph example
. And we're gonna use this tool called Apollo client, copy, paste it over. And we're going to add it with yarn, add dash dash dev at a P O ll O, slash, client, or excuse me, not Dev, because we do need this on the front end. So yarn add at Apollo slash client. Oh, sorry, we also need to do yarn, add Graph QL, we need to add both of those. And it's this Apollo slash client, which is how we're going to make queries to our newly created graph. QL. So we're gonna say import the use query hook, from
this package we just installed from at a P, O, ll o slash client. And we'll also import G QL. So to create a new query, we'll say const, get active item equals g QL. And we'll add this backtick here. And we'll add all of our Graph QL stuff in here, this is gonna be equivalent to this, this is Graph QL. Syntax. And we're gonna be putting this Graph QL syntax into our code base here. But we only want to get the active items. So how are we going to get the active items? Well, we can actually build
it over here on our playground first, and then add it to our code base. So we'll say we want to grab the active items, we'll grab the first five, and then we'll say where the buyer is going to be 0x 12345678. We're saying where the buyer is empty. So we're grabbing the active items where there is no buyer, and then we're going to do and then we're going to get the ID, the buyer, the seller, the NFT address, token, ID and the price from that. And if we hit run, we get our active item here. So we
see here, the buyer is this exact 0x 12345678 Because it gets defaulted to zero when there is no buyer. And this is why for item cancelled, we updated the buyer to be that dead address. So if it's bought, it won't be active anymore. And if it's cancelled, it also won't be active anymore. Now we can copy this query and paste it into our code. And now we have a Graph QL query that we can use for our graph example. Now in our graph example, we'll use this query with this use query hook. So in expor
t default function, graph example, we can say const. And it comes with a whole bunch of stuff like loading error, and then the data returned equals, use query. And then we'll just pass it this Get active item, or get active items, let's put an S on it, get active items. And then we can just return return a little div. And we'll say hi in the div, and then we'll just do console dot log data. And then now we'll go back to our app.js, where we're wrapping everything in a Morales provider, we also n
eed to wrap everything in an Apollo provider. And we need to initialize it kind of similar to how we initialize connecting to our morale server, but we're going to initialize connecting to our Graph QL. So we're gonna say import a P O ll o provider, a P O ll o client, and in mem ory, cache from at a P O ll o slash client, like that, and then we'll have to initialize this so we can delete the morale stuff. We'll initialize this client by saying const client equals new a P O LL. O client, and we'l
l give it the parameters here. And you can find this all in the Apollo client documentation will say there's going to be a cache to help when we do refreshes and stuff we'll say new in memory cache, and we'll say comma URI, a que where we're going to be connecting. And this is where we're going to add the API for our sub graph. So if we go back to details, we can see temporary query URL and this is a rate limited temporary query, because this is just a test net, and we're going to copy this, go
back to our code. And we're just going to paste it in here. So whatever you have for temporary query URL, and your sub graph studio, that's where you're gonna paste in here. Now, this client tells our Graph QL, where it should be making those queries. And we're gonna make it to here. Now, this starts with HTTPS. So is this centralized? Yes, because we are directly calling the graph website. However, all the data is still gonna be stored in this decentralized graph indexer. And kind of similar to
what we did with IPFS, we're doing this kind of as a gateway to make it a lot easier for us to connect and read the data from the graph studio. However, in the future, as more protocols and more browsers adopt the graph, and IPFS, this will become a lot easier inside of our Morales provider, but outside of our notifications provider, we're gonna say a P O ll o provider, and then client equals client. And then we're going to copy the closing tag, and put it around the notification provider and p
ress Save. Now I'm gonna save our front end, now we're going to try to run our front end. And we're gonna have to change some stuff in here because it's going to freak out. So we're gonna run yarn Dev, for new front end. So we're gonna go to our localhost 3000. And it's going to totally freak out, because we still have some morale stuff in here. And that's totally okay. We, of course, we don't need a hard hat Node running. Because we're on a test net, we don't need to be synched with Morales, we
don't need to be doing any of that stuff. Because we're working with a test net, right now, it's actually not freaking out, which is great. But it shows obviously nothing for recently listed. So what we're going to do now is we're gonna do slash, graph example, and hit enter. And we can see Hi, show up. But if we go to inspect, and we go to console, a console here, we can see an object here of active items, which is returned from the graph with buyer ID, NFT, address price and all this stuff in
the air. This is fantastic. So okay, okay. Okay. So all we have to do now is we just have to update. So let's go ahead, we'll kill our server. For now, all we have to do is update, instead of use mirallas query, we're going to delete this. And we're just going to query from Apollo query from our Graph QL. And everything else stays the same, right? Because our NFT box, and all the rest of the code that we worked with, will still work exactly the same. So first, we just got to get our address. So
we're gonna say import, same as Sell, sell NFT, import the network mapping, so I'm actually just going to copy it. So we're going to import network mapping from constants, network mapping dot JSON. And now we can say const. Marketplace, address equals, and we're going to get the exact same way we did this and sell NFT to, so we're going to grab this line getting the chain string, we'll paste that in here, which means we're going to need to get chain ID from user Morales. And then we're gonna ge
t the marketplace address like this. So we're going to copy that line, paste it in here. Okay, great. Now we have the marketplace address. So now we're just going to do const. Loading error data, which we can do listed. And if T is again, equals, use query, and we can do that get active items. So what I'm going to do is I'm going to create a new file and constants, we're going to pass that get active items thing in their new file, we're just going to call it sub graph queries, dot j, s. And then
here, we're gonna say import G QL. From at a Apollo slash client. And we'll say const, get active items, equals g QL backtick. And exactly what we did in that great, let's go back to the graph example, we'll just copy that whole line actually pasted in here. And now we'll just do export default, get active items. And we'll import this query from sub graph queries into our index dot j s. So we'll say import, get active queries are skimming apt get active items from dot dot slash constants slash
sub graph queries. And now in our use query will pass Get active items, which should return are listed NF Ts. So now, we'll change this from fetching listed NF Ts to loading, loading, or we don't have listed NF Ts. So if it's loading or we don't have listen if TS then do loading, otherwise, we're going to do another mapping, but the return of the Graph QL is going to be a little bit different. So instead of listing MTS dot map, it's going to be listed NF T's dot AQ two have items, dot map and f
t, and then we're going to get price. And if the address token ID, we're not going to get marketplace address, but we'll get seller from NFT. And it's not going to be returned with attributes. So we can just do console dot log NFT instead. And then we just pass all that stuff normally to, to that NFT box exactly the way that we did before. So really, we're all we're doing is we're swapping out the query methodology here, price is going to be from price price is going to be from the query, and ft
address is going to be from the query token ID from the query marketplace address, that's also gonna be slightly different, we're going to get that from our own config seller is going to be from the query, and then the key is going to be from the query as well. So now if we save that, if we restart our website, with yarn Dev, and we go back to our homepage, we should see everything exactly the same, except for the images being pulled from the graph, instead of being pulled from her Alice. Let's
go back to our front end, we'll give it a nice refresh, close out the console. And we'll go to our homepage. And I forgot to do use query. So let's import use query, import, use query from at a Paulo slash client. Let's save and let's go back and give that a refresh. And oh, my goodness, we now have updated to get our events from a decentralized data structure. That's freaking awesome. Now let's talk about hosting this real quickly, we are using the image tag in here in our NFT box, we are usin
g the image tag in here from next Jas, which comes with some pre processing. So it's a little hard to use on IPFS. So we would need to update the way we do images in order to host this on IPFS. But we still can do that. Some other options we have actually are Morales, we can actually even host our apps on Morales, if we want. We can also use things like for cell or Netlify, or etc, or really any other traditional centralized hosting service. Now, if you want to, I challenge you to update this co
de to make it be able to be hosted on IPFS. So that you'll have an end to end decentralized. And if the marketplace first wanted to make a PR to this code, so that it can be successfully hosted completely end to end on IPFS wins and empty for me. But wow. And with that we are done with less than 15. This is an absolutely monstrous accomplishment. And if you finish this, if you've understood everything, if you've gotten through everything so far, you should feel incredibly proud of yourself. Beca
use this is our last full stack section, our front end section and you're a full stack monster at this point. huge congratulations, you should be super, super, super proud. And definitely take a break, go get a coffee, and get ready for the final stretch of lessons 1617 and 18. Those are gonna go by a little bit quicker. I'm very excited for you take a break, and I'll see you there. Right, welcome to Lesson Six tene, where we're going to be going into even more low level code here. The hard hat
upgrades of course, per usual, our entire GitHub repository is located here. And additionally, we have an optional video that you can watch. If you want to learn more, we're actually going to watch a slice of that video that explains upgradable smart contracts. So let's jump in. Now I'm editing this video much later after I filmed that, 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 th
ose smart contracts are immutable or unchangeable. But what if I told you that they were immutable? Well, technically, that 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 smart 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 a
nd will be on chain 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 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 trilobites articles that helped me put this video together 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 that 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 Behind 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 the centrality. So we need to keep that in mind. And this is why it's so impo
rtant that before you go ahead and jump in and start deploying upgradable smart contracts, you understand the trade offs. So we're going to talk about three different ways to upgrade your smart contracts. The first one being the not really slash Paramor 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 subcategories, like metamorphic contracts, transparent upgradable, proxies, and u
niversal 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 add new storage or state variables. So this is really not really upgrading. But it is something to think abou
t 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 percent, every year or something like that. Maybe we have a setter function that says, hey, update that to 2 percent, or update that to 4 percent. It's just a setter function that changes some vari
able. Now, the advantages here, 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 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 have 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 ABA used before you call a function, you actually check some contract registry that is upd
ated as a parameter by somebody and you get routed to the 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 upgrades. But some people might even think that upgrading your smart contract is ruining the decent reality. And one of the things that makes smart con
tracts 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 upgradability, you should deploy your contract. And then that's it. trilobites has actually argued that if you deploy your contract, knowing that it can't be changed later, you take a little bit extra time, making sure you get everything right. And there are often less security vulnerabilities because you're just sett
ing 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 Eat method. And now I think it's less funny. So we're just gonna stick with social migration, the social eating method, or the migration method is just when you deploy your new contract, not connected to the old contract in any w
ay. 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 over into using this new one, that the upgrade is done, hence my slang name of social yeet. Because you use the first one out of the way and move to the second one. I think I'm funny. Yeah, this has the advantage of truly always saying, Hey, this is our immutable smart contract. And this is our new one.
This is really the truest definition of immutable, because since you give it no way of being upgraded in place, than if somebody calls that contract in 50,000 years in the future, it will respond exactly the same. Another huge disadvantage here is that you have to have a totally new contract address. So if you're an ERC 20 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 th
e state of the first one over to the second one. So for example, if you're an ERC token moving to a new version of that ERC token, you do, you 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 ne
w version of the contract. So there's a ton of social convention work here to do. trilobites has actually written a fantastic blog on upgrading from a v1 to v2 or etc. With this eat 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 a easy way, which leads us to our big ticket item is the proxies. What's our big ticket item? proxies, 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 dot sender and message dot 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 fallback 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 implementati
on 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 contracts 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 th
e 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 ty
pe 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 gotchas. And we're gonna talk about the gotchas. 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 trilobites doesn't really recommend using upgradable proxies for your smart contracts. Because they're fraught with a lot of these potential issues. 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 gotchas 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
what these smart contracts are actually kind of dumb, we actually set the value of whatever is in the same storage location on contract as contract B. So if our contract looks like this, and we have two variables and contract a, we're still going to set the first storage spot on a contract a to the new value. This is really important to know because this means we can only append new storage variables and new implementation contracts. And we can't reorder or change old ones. This is called stora
ge clashing. And in the implementations we're going to talk about, they all address this issue. The next one is called function select or 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. A function selector is a four byte hash of the function name and the function signature. Don't worry about the function signature for now. Now, it's possible that a function in the implementation contract has the sam
e function selector as an admin function in the proxy contract, 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 All 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 of the three implementatio
ns of the proxy contracts. This is called the transparent proxy pattern. And it's actually going to be the pattern that we're gonna be demoing to you today. In this methodology, admins are only allowed to call 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 into a big issue where you call a function, you probably shouldn't have, if you're an admin, you're calling admin functions. If your user you're calling implementation functions. So if you're an admin, and you build some crazy, awesome defi protocol, you better come up with a new wallet address because you can't participate. The second type of proxy we're going to talk about is the universal upgradeable proxy, or the op amps. This version of upgradable contracts actually puts all the log
ic 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
upgradeable functionality, you're stuck. And it's back to the Eat 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 of 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 mu
lti 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 Aetherium 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 l
ook at delegate call. Now, we're going to learn about how to actually build these proxies how to build these upgradable 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 Harnett. And if T's we have a sub lesson in there, about EVM, opcodes, 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 simp
le 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 VARs and updates are you into 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 are you into public num is that index zero, or sender's at index one, our values and index two etc. Now we're going to deploy a contract
a and now this contract is actually going to use the delegates call function. Now a contract a this is going to look a little bit different, but it's still going to have this set bars functions, except it's going to make a delegate call function call to our contract B. Now in our lesson 14 with NF TS we learned about call API dot encode with signature API dot encode etc. So if you're unfamiliar with function selectors, if you're unfamiliar with if you're unfamiliar with this syntax, be sure to
go back to lesson 14 To understand ABI dot encode with signature and contract dot call. The difference here is we're doing contract dot delegate call. What this call does is something very similar to call. Normally, if we did contract dot call on this contract, we would just call this, we would just be calling this function set VARs, which would update contracts B's storage, but instead we're saying Hey, call that set VARs function, and then pass this as an input parameter, but call it in our co
ntract, 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 this 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 littl
e 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 beam, we'll hit Deploy, we now have a contract, num, center and value are all blank, we'll update the number to something like 777, we'll hit Set VARS. Set VARs will 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 in Cinder are also all blank. But when we call set VARs, it's going to borrow this set VARs function from contract B and run it in contract a, you can almost think of it as if we're copying, set VARs and pasting it into our contract a just for one run, and then immediately deleting ADM, that's what this delegate call function does. So when I call set VARs, we're going to pass it this contract address as an input parameter. So it knows to call this contract
said virus function. When I pass it the address, and I pass 987. Since we're borrowing the function, we're not going to update this num. On contract B, we're going to update the num on contract a. So when I hit Set VARs, we see num now has 19. Seven, we see Senator 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 stored 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 num, we could call this first value. Senator, we could call something else. And then value we could call foo, or whatever you want here. And when we borrow this function using delegate call, instead of 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, you're accessing the nu
m variable, which is, which is at storage slot zero. So when we borrow set bars and contract a with Delegate call, we'll say storage slot zero is going to equal that underscore num. Which are this contract storage slot zero is first value. So we'll say first value equals underscore Now, something else is going to be stored slot two, so it's gonna say okay, storage slot two, we're gonna update storage slot two to message that sender. Okay? value here is storage slot three. So whatever's in storag
e, slot three, will update with message dot value like this. So that's essentially what's going on behind the scenes. So let's go ahead and let's delete those and redeploy. redeploy them. So we'll deploy contract be deployed contract a, right now in B, once again, if we do 1234, set VARs, we have 123. And then contract a. Now even though these variables have different names, we could grab contract B's address, paste it in, do 654, hit Set VARS. And first value is now six by four. So delegate cal
l 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 even if you don't have variables, it'll still save to storage slots. So in contract a, if we didn't have any of those variable names, storage slot, 01, and two would still get updated. Now here's where things can get really interesting. Let's delete our contract again. And let's change the type of our contract A's first value to from a UNT t
o a 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 VARs function of contract B, which takes a Yewande and assigns the first storage slot that number we pass it, but our first storage slot is now a Boolean was 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 tu tu, tu as our input parameter, we'll hit Set VARS. Our tran
saction actually does go through. And now when we look at first value, it says true. Hmm, that's really weird. What if we change set VARs to zero, and hit Set VARS. And now, first value is false. In storage here, when we add a number with set VARs, 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 actua
lly get some really weird results. If your typings are different, or if your stored variants 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 gonna b
e working with, once again, in the hardhat upgrades, FCC sub lesson, small proxy dot Sol, and you can go ahead and 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 sub lesson. If you want to just move on to learning how to actually build these proxies, without reall
y 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 dot sole thing from up in Zeplin. openzeppelin 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 you'll. And it's an i
ntermediate language that can be compiled to bytecode for different backends. It's a sort of inline assembly inside solidity and allows you to write really, really low level code close to the opcodes. Now we're not going to go over you'll but I'll leave some links to the you'll documentation if you want to learn more. Even if you're a really advanced user, you really want to try to use as little EULA as possible. Because since it is so much lower level, it is much easier to screw things up. Howe
ver, like I said, for this example, we are going to be using a little bit of you'll now in this proxy that we're going to be doing, we have this delegate function, which inside this inline assembly, which is you'll, it does a whole lot of really low level 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 whenever it receives a function that doesn't recognize i
t'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 can be equivalent to like upgrading your smart contract. And then we have implementation he
re 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 storage. The one caveat though to this, we do still need to store that implementations address somewhere, so we can call it so ERP 1976. It's called the standard proxy storage slot, which is an Aetherium improvement proposal for having certain storage slots s
pecifically used for proxies. And in our minimalistic example here, we set bytes 32, private constant implementation slot to that location in storage. And we'll say, okay, whatever is that 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 go
ing to build here. So we have the small proxy is proxy. And we'll create a real minimalistic contract. So we'll say contract employee, mentation A, and we'll just give it a U and 256. public value and then function set value, you add 256 new value, public will say value equals new value 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, do function, get data to transact. And we can get the data using the API dot encode with signature that we learned in an earlier lesson. So function get data to transact, we'll pass it a un 256 number to update. So we'll give this the number we want to call a new value. We'll have
this be public pure, that's going to return a bytes. Memory. And we'll just say return ABI dot ENCODE. With signature set value, you went to 56, 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 dot encode ABI dot encode with a signature and call anything with its raw bytes bring and get the data to transact. And we know that when we call im
plementation a, from our small proxy, we're going to update our small proxies storage. So we'll create a little function in solidity just to read our storage in small proxy. We're gonna say function, read storage. And this will just be a public view, will do returns, returns you into 256, value at storage slot, zero. And we are going to use a little bit of assembly here since we are doing all this low level stuff. And we're going to call the s load up code to read the value at storage slot zero,
we'll say value at storage slot zero, 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 s load of storage slot zero, and then it will return this value here. So we're reading directly from storage. Oops, and then we need a little parenthese here. Sorry. So now, 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 cal
l this proxy contract, we're going to delegate call the functions over to here. So we're going to grab current implementations A's address, paste it into set implementation 77. So this is the data of set value you in 256, with that number to update encoded in it. So if we call our small proxy, with this data, our proxy contract is gonna go, oh, okay, this is a function. I don't I don't see that function here. We're going to call our fallback, right, which again, is coming from open Zeplin. And o
ur Fallback is going to do this delegate, which is this low level stuff, but it's basically just doing a delegate call, we're gonna call our fallback function, and then we're gonna get the function in the implementation A, we're gonna borrow this function, and we're gonna use it on our on ourselves. So if I copy this, the implementation has been set to being this address down here. So all the logic is going to be done here. So when I go ahead, and I grabbed this, and 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 one, 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 onset 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 was 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 low level 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 plus two 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 also means that the developers of this protocol can essentially change the underlying logic at any time. This is why it is so im
portant 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 sedimentation gets called becaus
e 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 universal upgradable proxy can help us to, and I'm not going to go too much deeper into these now. But we'v
e left some links 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 discussion thread and make a new discussion about proxies make a new discussion about the Assembly about the you'll set implementation, this is a great time to connect with other people taking the course and ask questions here, because I
know that this is a really advanced section, and requires you haven't gone through a lot of those sub 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 the section we're 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. But with all that being said, we
finally have all the knowledge that we need to build our hardhat project that deals with upgrades. So let's go ahead and jump into it. Your new terminal, we're going to do MK dir, hard hat, upgrades, FCC, CD, hard hat, upgrades, FCC, and then code period, or file, open folder, this folder here, now I'm going to grab that same yarn add we've been grabbing from less than nine, we're gonna paste it in, we're going to add all of these different parameters. And once again, we're going to copy over o
ur hard hat config from previous sections, we're going to copy over prettier. And we're just going to get our basic default setup. At this point, you might have a setup that works best for you and that you like better. And feel free to grab that as well. So I'm going to paste the prettier is in here. And I'm going to paste the hard hat.config.js that we've been using, instead of running yarn hard hat. And now we should be good to go. So let's create a new folder called contracts. And in here, we
're going to create a new file called Box dot soul. And then it's this contract, that's going to be our implementation or our logic contract. So it will say pragma, solidity carrot zero point 8.7 contract box will say you into 256 internal value will do event value changed you into 256 new value, do function store, you went to 36 value, this will be a public function will say value equals new value. So this store function is going to update our variable at storage slot zero, internal, and then w
e'll just omit value changed that new value. And then we'll just create function retrieve, which will be a public view returns a UNT 256 We'll just do return value. And then we're going to create a new function called version. And this will be a public door. And that returns a un 256. And we're just going to have this return one. So our box contract here is going to be version one. Now we're going to copy all this code, paste it into a box v two dot soul and rename it to contract box v two, we'r
e going to update the version to version two here. And we're going to create a new function called increment. And this will be a public function. And we'll say value equals value plus one. And then we will emit a value changed event with value. We're going to have one contract address originally use the logic in box and then we're going to upgrade it to the logic in box V two. And we're going to learn how to use all the tools that we've been working with here to add this logic and create this lo
gic And let's just make sure this works, we'll do yarn, or that compile. So let's make a readme.md, we'll say, one, we're going to upgrade box to box V two. So we're going to make a proxy contract, that's gonna point to box. And then later on, we're going to update it to point to box V two. Right, so we're going to start it up pointing to box, then we're going to have it point to box V two. And that's how we're going to upgrade it, one of the first things we're going to need to do is deploy a pr
oxy, we can deploy a proxy manually ourselves, and we can build the proxy contracts and do all that stuff. That's our first option. Hardhead deploy also comes built in with deploying and upgrading proxies itself, where we can just specify that we want to use a proxy. And we could specify the type of proxy that we want to use. So number two is just saying using hard hat deploys, built in proxies. And then number three is open Zeppelin actually has an upgrades plugin, which allows you to write som
e really simple scripts that allows you to have a really simple API like upgrades dot deploy proxy, and then upgrades that upgrade proxy. Now for this section, we're going to be doing the hard hat deploys built in proxies. However, in the GitHub repo associated with this, if you go to scripts, there's other upgrade examples that will show you how to use the opens up and upgrades plugin. And we're not going to do deploy a proxy manually manually, because we essentially just showed you how to do t
hat in our sub lesson. So we're going to show you this, we're going to show you the Hardhead deploys built in proxies, and if you want to use the openzeppelin upgrades plugin, that is available in the GitHub repo as well. So let's go ahead and do this. So we're going to go ahead and we're going to make a new folder, or deploy folder. And first, we're going to make a new file called a one, deploy box dot j s. And this is going to look really similar to everything we've been doing so far. So modul
e dot exports, equals async function, we're going to get named accounts and deployments. The arrow function will say const deploy COMM A log equals deployments const deployer equals await, get named. Accounts, do a little logging, like this, and then we'll say const, box equals await, loi, box, comma, we'll say from Deployer, comma, args like this, we'll say weight con formations is going to be network dot config dot block confirmations for Masons. And yep, we got to grab const from hard hat. An
d then we can add the parameter in here for proxies. And this is where we can add a ton of information. So like I said, we're going to use the transparent upgradable proxy from open Zeppelin, which if we want to use it, we're going to have to add open Zeppelin. So we'll do yarn, add dash dash dev at open Zeppelin slash contracts. And we can tell our hard hat to deploy this box contract behind a proxy will say the proxy contract is going to be the open Zeppelin transparent proxy. And we're also g
oing to do a via admin contract. So instead of having an admin address, for the proxy contract, we're going to have the proxy contract owned by an admin contract. And doing it this way is considered a best practice for a number of reasons. But we'll name this admin contract, box proxy admin and the artifact for this box proxy admin. So we'll need to create a box proxy admin contract to be the admin of our box. So in our contracts folder, create a new folder called proxy. And in here, a new file
called Box proxy admin that saw and this is going to be the admin contract we're going to have for controlling the proxy of our box so inbox proxy admin dot Saul will do SP DX license. I then to fire MIT pragma solidity, carrot zero, point 8.7, say contract, box proxy admin, like this, right? And once again, we're going to use one of the open Zetland tools in the transparent folder. They have a proxy admin dot Saul, which is going to be essentially what our box proxy admin is going to be. It has
some functionality, it has some functions in here like change, proxy admin, upgrade, upgrade and call for dealing with upgrades. All contracts. So we're going to import it will do import at open Zeppelin slash contracts slash proxy slash transparent, slash proxy admin, dot soul. And we'll say our Brock's box proxy admin is proxy admin, like this. And to have this box proxy admin work with the heart at deploy plugin, our constructor needs to take an address owner as an input parameter, but we're
just going to leave that blank. And then, and then we need to do the proxy admin, which is just going to be blank as well. And that's it. That's all we're going to do box proxy admin contract, which just has all of the functionalities to do upgrades and change proxy admin and all this stuff. We're going to deploy our box contract behind a proxy and opens up and transparent proxy that is owned by our Brock's proxy admin contract in the template Aetherium contracts. GitHub repo is actually an exa
mples slash opens up on proxies branch that will show you how to work with different types of proxies. And there will be a link to this in the GitHub repo associated with this course. And then we'll do our verification, say, chains dot includes. And we'll go ahead, I'm going to copy paste our hard hat helper config from our last project, which has development chains, hard hat and local host that we export, will import this as well. const development chains equals require dot slash helper hard ha
t config. If development chains dot includes network dot name, and process dot env dot ether scan API key log, verifying that the same as we've done a way to verify last, we're going to copy over our utils folder. So just copy, paste, we now have verify, which will import it in here. So we'll do const verify equals require dot dot slash utils, slash verify, await verify box dot address. And then args is going to be blank. So we'll just do blank here, and boom. And that's going to be it for our b
ox deployment. So we can test this out by running yarn Hardhead deploy, see if everything works here. And that's it done. And then we should do actually, we should add log beach true as well. Let's run this again, much better. So you can see we actually deploy a couple of contracts. So we deploy our box proxy admin, which is going to be our admin contract, then we deploy box implementation. So hard hat deploy, went ahead and took our box contract and renamed it to box implementation and then dep
loyed it, then it deployed our box proxy here. So anytime we call this address, it actually will point to the logic of our box. Now what we can do is we can write a deploy script to deploy box, the box v2 implementation, and then upgrade our box to box V to create a new deploy script called Zero to deploy box v2 dot j s or deploy box two dot j s. And we'll do something really similar here. Right, so I'm just going to copy pretty much of this, paste it in here. Now we're going to do const box v t
wo equals await, deploy. Box v two, comma, from Deployer. Log True RMS blank, weights confirmations, it's going to be network dot config dot lock. Or masons, then I'm going to copy the verification code, copy this, paste it here, server, this is going to be box v2 dot address. Okay, great. So we now have some code where we can deploy box and box v2. Now let's go ahead and write a script to actually upgrade these. So we'll do a new folder, scripts. New File, and we'll call it upgrade box dot j s.
Now we're going to do it the manual way here. And the reason we're going to do it the manual way is because I want to show you exactly the functions that we're calling to do this upgrade process. However, hard hat deploy also comes with an API to make it really easy to actually just upgrade your box contracts. This is gonna be script. So we'll start off with async function main. And then we'll copy paste our traditional script, main dot then process exit blah, blah, blah, that whole thing. We'r
e first gonna get the box proxy admin contract. We'll say box const. Box, proxy admin equals await ethers dot get contract, box proxy admin and we got to import you Here's from Hardhead, then we're going to get the actual proxy, which is our transparent proxy. So we'll say const transparent proxy equals await ethers dot get contract, box underscore proxy. Since hard hat deploy, we'll just name the proxy the name of the implementation underscore proxy. And then of course, we're going to need our
box V to contract. So say const. Box v two equals await ethers dot get contract, box V two. Now we can say const, upgrade TX equals a weight box proxy admin, that upgrade. And we're going to call the upgrade function on our box proxy admin, which calls it on our transparent proxy, which will change the implementation from box one to box two. So box proxy admin, that upgrade, we're going to upgrade the transparent proxy dot address to our box B to that address, it will look in our box proxy, a bo
x proxy has an upgrade function which calls upgrade to on our transparent upgradeable proxy will do a weight upgrade TX dot wait one. And now to work with the functions on our box v two, we're gonna say const proxy box equals await ethers dot get contract. At box v two, we're going to get the box v two ABI however, we're going to load it at the transparent proxy address. This way ethers knows okay, we're going to call all of our functions on the transparent proxy address. But this proxy box is g
oing to have the ABI of box v2, which is what we want. Now we can say const version equals await proxy box dot version. And we'll say console dot log version. And if we want to compare this to its original implementation, before we upgrade, we can do the same thing. We can say const proxy box v1, let's actually call this proxy box V to say cost proxy box v one is going to be this exact same thing equals this call box here. And we'll do const version equals weight, right proxy box v1 dot version,
console dot log version, or version v1, version v1. We'll call this version v two, version v two, and proxy box V two. So we'll get our version v one will upgrade. And then we'll see at that same address what the version function now returns. So let's open our terminal. If I run yarn, our head node will spin up a node will have deployed our admin our implementation, our proxy, and then our box V to implementation. I'll make a new terminal. And I'll run yarn, hard hat run scripts upgrade box tha
t J S dash dash network, local host. And we should see that box actually update. And that's exactly what we see. And then let's do well, it's I forgot to do.to string in here. But it goes from version one to version two on that exact same address. And with that little code, we have successfully learned how to upgrade our smart contracts programmatically. Now, like I said, in the GitHub repo associated with this lesson, you can also check out the upgrades plugin from open Zeppelin. So to work wit
h that, you would just do upgrades dot deploy proxy proxy to call the Prepare upgrade function, and then upgrade upgrade proxy just like that. They also have an upgrade tutorial, step by step for hardhat that you can follow along with as well. Now I know this was an advanced section. And I know we went a little bit quick here. But honestly, if you just finish this section, not only have you completed all these other sections that make you a really powerful smart contract developer. But you've le
arned some really advanced stuff here. We've gone into low level code like delegate call, we've gotten to assembly we've gotten to you'll we've gotten to these proxy patterns, which can really make you a an incredible stand out developer in the smart contract space. So if you just finished this section, you should be so so proud of yourself because we went really fast and because there's a lot of advanced information here. Now, like I said, 100 percent, be sure to go into the discussions tab and
ask questions and connect and talk to other people in the area. Maybe look at the already running discussions and jump in and start asking other students and start asking other people about what they've learned and how their proxies are going. And if they made anything really cool. If you're just excited and you want to go to the show and tell section, make a show and tell me like hey, here's my GitHub repo for doing this upgrade section. going here and be excited with that being said go and ta
ke that coffee break go take that walk go to the gym go get excited Go tell your friends we are almost done we have two lessons left and then you're home free All right, welcome back to lesson 17 For hardhat. Douse, you're almost done. Now for this section, I've actually already made a video on how to code a dowel with TypeScript and solidity in JavaScript. So we're actually just going to play this video for this section. The reason we're going to display this one is because I did a lot of work
to make this one look really good. And it's still incredibly up to date. So this is going to be in TypeScript and solidity. However, we're going to have the JavaScript edition of the code base in this code from the video section. If you want the most up to date version of this delta template code, you can use, you can select this up to date code, which goes to this doubt template repo. I'll be updating this repo periodically with new Dao examples and new ways to create doubts or decentralized au
tonomous organizations. Now, before we learn how to code a doubt, we should learn what the DAO is. And again, I've already made a video that I've 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 Dow. And then our last section is going to be security and auditing. And we're going to finish this out. So Bucklin, let's learn what a Dow is. And then let's go ahead and build a Dow, let's do it. Now, daos for decentralized a
utonomous organizations is a bit of an overloaded 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 down because the miners can 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 Tao is just a buzzword, so they just slap t
he name relay on to any organization so that they can get some clout. And this makes for sad, Patrick. And it's not to be confused with the Dow, which was an implementation of a 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 and the Dow term is used in a lot of different ways. But in essence, imagine if all of the users of Google were given voting power into what Google should do next. And the rules of the voting was im
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 o
f the protocol that's setting the precedent for all other doubts and 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 gonna have a full coat 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 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, oftentimes, they're gonna wa
nt to do a lot of new things, maybe they want to add a new token to allow borrowing and lending, maybe they're gonna want to change some of the API parameters, maybe they're gonna want to block certain coins, there's a lot of different things that they might want to do. So that's where we're gonna go ahead to governance, this is where you can find a user interface for 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 tha
t 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 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 actually see that proposed transaction right here. If we click on this, and we scroll down, we c
an 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 the 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 param
eters 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 Do functions, and the owner of these two contracts is likely going to be this governance style. And values. Zero just means that we're not going to send any eath alo
ng with these transactions, once a proposal has been created, after a short delay to becomes active, and this is when people can actually start voting on them, this delay between a proposal and an act of 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, we click on this transaction again, and we go to the compound governance contract. And we scroll down to contra
ct, right as proxy, we can actually see the exact function that the people call 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 tech savvy. So you can vote right through this
app dot compound at finance. Or you can just send the transaction yourself. Once all those votes happen. It reaches this queued stage. Now what is queued 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 cute function. And it only can be called if a vote passes. And it says, OK, that postal ID has been cued, 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 A detail. So this is going to be a full example of the lifecycle of a proposal going through this process. Now there are a couple that even failed, a whole bunch 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 oftentimes, 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 liked them or don't like them. Oftentimes, 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 can 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 snapshot actually helps you with the voting process. All right, now you've seen the protocol that has been influencing all the other details on how to vote. Now, you know, now that we know what a doubt 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 days, because sometimes they do need to update and change to keep up with the times. Not all protocols need to have a Dow, but those that do need to have a doubt need a way for the participants to engage. This is one of the most important questions to ask him 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 ERC 20 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 gray. 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. And if T's 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 not. It really just depends on what your down community setup is going to look like. Now the next one we're going to talk abo
ut 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 axed. You get punished for making evil or bad decisions for your Dao and your protocol. I like this mentality because even if you buy a ton of tokens and decide to be ill with it, you can be
held accountable for your bad decisions. Now, the hardest part about this, though, is gonna be how do we decide as a community? What is 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 use the protocol. And even if they had 1000 wallets, they use 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 1000s 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 chainlink integration, because proof of personhood is basically just off chain data that can be delivered on chain. And that's exactly where channeling shines. Now, as you can see all of 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 regul
ar 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 ERC 20 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 and governance is going to work in our smart contracts. And in fact, you should draw
parallels and look for inspiration from the web to space. Now when it comes to implementation of the voting, I put them into two categories on chain voting and off chain voting on chain voting is exactly what we saw with compound, the smart contract on chain, your voter, you call some function called vote with your meta mask your ledger or whatever, send a transaction and vote, you voted Congrats, you can wear your little sticker now call that function and you send a transaction, you send a tra
nsaction, what are the transactions use that are kind of annoying and kind of costly? Oh, that's right gas, I imagine you have 10,000 people in your community and it costs $100 To vote per person, you're 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 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's seat, where they use some random sampling to do some quadratic voting to help reduce costs while increasing civil resistance. You want to learn more about that one to be sure to read about it in the description. So on ch
ain voting is the simplest one here. But let's talk about off chain voting. To cast the vote off to decentralized context, relax, relax, you can vote off chain and still have the 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 signed transaction to a decentralized database like IPFS, count up all the votes in IPFS. And then when time comes, deliv
er the result of that data through something like an Oracle like chain link to the blockchain all in a single transaction. Alternatively, what you could do is you could replay all the same 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 secu
re and better and blah, blah, blah, die for it. This is your call to action go build this thing. This option. 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 decent quality of your application. So don't do that. And if you made it
to this point of the video, give yourself a little pat on the back. You're doing fantastic. Fantastic. Like I said, I have a video coming out after this one it'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 to help get you up to speed quicker. Now there are a number of no code solutions that can go into building one of these dowels Tao stack Aragon. Just kidding, this is Aragon, colony and Tao house are all alternatives
that can actually help you with the upside of running a Dao and building a doubt. However, if you want more granular control and you don't want to have to pay any 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 Dao. And actually performing that execution, users can vote through this protocol with their actua
l tokens, those transaction gets stored in IPFS. But none of it actually gets executed. Unless the doubt chooses to, this can be a great way to get a feel for what your Dow wants to do. And Optionally, you can send the transactions and execute the votes as well highly recommend checking out Zodiac which is a suite of database tools for you to implement into your Dallas as well tally is another one of these UIs that allows people to see and actually vote and interact with these smart contracts th
rough user interface. So those of you who don't know about Gnosis safe, you absolutely should know Safe is a multi SIG wallet. And the reason I put this on the list, even though it's adds kind of this centrality component is that most dowels 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 1000s of people to wait for a vote. And in the beginning, any protocol is going to be centralized to some degree anyways, using a mult
isig, we're voting happens through only a few key members can be good in the beginning for your dials, 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 opens up and contracts we love opens up and contracts. These are the contracts that we're going to be basing our Dao code along. Alright, so that's all the tools. That's the architecture. One more thing before I let you go legality, the future of Dows is i
nteresting for all these reasons we just talked about, but especially on a legal front, does it make sense for a doubt to live by the same regulation as another company? Why would you even force it down to do something, you'd have to enforce them to all vote a certain way if the government tells you to, it's a little gray, it's hard to nail down who to even keep accountable for these days and the United States at least you can actually form your own Dow and have it legally recognized in the stat
e of Wyoming. This is something I want to do. So we'll just have to see what happens there. Oh, 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 I found them kill baby. All right, well, you heard him it's time to build. Like we said, All the code is going to be located in less than 17 Here, let's jump in. In this video, we're going to show you how to build your own doubt inspired b
y compound now this is going to be 100% on chain voting and on chain governance. We're going to show you the easiest way to spin up an NFT or ERC 20 voting type down all using solidity and hardhat. Now if you haven't watched my last video going over the architecture of Dows, what goes into one of these be absolutely sure to watch that video first and then come to this video. Because that video explains all the philosophy behind what we're doing here we're going to be using opens up and contracts
and a hard hat framework to build this all in solidity. If you want to see a brand new or Pythonic version of doing this, check the link in the description because we did a video over at the chainlink hackathon recently. And additionally, additionally, we know that because we're doing this 100% on chain gas fees are going to be expensive. So I'm really looking forward to somebody doing a chain link plus IPFS plus snapshot integration so that we can do all this off chain. And once that exists, y
ou already know I'm gonna make a tutorial on that. And if you like this style of content, be sure to smash that like button, subscribe and leave a comment in the comment section to let me know what you want to see. Next, let me know how you want to supercharge your smart contract developer experience. So let's jump in. Right, so here's what we're going to be building, we're gonna have a very basic smart contract here, right, it's called box and all it can do is store a value and then retrieve a
value. But the thing is, its ownable. And only the owner of this contract can call the store function and guess who the owner is going to be the owner is going to be the doubt. So only through a process of governance, can anyone store a different function here. And once we're done, we're going to go through the entire process of proposing voting queueing and then executing a transaction in a Dao to update our Bach contract. And that's one of the beautiful things about these these Dao setups is t
hat they're completely modular, right. And so when I go through the whole process, I'll do Hardhead tests here, which my tests right now are set up to just do everything, we're going to see every single step that this Dow is going to take. So we see box starting value is going to be zero. And then all of this stuff is going to the governance process. These are just some some notes. Basically people are voting, queueing and executing. And then at the end, we chained the value of the box contract
through a voting process. And that's exactly what we're gonna show you how to do today. Now remember all the code for what we're going to be doing here is in my doubt template GitHub repo so if you ever get lost, feel free to refer back to this to get started. And additionally, if you want to see the Pythonic version of this, feel free to go back to the downmix The main thing is though that all the contracts are going to be the same no matter what brownie hard hat, dab tools, foundry, it doesn't
matter. So the first part of this section is gonna be exactly the same. And here's our agenda here. First, we're gonna write the smart contract. So if you're not familiar with Hardhead, who cares, we're gonna be doing the smart contracts first, then we are going to write deployment scripts. And this is where your hard hat knowledge is going to come into play. We're going to be writing our deployment scripts in TypeScript here, because TypeScript is phenomenal. If you're unfamiliar with TypeScri
pt, I challenge you to rewrite this in JavaScript and make a JavaScript version. And then finally, we're going to write some scripts to interact with our governance with our deployed contracts. Now, a quick note, this isn't how I originally built this, I didn't just read smart contracts, write deployment scripts, write the scripts, and then the tests and boom, I was done, I had a back and forth between tests, smart contracts, deploy scripts, etc. If you're thinking, Oh, my goodness, that's so ea
sy for him to go through this. So seamlessly. When I originally wrote this code, it was a lot of back and forth. And that's how you should be developing, you're going to be moving between tests and smart contracts and stuff. Additionally, in this tutorial, we are going to show you some sick Hardhead skills. So you are not only gonna learn how to build a Dow, but you're gonna learn some really advanced Hardhead skills. So let's jump in. Let's do this. So the code editor I'm using is Visual Studio
code. So make sure you have a code editor up and ready to go. And you'll need a couple of prerequisites here. Again, the prerequisites are in the GitHub repository, we're going to need Git, no J, s. And yarn, if you want to just clone this repo and follow the instructions here to get started, you absolutely 100% can and then you don't even need to build this from scratch. But we're going to want to learn to build this from scratch. So let's just start git dash dash version. Great, we have Git n
o dash dash version. Great, we have node, and then yarn dash dash version. Great, we have yarn, we can get started. So everything that we're going to be installing here for packages is going to be a dev dependency. So the first thing we need to do is do yarn, add dash dash Dev, hard hat, if you'd haven't already. And now in our folder, we're gonna have node modules package dot JSON readme and a lock. Of course, now that we have that we can run yarn RDAP, we're gonna get the hard hat CLI up. And
we're going to have all this stuff in here, we're just going to create an empty hardhat dot config dot j s, and we're going to turn it to TypeScript. The advanced sample TypeScript project has a bunch of stuff that I don't like. So we're just going to create an empty hardhead.config.js. And perfect, we've got a little hard hat.config.js. Now let's go ahead and create a folder, or contracts folder. And this is where we're going to add all of our contracts. So the first thing contract that we're g
oing to need is the contracts we want to have govern, which in our case is going to be box dot soul. Now, I am actually just going to copy paste my box, that soul here, because it's not particularly interesting. But you could really code whatever you want here. So feel free to pause the video, copy paste from my GitHub repo, create your own governance contract that you want to play with, or do whatever you want here. But for us, we just have a store function, and retrieve function, and an event,
and then a private value that we're going to be storing and retrieving. And that's it. So of course, we want to fix this. We're importing from openzeppelin contracts opens up is amazing. We're gonna want to add this we'll do yarn, add dash dash Dev, at opens up on contracts. And that should get rid of the box. That's all. let's reopen box. And boom, looks like we did a detour to that perfect. And for extensions, I'm using the solidity, the one Blonko, slit extension. And that's what we get this
wonderful linting things here. Great. So now we want to check to see if this compiles if using remix, you can compile with remix hard hat, you're gonna see how we compile here. Or if you're using you know, Browning, we just want to see if this compiles correctly. So run yarn had a hard hit Compile. Looks like we ran into some compilation errors, because we need to update this, let's use these 8.8 of solidity we'll try to compile again. And perfect looks like we're compiling successfully. Look h
ere, we do indeed have our contract in here. Okay, perfect, easy part out of the way. Already. That was so quick. Now let's start creating the next part. Let's create the governance part. So what we're going to be working with to build this governance platform is we're gonna be building it off of the ERC. 20 standard, so you're gonna get an ERC 20 token. And that's going to be the token that you get to vote. So let's create a new file called governance token. That's all governance token dot Sol.
And this is gonna be the code for the token that we use to actually vote. Now we're going to create a normal ERC 20 token. And then we're going to extend it to make it governance a bowl and you'll understand what I mean in a second. So let's go ahead and make this spdx license identifier. It's going to be MIT pragma solidity we'll do zero point 8.8. And then we'll do contract governance token, and then we'll say is ERC 20 I'm just gonna go ahead and import openzeppelin Because open Zeppelin has
a package where basically has everything we need for an ERC 20 token. So we're gonna say import at open Zeppelin slash contracts slash token slash ERC 20x We can go to their github openzeppelin contracts token, your C 20 And we'll do ERC 20 Dotto, we'll do this for now. token, use your C 20 ditzel. We're gonna change this, but don't worry about that yet. Now we're going to do a un 256 Public Storage Max supply, it's the best practice, but it's fine, we'll give this a max supply this much was go
ing to be 1-234-567-8910 12345678. So it's gonna be 1 million, we're gonna do 1 million of these tokens. And then we're gonna create the constructor construct or your C 20. Give it governance token as a name, and then our symbol is going to be GT. And for those who who don't know, when you inherit another contract in your constructor, you can use that inherited contracts constructor as well. In fact, I think you have to So governance token G team, and then we'll even call one of these ERC 20 fun
ctions called mint. And we'll mint to message dot sender, so whoever deploys this ERC 20 contract will just meant them everything, the whole Max supply. Now normally, if this was a normal ERC 20 token, you'd be all done. But this isn't a normal ERC 20 token. See, when we do votes, we need to make sure that it's fair, imagine this for a second, someone knows a hot proposal is coming up, they want to vote on. So they just buy a ton of tokens. And then they dump it after the votes over. We want to
avoid this. We want to avoid people just buying and selling tokens to get in on governance. So what we do is we actually create a snapshot of how many tokens people have at a certain block snapshot of tokens people have at a certain block. And we want to make sure once a proposal goes through, we actually pick a snapshot from the past that we want to use this kind of incentivizes people to not just jump in when it's a proposal and jump out because once a proposal hits, it uses a block snapshot f
rom the past. So we're actually going to need to change this a little bit. We're gonna change this from ERC 20 to an ERC 20 votes, and we can actually see this in open Zeppelin and the extensions slash ERC 20 votes that soul contract. If we go back to IRS to their GitHub, we can see ERC 20 votes, they also have a snapshot, which is pretty similar. And some of the main functions are it has these checkpoints. So these checkpoints are basically Hey, what is the snapshot? There's a number of checkpo
ints, you can also delegate your tokens to different people. So maybe you're not going to be available to actually vote. So you say, Hey, I'm gonna give my tokens to somebody else. You can get how many votes somebody has passed, votes get passed, or was apply it has all these functions that make this token, much better as a voting tool. Right makes it much much better. So we're gonna say our contracts governance token is ERC 20 votes and we just have to add additional constructor, this ERC 20 pe
rmit, I'm sorry, I kind of copied pasted that. So ERC 20 permit governance token. And right now we have a governance token that is a little bit more capable of doing actual voting, right, because as the snapshot has this delegating functionality, it has these checkpoints, it's going to be much better for doing votes in a fair way. The only thing that we need to do though, is we need to add some overrides, right. And we're just gonna say the functions below our overrides required by solidity. And
this part is a little bit boring. So I'm just going to copy paste it, feel free to copy paste it from my GitHub. But what we're doing is anytime we do this after token transfer, and the time we transfer a token, we want to make sure that we call the after token transfer of the ERC 20 votes. And the reason that we do this is because we want to make sure that the snapshots are updated, right, we want to make sure that we know how many people have how many tokens at each block. Same thing with the
mint. Same thing with burning, we want to make sure we always know how many tokens people have at different blocks or can be at different checkpoints I should say. And that's the most important bit at which checkpoint Are you going to use for your token voting. So cool. Feel free to copy that, again, from a GitHub or if you want you can even just try the rest of the tutorial without this and see how you fare. But cool. So now we have a governance token and ERC 20 token that we can use for gover
nance. So let's try to compile it. Yarn Hardhead compile. Great, looks like things are compiling successfully. Perfect. So our governance token looks good. Our box looks good. Let's actually now start creating our governance contracts. Now we're actually going to make a folder called governance standard because this is going to be the standard governance model. This is going to be this on chain ERC 20 and I plan on updating this in the future with no a governance off chain or something right. So
for now, we're calling a governance standard because this is the quote unquote standard way to do governance, but in the air, we're going to need two contracts actually, we're gonna need a government work, contract that soul and then we're also going to need a time lock that soul and this will make sense in a second. So our gov contract dot soul, this is going to be the contract that has all the voting code, all the voting logic that our governance token is going to use, the Time Lock is actual
ly going to be an additional contract that is actually the owner. So the Time Lock and the governor contract are sort of one in the same, but the difference is the Time Lock is actually going to be the owner of the box contract. And this is important because whenever we propose or cue something to a proposal to go through, we want to wait, right? We want to wait for a new vote to be executed. Now, why do we want to do that, let's say some proposal goes through, that's bad. So like, let's say we
have a box contract. And then a proposal goes through that says, Everyone who holds the governance token has to pay five tokens, or something like that, right, or whatever, or who knows, right? Maybe that's something that you don't really want to be a part of. So all of these governance contracts give time to give time to users to get out, if they don't like a governance update. So we always want to have some type of timeline. So once a proposal passes, it won't go in effect right away, it'll ha
ve to wait some duration, and then go in effect. So that's what the timeline is gonna be for. Governor contract is going to have all of our actual code. Now we can cheat a little bit. Actually, we can cheat a lot of a little bit. So opens up one has a thing called the contracts wizard, and there'll be a link to this in the description as well. And this opens up when wizard is a way for us to write really basic boilerplate code right in there wizard. So right, so if we go to the wizard contract h
ere, we can see we can make an ERC 20 and NFT 1155. And then finally, this gov thing here. So we can call it give it a name, we're going to call Rs. Gov contract, during explain what all this means, and give it a voting delay, which is the delay since a proposal is created until voting starts. So once you create a proposal, you gotta wait a little bit, the voting period, how long votes should go for. And the reason that this audio is important is because they actually do votes, voting period in
terms of blocks. So it's an anti pattern to actually do timed based things in smart contracts, it's much better to do block based things. So we're saying one week, but it's that's going to be you know, if if the average block time is 13.2 seconds, we're gonna figure out the weak proposal threshold is going to be the minimum number of votes and account must have to create a proposal. So maybe you only want people who have a lot of your governance token to make votes quorum percentage, it's what p
ercentage of people need to vote it all. So we're saying 4% of all token holders need to vote or we could say you know, exactly 100 tokens need to vote whatever we want to do here. We also have some updatable settings we have Bravo compatible Bravo is the compound type contract. So if you want to make it integratable, with compound you can do that. Votes comp like or ERC 20 votes, we're working with this ERC 20 votes, we always want to do a time lock, we're gonna do the open Zeplin implementatio
n of a time lock, you could also do a compound implementation, we aren't going to do upgradability here, however, I have a number of fantastic resources on how to actually do upgradability. And if we did want to do upgradability, it adds all this other stuff. We're not going to do that for now because it makes it so much longer video, and then you can add some stuff like this, but Oh, so that's pretty much it. And I know this feels like you're cheating, or we're just going to copy this whole thi
ng, right? Copy all that stuff that we put in copy to clipboard, and we're going to paste it in. Don't worry, I'm gonna explain what's going on now. So we have our government contract. And this is governor Governor setting Governor counting simple Governor votes, Governor votes, quorum Franco, all this stuff. All these are just implementations to make it easier to be governor, Governor counting simple is a way of counting votes, Governor votes is a way of integrating with that year's 20 contract
. Quorum fraction is is a way to understand quorum time lock. Obviously, it's time lock. This is going to be the base contract. That's gonna be some settings. And we're gonna talk about this in a minute. But let's go over what are the functions here so we have voting delay. This is exactly the voting delay, which we're gonna do superdad voting gelei, we're gonna get from this governor settings contract that we're going to set in a minute your voting period that we're going to set in our gov sett
ings, which is this one right here. And again, if you want to like look at all these contracts, you absolutely can, right, if we go to contracts, governance, extensions, we have all these in here, right? So if we look at governance settings, we can see it has voting delay voting period, proposal threshold, and those are right in its constructor. And that's exactly what we're setting, right. We're setting voting delay voting period, and then the proposal threshold, and then we're also going to ma
ke this customizable as well. And the rest of these that's exactly what doing calling the quorum from the super get votes. And then again, the super is those inherited contracts, get the state and then we have some interesting functions we have proposed. This is what we're actually going to do to propose new governance we have proposal threshold, and then we have execute which executes a cued proposal. To cancel, we have executor which we're is going to be who can actually execute stuff, we're a
ctually going to make it anybody and then supports interface, you can basically ignore. But let's make this a little bit more customizable. So we have Iboats token, this is going to be our governance token, the timeline controller timeline, this is going to be the timeline controller that we make an amended. And again, we need this because we don't want to let any proposal just go through once it passes, we want to give people time to get out. But let's add the UN 256 voting delay as a parameter
here. And for voting delay, we're going to do this, we're going to set it as our governor settings, we're going to do a UNT 256 voting period. And we're going to add that right here. And this means 45,000 blocks is approximately one week. And that's what that means we're going to leave proposal threshold to zero because we don't really want to change that we want to let anyone make a proposal. And then we're just going to add you in 256 underscore core percentage to this. So Governor votes quor
um percentage corporate senators. So now this is completely customizable, for voting, delay voting period, core percentage for whatever you want it to be. And believe it or not, that's it. Now you have a simple governance contract. Thank you, openzeppelin, for doing 99% of the work for us. So that's it. So this contract, it's going to have all these functions that we're going to go over for proposing for executing and for queuing, different proposals. Right. Now we got to make a time lock contra
ct here. And this contract is actually going to be a lot easier. So we're just going to do it from scratch. So we're going to spdx license I then to fire, my team, do pragma solidity and let's just do this your point a point zero, and then we're going to import from open Zeppelin, a contract called the Time Lock controller. So if we look at the governance here, if this time lock controller dot soul contract, and this has all this functionality in here for creating roles, who can actually propose
who can execute, who's the Time Lock admin, but it also has these execute stuff in here as well. It's gonna work in tandem with our governance contract, right? This is the contract that says that makes sure our governance contract doesn't just push stuff through willy nilly. So we're gonna say we're gonna first import that import at open Zeppelin slash contracts slash governance slash Time Lock controller. That's all and then we're gonna say contract, I'm lock is Time Lock controller like that.
And we'll create our little constructor here, and truck door. And this because this takes a couple different parameters, we're gonna take a un 256 Min delay, which are min delay, Min delay is going to be along you have to wait before executing. So this is Hey, once proposal passes, great, we gotta wait this minimum delay, then we're going to do a list of proposers, an address array memory of proposers. And then the proposers is the list of addresses that can propose for us, we're just gonna say
everyone's gonna be able to propose. And then last, an address array, memory of executors who can execute everything, and we're just gonna say executors who can execute when a probe posle passes. And again, we're just gonna say everybody, and the reason we need these is because we need to pass these to our time lock controller, this constructor is expecting three parameters. So we'll just do Tama controller, delay, pro posers, X EQ, tours. And that's it. So this is going to be what owns everyth
ing, it's the timelog, that's going to be owning our box. It's not the government contract, the government contracts is where we're going to send our votes and stuff. But at the time lock that actually everything needs to flow through in order for governance to actually happen, because we want to make sure we have this min delay, we go through the right process and everything. And believe it or not, that's everything. That is all the code you're going to need as far as the solidity goes, to crea
te a governance to create a Dao. So even do your own hard hat compile, make sure everything's compiled. And tada, we've done it, you've done most of the hard work. Now we're going to flip over to actually writing the scripts to deploy and to interact with everything using TypeScript here. At this point, if you're like, Oh, I already learned everything that I wanted, I don't use hard hat, I use some other tools. This is where I challenge you to go out and I challenge you to try something else. No
w if you've reached this point, I just want to give you a huge congrats, because you have taken the steps to build your own doubt build your own governance model. That's all the solidity that you really need. You can take that deploy that and you're good to go. But of course, we know that there's more to being a smart contract developer than just the solidity you got to do the tooling right to let's go ahead and we'll jump into writing those TypeScript scripts to actually do this. And again, if
you want to see a Python version of this, go check out a link up description to see the Pythonic version of this. And of course, don't forget to smash that like button, subscribe, leave a comment on how you're doing so far. And, of course, give yourself a pat in the back. Great job. You're doing amazing getting this far. Congrats, let's jump in. Alright, so we're back here, we've written our smart contracts already, check wasn't that easy, right, this was way easier than I thought it would be. N
ow we're just gonna write our deployment scripts, and then we're gonna write our scripts to interact with them. Again, my full repo also has tests, but we're just gonna write some scripts. And then feel free to check out the tests yourself. So let's write those deployment scripts to we're actually going to be using a package for deployment called Hard Hat deploy. It is absolutely phenomenal for hard hat for making your deployments much, much easier. We're gonna scroll down to installation, and w
e're actually gonna go ahead and install this. So typically, you could install it like this. Well, we're gonna use yarn, but we're gonna do kind of the more safe way which looks a little wonky, but I'm explaining it right. So instead of NPM install, we're gonna do yarn, add dash dash Dev, and then this whole thing right here. So we're gonna do yarn, add dash dash Dev, and then just paste that in here. So this is gonna be at nomic, labs slash hard hat, hyphen ethers at NPM, colon, hard hat, deplo
y ethers. And what this is doing is we're basically saying hard hat deploy ethers is going to be overriding this hardened ether thing. And we're also going to add ethers as well. And then once we add this in, check our package json, we can see we have hard hats. We have hard hat ethers, which is being overwritten by this hard hat, deploy ethers. And then additionally, we're going to want to add on a deploy. So do yarn, add dash dash Dev, hard hat hyphen, deploy. And what this is going to allow u
s to do is instead of having to write scripts, and do all this stuff, that kind of makes it hard to save your deployments and everything, we're going to just create a deploy folder, where we're going to add all of our deploy scripts in here. So I absolutely love this package. It's makes deployment really, really easy. So in here, we're gonna create new file, it's going to do oh one, we're gonna go step by step deploying everything, we're gonna call this deploy, govern or token dot TypeScript, th
at's gonna be the first thing we're going to do. Also, we're gonna change this to TypeScript. Tada, we now have TypeScript. Yay. Now the one thing that is kind of nice about doing kind of that advanced TypeScript thing at the heart had kind of gives it the beginning, is you don't have to install all the TypeScript stuff yourself. But we do. So we're going to do yarn, add TypeScript type chain, vs node at type chain slash ethers, V five, this is a lot of stuff, don't worry type chain slash hard h
at, at type slash Chai, at type slash node. And then we'll make sure this is all Dev, dash dash Dev, I know there's a lot of stuff. There's all this stuff to make it TypeScript D. You can absolutely do this in JavaScript if you want. You just have to do JS files and ignore the typing. So But feel free to do whatever you want to do. Alright, cool. And we should be okay here. Let's go into our governor token here. And we'll create a deploy script. So the Hardhead deploy GitHub repo has a little de
mo boilerplate code for you actually do your deploy script. So feel free to reference here if you lost or confused. So what we're going to do is we're going to import the hard hat runtime environments, from our enhanced slash types. And you'll see why we need this in just a second. And then we're also going to import deploy function from Hardhead. Deploy slash types. And these are the two main things you need to create a deploy function with pothead deploy, we're going to create our function, we
're going to call it const ploy governance token, it's going to be of type deploy function. So in order for these to actually work, we just create a whole bunch of deploy functions that we run with heart hub. And this is going to be an async function. That's going to take the hard hat runtime environment as an input parameter that we're going to call HRV. So when we run hard hat deploy, which you'll see in a second, we're actually passing our fake hard hat chain that gets spun up in the backgrou
nd for us, right, we can even do like console dot log Hello. And if we do yarn, hard hat deploy. Actually, before we even do that, if we do yarn, hard hat dash dash help, you'll see, since we imported hard hat deploy up excuse me, we need to add this to our config. First in our config, we're gonna need to do top imports, hard hat deploy top Roscoe need to import at nomic labs slash hard hat ethers, we're also going to need to import at type chain slash hard hat. And then we'll leave it there for
now. We'll have to import more stuff in a second but literally like that. Now, if we do yarn hard hat that should help we should see a new task in here. And we do we actually see a ton of new tasks right? Filled with tasks, check clean compile, console deployed. And this is the new task that we have that actually deploys all of our contracts, anything that's in this deploy folder, our head will go ahead and run right now in our deploy folder. All we have is this console dot log Hello. So if we
run yarn, or hit Deploy, we should See, it just prints out hello. It'll spin up a new blockchain background, while all of our projects and everything, do some type type chain stuff, and it says you'll see this a lot deploy script dot func is not a function. And that's because we actually need to export this now. So we'll do export default, deploy governance token. That's why it's getting mad at us. Now we'll run yarn had her hard hat deploy. And boom, we say hello. So this is how we can actually
deploy all of our scripts. And we can run everything that's in this deploy folder in one go, which is really helpful. So let's go ahead and deploy our governance token first. And this will get a lot faster as we go along. Don't worry, so delete this. And first we're gonna do it, we're gonna say const. We need an account to deploy this first. So we'll say const, get named accounts, deployments, and network equals HRA. And this is going to be a little bit more advanced. This is hard stuff. This i
s this is the slick stuff we're doing here, we're getting these from our hard hat runtime environment, which is being updated from hard hat deploy. So get named accounts is way for us to actually import accounts from our hard hat config, right into our deploy script. So we're gonna go to our hard hat config. And we're gonna create a new config that's a little bit nicer than this. So first, we need to import the hard hat config type. Since we're using type scripts, we're going to import hard hat
user config from hard hat slash config. And we're going to create a config. So I'm just gonna comment this out. For now we're gonna say const. Config, it's gonna be type hard hat user config. Equals, and this is where we can add a whole bunch of stuff. So let's say our default network is going to be hard hat, which is kind of our local fake blockchain. And then we're gonna say solidity is zero, point 8.8, then we're going to do this thing called named accounts, which is what we came here in the
first place for. So this is just a list of accounts that we can use. So for accounts, we'll say Deployer, this will be the name of our account that does all the deploying, and we'll just say, default, is going to be zero. So whenever we run an any chain, our zero with account is going to be named Deployer. What other thing that we need to do is we need to add our networks here. And there's actually two networks that we're going to have, we're gonna have a hard hat with a chain ID of 313337. And
we're also going to have local hosts of chain ID 31337. Now, these look like they're pretty much the same. And I understand that, but they're not. And you'll understand why in a second, but we need them for now. Just to tell Hardhead hey, here are the development fake blockchains that we're working with? Okay. So this is kind of our basic setup here. Okay. I know that was kind of a lot. But now that we have get named accounts, we have network, right? Because anytime you deploy something, it's go
ing to be on a network. And when we deploy something, if you run yarn, hard hat node, what hard hat is going to do, it's going to spin up a fake blockchain in the background. Oh, it's gonna be mad at me for a second. Oh, I forgot to add export, default config, right, we need to export the config. Hell hard hat that we're using this version of sling. Now if you're on a hard hat node, you'll see why we added these two networks up here hard hat on localhost, we actually get spun up our own fake blo
ckchain, we get accounts, we get private keys, we get everything right. This is a hard hat Node running in this terminal, right? When you run hard hat node, oddly enough, it's actually the local host network. It's not the Hard Hat Network. When using hard hat deploy, it's gonna be the local host network. Or excuse me, when you use hard hat node, it's actually going to be the local host network, not the Hard Hat Network. The Hard Hat Network is what it uses when it runs tests. localhost is when y
ou run this hard hat node and have this kind of fake blockchain running in your terminal. So that's what the localhost is. Cool. Well, Ctrl C will kill that. Alright, great. So now stuff is actually working. So get them to count deployments is going to be a whole bunch of stuff from deployments, you'll see in a second and network is the network that we're on. Okay, great. So now we're gonna grab const deploy log equals deployments, this deployments object comes with this deploy function. And thi
s log function, this log function is kind of nice for doing logging. And then we're gonna grab const, employer equals await, get named accounts. So we're grabbing from our config, this deployer account, right? And it's always going to be the zero with index. So it's defaulted to the zero index for whatever accounts that were with. Great. So we now have an account to deploy stuff from we have a deploy function, we have all this stuff, we're looking pretty good. Cool. So sometimes they'll do like
a log, flying governance token, dot, and we'll say const governance token equals await, deploy, and then the name of the contract which is governance token, comma, and these are all the parameters that we're going to pass to it. So we're gonna say from deployer doesn't take any arguments. So args is just going to be blank. We're going to do log to be true so we'll get some logs printed out for us. And then I have this wait confirmations attribute set in GitHub repo. For now we're going to ignore
this. But if you follow along with my repo and you want to auto verify stuff, this is something that you're going to want to use. So you need to wait some amount of blocks for this contract to be deployed before you can actually go ahead and verify it, right. Because if you're using ether scan or something, you're gonna need to wait like, yeah, you're gonna need to wait a few minutes. So check out my GitHub repo for this wait confirmation stuff, I'm just going to ignore it for now. Additionally
, in my GitHub repo, I have this verify function, where we check to see if it's on a development chain. And if it is, we don't verify it. But if it's on like ether scan or something, we go ahead and verify it. So be sure to check the GitHub repo to learn how to just auto verify without having to do anything. Now if we just do this part. And then we can even do Floyd, governance token to address governance token dot address. And we'll do yarn hardhat. Deploy. Boom. So we spin up on a fake Hard Ha
t Network, we do deploy governance token to address boom. And this is how we deploy a fake has deployed this to our own little network here. Great. So this tokens been deployed, we have our deploy script. Yeah, zoom out a little bit. Let's zoom out a little bit. Great. That's the whole thing. Now we're going to add one more thing here, we're going to add something called delegate function. Now, when you actually deploy this contract, nobody has voting power yet. The reason is, because nobody has
the token delegated to them, we want to delegate this token to our Deployer. Right, so we're going to call this delegate function. So we're going to create a new function called const. delegate. And it's going to be an async function. It's going to take a governance token address as a string, it's going to take a delegated account, also as a string, so we're racing and say, who do we want? Delegate? Who do we want to be able to vote with our token? Okay, so we have created this async function c
alled delegate. And how do we do this? Well, we say Kant's over its token equals token equals await ethers dot get contract at. And probably for two ethers for us from hardheaded Otto did that, which is great. That's what we want. Once it's like ethers. Thank you vs. Code away. Ether is like a contract at. And we're going to say we want our governance token, which is at contract, governance token address. And I have auto format unsaved, which is why it keeps formatting like that. This should be
delegated account. Okay, cool. We have our governance token contract. Now we can do const TX or transaction equals await, governance token dot delegate delegate this delegated account here. And then we can do a wait, we'll wait for this transaction to be confirmed by one block. And then we'll just do console dot log checkpoints, wait, governance token dot num checkpoints delegated account? So what is this doing? So we have this num checkpoints function which we can go check to see on that ERC 20
token what this is actually doing. But basically what this whole thing is doing, we have this delegate function that we haven't used it. But when somebody calls us, we're saying, Hey, you can use my vote, take my votes and vote however you want. And that's what these this delegate does. Now, if we look at this token, here, see 20 extensions, your see 20 votes, we look at number checkpoints, we can see how many checkpoints that account actually has reason this is so important is because once aga
in, like I was saying when people do a vote, they do it based off some checkpoints. And anytime you transfer a token, or delegate a token, basically call this function move voting power, which happens with the back end, which writes the checkpoint and says, Hey, at checkpoint x, here's what everybody has for voting powers. And that's what these are so important. And I know I said before, it's every block, but it's actually just every checkpoint, whenever these checkpoints are updated, that's gon
na be a lot cheaper on gas than if we just did every single block, right? That'd be kind of insane. So the checkpoint for this governance checkpoint, and we'll see what that actually is in just a second. So we'll even do a wait, delegate, governance token dot address, and Deployer. And we'll say log delegated. Now, when we're on this function, John Howard hit Deploy. We have one checkpoint, which makes sense, right? Because this was just deployed, it was just delegated. This address has one chec
kpoint. That's it. And the reason I checked for this is because if you see zero checkpoints here, it means you haven't delegated correctly. So be sure to check for checkpoints. But that's it. We have our deployed governance token contract done. Bravo. Let's move on to the next one. So what do we want to do after we deploy our governance token? Well, let's deploy that timelock or timelock.ts. And we're going to copy a lot of this stuff over from here, so I'm actually going to Oh, and then sometim
es you'll get some weird linting errors here. I just do det TS ignore there. And sometimes you'll get it here too. Oh, actually, we don't even need network. Okay, cool. Yeah, you don't even need network loops. Sometimes we get some weird linting errors. Sometimes Vyas code has a hard time telling understanding like this, this overwrite thing that we did. So just run that TS ignore if if it gives you some, some engineers, anyways, yes, we have this Oh, to deploy time lock here, we're going to dep
loy our time lock contract. And we're going to borrow a lot of the things that we did from here, so I'm just going to come back here are actually going to copy paste these two top bits. Again, we're gonna do const deploy timelock is going to be a deploy function, it's going to be an async function that takes the heart at runtime environment as a parameter, and cool, nearly exactly the same sorry. And then we're going to grab these first three lines, or first four lines, I guess, pesos, then we'r
e going to be getting those exact same things here. And we're going to be doing nearly the exact same thing. So we'll do log deploying. Time Lock, point time lock, will do const. Mark equals await, deploy, unlock. We'll add some parameters in here, we'll say from Deployer. Now does this take some arguments? It absolutely does. Right, we can take a look at the Time Lock, Min delay proposers and executors. So what do we want our min delay to be? Well, this is a value that we're actually going to u
se a lot. So what I usually like to do is I create a new file called helper. hardhats config.ts. And right at the top, I'll say Export const min. Delay, and I'll have this delay be whatever I want it to be. So let's just go ahead and do 3600, which is going to be approximately an hour, right, you gotta wait this many seconds, I think that's an hour. Without the old calculator. There's 60 seconds, in 60 minutes. Great. That's gonna be one hour. So wait 30 minutes. And we're gonna go ahead and imp
ort that here. We'll say import, Min delay. Wow, autocomplete for being great. From helper from, you know, it's down directory, helper Hardhead config. And that's gonna be our first argument here. Our second argument is going to be a list of proposals. Now we're going to leave it blank for now. And also the list of executors we're also going to leave it blank for now, we're going to update this in a minute. And you'll see why once we get there, we'll do log true. This also has a wait confirmatio
ns thing in my GitHub, but we're going to skip that for now. It also has an auto verify, we're also gonna skip that for now. Then we just need to export default, deploy timelock. And boom, we should be good. So let's try to run this on hard hat deploying. So now this should run both of these great deployed governance token deployed timelock. Perfect, we are cruising now what we want to deploy that governance contract now. So let's go ahead and do that. We're gonna do Oh, three LOI. Gov, nor cont
ract.ts. And you guessed it, this is going to look pretty similar to what we just did. Right. So in our deployed time lock, let's go ahead and just grab those top two things. We'll paste it in here. We'll do const deploy, govern or contract, there's going to be an apply function, it's going to be an async function, taking a part at runtime environment, save and close this for now. And we can even go back and grab these three lines from our Oh, to deploy time lock, paste that right in here, becau
se we're going to need to get the exact same things. And additionally, for this, we're going to need to get the governance token and the Time Lock contract. So we'll do const governance, token equals await. Get which actually, we have this, this get function that comes from these deployments, which literally just goes out and gets these deployments. So we'll say get Gover Nance token. And then we also need to get the Time Lock. So await, get m lock. And we need these to pass as parameters for ou
r governor contract. Right? Because if we open up the governor contract that soul, we look at the constructor, it takes the token, the Time Lock voting, delay voting period and quorum percentage as input parameters. So we'll do a quick log deploying go burn nor ello. And they will do const govern nor contract equals await, deploy, and will deploy the govern nor contract I'm not sure if I'm spelling this right always, but that's fine. And we'll do the parameters once again. So it's gonna be from
Deployer. args are going to be this list of args. What's the first thing that it needs? It needs the token first and the Time Lock. So we'll do governance token dot address, then it's going to need the Time Lock that address. And it's going to need a vote on voting delay voting period and quorum percentage. So these are also values that we're going to make a lot. So let's open back up that helper Hardhead config, and let's create those as well. So we'll say Export const just voting period. And w
e'll say this is going to be five blocks, we'll do export const voting delay, this is going to be just one block, which I know is really quick. And then we're gonna need export const Orem percentage, which we're gonna say is four 4% of voters always need to be voting. Excuse me, 4% of voters need to have voted for a vote to pass. Great. So we're going to do voting delay voting percentage quorum percentage. So we'll import those so to import voting delay voting period, or quorum percentage from h
elper Hardhead config. And now that we have those delay period percentage, we can just do kind of a voting delay, voting period, farm percentage, and then we'll say log is true. Again, this one as well. It has a wait confirmations and auto verification that we're going to totally ignore. And then we'll export default, blood Governor contract. Oh, Carrie, we're getting spicy. Let's just make sure this works. Yarn hardhat deploy. We should see three contracts deployed here. I think to compile gove
rnance, token deployed timelock deployed governance contract deployed. Let's go. Alright. Now, we're not done yet. We have two more deploy scripts to do. The first one, we're going to call setup governance contracts. Okay. And this one's really important. The right now our time lock contract has no proposers and no executors. Right. So we want to change that we want to only allow for the proposer to be the governor, the governor contract should be the only one that proposes things the Time Lock,
and then anybody should be able to execute the way that this works. We say the governance contract proposes something to the Time Lock once it's in the Time Lock, and it waits that period. Anybody can go ahead and execute it. So Governor contract everybody votes and everything. Once a vote passes, Governor says hey, Time Lock, can you please propose this? Tom like goes yeah, sure. But we got to wait, this minimum delay, once it's been in delay happens, anybody can execute it. Now this would be
really cool to do an integration with chain link keepers, by the way, for the chain link keepers to automatically execute. And I should build the next anyways. So we have to set this up so that these work as such, so we're gonna create a new deploy thing called Oh, four, setup, governance contracts dot TypeScript. And this is going to be the code that does all the setting up. And this is gonna look really similar once again, to all of our other deploy functions. So we'll go head back from oh thr
ee, we'll paste these two top ones in here, of course, we're gonna do const setup contracts, is it going to be a deploy function, going to be an async function, it's going to take HRV art at runtime environment as parameters, and then that's the winner right there. Cool. And we're gonna be grabbing those same three from the top, as you can see, that gets a little bit easier, because it's kind of repetitive, right, we're gonna grab that bit right here. And now we're gonna get those contracts so t
hat we can interact with them. And this is another reason why a hard hat deploy is so nice, because we can just do const timelock equals await ethers that get in the next let's go ahead and import ethers from hard hat imports. Ethers from Red Hat will even drop a little TS ignore here. Ethers dot get contract, we want that time lock contract. And we say we want to attach it to the Deployer. So whenever we call a function on it, it'll be the deployer calling that function and we want to do const
Governor equals await ethers dot get contract, Governor contract, this is all going to be attached to the Deployer. Right. Now, we're gonna do log setting up roles. And we're going to set up the roles right, again, we're setting it up so that only the governor can send things to this time lock, because the Time Lock is going to be you can almost think of the Time Lock as like the president. Right. So everything goes to the Senate, the House representative, which is the governor and then the Pres
ident just says yeah, sure. We just got to wait this minimum delay, but the President will be the one to actually execute everything which I'm not actually sure that's how it really works in in politics, but for for now, that's that's where we're protecting the president or the time like is the only one that can actually do anything here. So the way that this works is we're actually going to get the byte codes of different roles, right? So if you look at these time locks here, so we'll do ones u
p on contracts. And we go to the governance here. We go to Tama controller has these things called proposal roll, executor roll time, like admin, etc. And these are just hashes of these strings here. But these are these are bytes 32 saying, Hey, anybody who has this this byte 32 is a proposer, anybody who has this byte 32 is an executor. Anybody has this byte there and soon as time like admin, etc. Right now, our Deployer account is the time like admin, and that's bad. We don't want that we don'
t want anyone to be a time like admin, right? We don't want anyone to have power over this time lock. We don't want any centralized force here. So what we're going to do is we're going to const we're going to get those roles. proposer, proposer role, it's going to be a weight, unlock that row pole sir role. And if you're familiar with multi call, this would be a great time to do multi call and copy paste that whole line x EQ tour role at x EQ tour roll, we're gonna copy this whole line admin rol
e. And this is going to be on lock admin role. So these are these three roles that we need to fix, right, and let's go ahead and fix them. So the first thing we're gonna need to do is we're gonna need to do const row poser dx equals await Time Lock dot grant roll, propose a roll to our governor dot address. So saying, okay, Governor, you're the only one who can actually do anything once you tell the Time Lock to do something. We'll wait for the Time Lock period to be over. And then we'll be done
. And then we'll just do an await posit TX dot wait one block just to make sure. Now we're gonna do the const executor, TX equals await Time Lock dot grant roll executor role to nobody, we're going to execute this we're gonna give this to nobody, we're going to say address zero which is going to be something that we're going to want to add if we go to our helper or head config will say Export const address zero equals zero by you can just copy paste this if you want. There's a couple other ways
you can do this with ethers as well. We're just gonna do like this. I like having my conflict this and then we just import it say import at zero from dot dot slash helper Harnett config. So we're giving the executor role to nobody, which means everybody. So once a proposers thing has gone through, anybody can execute it. So we'll say executor, TX That wait one wait a block. And then got one more to do here, we need to revoke role right now our Deployer count owns that time lock controller, right
. And that's how we can actually do these transactions, we can actually grant role because our Deployer account owns it now that we've given everybody access. And given all the decentralized access we need, we want to revoke that role. So const revoke TX equals await. I'm locked up revoke role, admin role from Deployer will do Rotex that wait, now guess what anything that's um, like, wants to do has to go through governance, and nobody owns the time I controller, it's currently after this runs,
it's impossible for anyone to do anything with the Time Lock without governance happening. And then of course, when the export default set of contracts, great. And then the last step that we need to do here is we need to deploy the contract that we actually want to govern over write that box contract, that real basic contract. So we're gonna create a new 105, deploy box.ts. And we're gonna do some of the same exact stuff we've done right, so we're gonna grab these two, these two here, paste it i
n, os deploy box is going to be a deploy function equals async function, Ah, sorry, hard hat runtime environment, we're gonna grab those first three lines, the TS ignore, just like that. And now we're going to deploy this box. So log, deploying bucks, and we're going to do const box equals await, deploy box, give us some values from our Deployer. args does this have any args so open a box dot soul, I don't see a constructor. And while this is the easiest contract out of all these though, no cons
tructor, and then we'll just say log, it's going to be true. And again, if you want to check out my GitHub repo for that confirmations, but feel free to do so it's coming here. And right now, our deployer has actually deployed this right, not our time lock. So we want to give the boxes ownership over to our governance process. So now we're going to do say const timelock, is going to be a weight ethers dot get contract. The same thing as before. timelock. We're going to grab ethers from hardhat i
mport ethers from hard hat. And we're gonna do a little TLS ignore, it's being finicky. And then we're going to transfer the ownership of our box to this time lock, okay, and now so this is actually what's known as a box deployment. So before we do that, we have to get the box contract. So this is a box deployment object, which doesn't have contract functions we want to get the box contract object so we to box or const box contract equals await ethers dot get contract at box and then we'll just
do you know box that address. You could also do get contract. Actually both of these pretty much if you have the address, you can just do box that address. You could also do get contract here. Either one works now that we have the box contract, we do const transfer owner, dx equals await by contract dot transfer TX or schema dot transfer ownership to our timelock dot address, time walk dot address, then we just do a weight transfer ownership TX dot weight one, do a log, you done it. Those are ex
port default. Deploy box. Oh, let's see if this works. So we just did everything. We're deploying the GOV token, deploying the timelock, which owns the governance process, we're deployed the governance process, we're setting up the governance process so that it's totally decentralized. And then we deployed and set up our box so that it only can be updated through a governance process. Let's see if it works. Yarn, hard hat deploy. Let's see if it works. Bada boom, you've done it. So you've just s
et up a script to set this entire governance process up so you can build your own doubt. Are you still here? Well, hell yeah, you are, congratulations on getting this far, we have one more piece to go, we just got to write those scripts. So we can actually interact with this, we can actually do a governance, we can actually see exactly what the governance process looks like. Now again, if you didn't watch my last video on Dows, be sure to watch that, because that's going to give you all the cont
ext for this part here. And if you're still watching 100%, smash the like button, hit the subscribe, leave a comment in the comment section below, it really helps the channel out. So proud of you for getting this far. We're almost there, you're getting now one more to go. And then you are home free on building your doubt. Let's get back into it. Alright, so now we're going to make some scripts to actually interact with propose Q and vote on anything that happens in our Dao. And these are the scr
ipts, these are kind of the things that you would do on your front end when you build this when you build your doubt on the front end. Or you could do an integration with snapshot or tally or something like that. And again, if you want to see come to full functionality on the GitHub, I have this test flow.ts It's not the greatest test here. But you can also check this out, because it also does a soup to nuts demonstration of going through this exact process. So let's go ahead and start making so
me scripts. So we're gonna create a new folder called scripts. And this is where we're going to put all of our scripts. Now the process for this is going to be we're first going to propose something right? You know, maybe we're going to propose that our box contract stores the value 77, right? Because when it first gets initialized, it's going to start with zero. So maybe we'll we'll propose it could start at 77. Once proposing is done, we are voting on it. Right once proposals it and we're goin
g to vote on whether or not we want the proposal to go through right yes or no. And then if it passes, we go to queue and execute, we queue first. And then we execute, I'm just putting them both in the same script to make it easier. So let's start with propose here, because it's going to be the first thing that we're going to do. So let's create a new function. We'll call it async function, and then we'll actually export it to export async function propose. And we're going to be in here for a li
ttle bit. So let's clear everything out. And okay, cool. So this is where we're actually going to propose on our governor contract, right? So we're going to propose a new governor contract. So the first thing we're gonna need, of course, is gonna be the governor. So you can't govern nor equals await ethers dot get contract, govern or contract, right? Since we're doing ethers, we're gonna have to do import ethers from heart app. And then we're still getting that fundamental thing. We'll do a litt
le AT Ts ignore here. Cool. So we have the governor contract here, we're going to need the box contract, we're gonna say hey, we want to propose the box contract changes the store value. So we'll do const box equals await ethers dot get this is a gift contract, we want get contract, get contracts at box. And those are the two main ones that we're going to need just to start. Now, if we look at the proposed function, right, if we go to governance, we go to Governor, and we look at that proposed.
This is what it looks like. Now, I explained this proposed function in my last video. So if you haven't seen it, be sure to go back and watch it right because it'll give you everything that you need to know here are basically we pick a list of targets, which our list is just going to be just our box contract. These are the targets that we want to call functions on, we do values like how much needed ether we want to send, which we're not going to send anything, we have bytes, a array called data.
So this is going to be our encoded parameters for the function that we want to call and then a description. So that's exactly what we're going to do here. So first, we need to figure out what we're going to do. So look at Box, we're going to call this store function with this new value here. So we need to encode we need to encode this socks here. And we also need to encode what we want to upgrade it to right so we have to code all the function parameters. So we'll do const encoded function call
equals box and the way we can get this box that interface that encode function data and This is what actually turns it to being this bytes call data, right? So we're encoding everything and this encoded function, you can find this in the ethers documentation, we have to pass it the function to call, and then the arguments we want to pass, right, and this is how we actually get that. So let's get these arguments here. So we're gonna say args, we're going to make our proposed function a little bi
t modular. So we're gonna say args is going to be an array of anything, and then we're gonna say function to call is just going to be a string, right, and then right at the bottom, we're actually gonna call this, this proposed function. So we're gonna say propose, and let's say we want to give it 77, the function is going to be what it's going to be store, store. And that's a string. And this needs to be a list. So we're going to do like this. Now, we're actually going to use this all over the p
lace. So since we're gonna be using this all over the place, we want to stick them in this part head helper config. So what we're going to do is we're gonna say, export const, new store value equals 77. And we're gonna do export const funk equals store. And I propose, we're just going to import those. So we'll do import, new store value, and also funk from helper Hardhead dot config, and it added it in for us, which is great. So we'll just put new store value in here. And then we'll put funk in
here. And I know this might look a little confusing, but basically, the first thing we're gonna do is we're gonna call this proposed function which calls you know, post function up here. Now we're going to do some fun little then process that exit zero. And then we're going to do a dot catch error, which if there's an error, basically, we'll just do console dot log error, then process that makes it. And this is pretty typical setup for a really any script you work with, and hardhat. So great. So
we have constant coded function call, which has this function to call an arc. So we're basically combining these into this bytes thing. And we can even print this out, you can see what this looks like. So you do console dot log, you see that this is like this, this crazy bytes thing here. And the way we can kind of test this, we'll do yarn hardhat node, which will spin up again, our fake blockchain. But additionally, with Hardhead deploy, it will deploy all of our contracts here, right, we can
see timelog governance, you know, everything that we need for testing locally has already been done. So once we have that up, we can then do yarn hardhat, run scripts, propose that TS dash dash network, local host, this is important to do, again, because when you're working with a node that's running locally, you're going to be working with local host, we'll see what it prints out here. Contract named Governor contracts, Governor contract. Let's try that again. And cool, you can see this is what
that encoded function call and arguments looks like is this really long byte string. But if you were to decode this, using the box interface, you would get the function call and the arguments, which is really exciting. So cool, we've encoded it to bytes. And now what we want to do, we encourage the bytes, and now we're going to create that proposal transaction. So we'll do console dot log will say pro posing, and say, function to call on box that address with args. And then we also need to pass
a proposal description. So we're gonna say pro pose, all description, we would do it on new line, why not? Pro pulls all this option, which we don't have yet. Alright, we're gonna get it. So we also need to pass a proposal description, right, because we have down here, description. So let's add another parameter to our propose here. So we'll say proposal description, and this will be also a string. Down at the bottom, we're going to need a proposal description as well. So we'll create a proposa
l or export const proposal description, there's just going to be some string. So we'll say proposal number one, door 77 In the box, that's the description here, comma proposal description. And then we import this or a helper config. Okay, perfect. So now we have the new store value, the function the proposal description, and we can now call that propose that we were just looking at so here's what we're going to do const propose TX equals await. gov dot propose. And we need to pass those lists. S
o first is going to be a list of targets, which for us is just a box that address right only one target. And again, these these little brackets, make it a list of values, which is just going to be zero, a list of encoded function calls or our bytes data, basically, and then the proposal description, and then we're going to do propose, TX dot wait one. Now, if you remember, from compound, this is going to be the exact same if we go back to compound back to governance, this transaction is literall
y going to be the same as this created thing here. Right? And if we scroll down, like more, we can see the code input data, those exact same things on a compound proposal, right? We have targets values signatures, well okay, this CES is a little bit more, this a little bit more advanced here, using signatures, but it's got the same thing called data and then a description here, okay. Now since we have a voting delay, people actually can't vote until the voting delay passes. Now, with a local blo
ckchain, nobody's actually processing blocks and time doesn't really pass as quick as we want. And so we're just going to speed things up for our own testing purposes. So the way I normally do this is I create this this variable, all development, exports, on development chains, and I'll add hard hat and local host. Because we can actually do things with our own local blockchain, we can actually speed up time, we can speed up blocks, we can do all this crazy stuff. So usually, I'll actually impor
t this in here. And then we'll do a quick F. And I'll say, if we're on a development chain, let's just go ahead and speed things up for us. Right. So I'll say if development chains that includes network dot name, and then we can import network from from ethers, as well. And this is what I was talking about those super six skills that you're gonna learn. If it includes network dot name, then we're gonna go ahead and move the blocks forward, right, because if we're not on development chain, we can
't actually move blocks. So what we'll do here is actually I'll create a new folder called utilities, you folder, you are utils. And in here, I'll create a script called Move blocks.ts. And we're just going to create this little function called move blocks, which moves blocks for us. And you'll see how we do this. So we're going to import network from heart app, because we want to speed up that voting delay, we'll do export async function, we'll call it move blocks. And it'll take an amount, whi
ch will be a number, so how many blocks that we actually want to move. And then we'll just do console dot log moving blocks. And we'll say for let index equals zero, index is less than amount. index plus plus, or we're going to do is we're going to do a weight network DAP provider dot request request. And we're going to request method EVM. Mine. So basically, we're mining for our local blockchain, right, so you can find these docks in the hard hat docks in the ethers docks, there's a couple diff
erent places you can find these. But this is kind of this really cool hack that we can use to actually move blocks forward on our local chain. Now, obviously, this won't work on an actual chain, because you'd actually have to do the mining but on our local chains, we can absolutely do this. So we've exported this move blocks function, and we're actually gonna grab that Mark propose, we're going to import move box from utils blocks. And we're going to say down here, if we're on this development c
hain, and do a weight move blocks, and then we'll move blocks by that voting delay that we were talking about, right? Because we need to wait that voting delay in order to move and it looks like an auto import it for us from our helper hardware config. I told you, we were gonna use that a couple of times, but we're gonna move blocks by that voting delay. Now, this proposed transaction does some stuff that we actually want, right? So one of the big things that it wants is, is it has this proposal
ID. And if we scroll down to the event that it emits, it ends up emitting this proposal ID, we actually need the proposal ID for later on when we actually go to vote. So what we're going to do is we're actually going to do const propose receipt equals proposed text dot weight. And we're going to get those events from this proposed receipt. So we're gonna say const. Proposal, id equals proposed receipt, that events, the zero with event because that first event is the only one we care about that
are your stop proposal ID. This is how we get this proposal ID from this omit also created event. A couple other ways to get proposals to get events in hardhat. And I got a video on it on my YouTube, if you want to go check that out. Something else that we want to do is maybe we want to see what the deadline is with a snapshot, you can go ahead and check my GitHub to kind of see what the snapshot looks like or the deadline, basically, how long we have to vote, you know what snapshot you're worki
ng with, and all these different things. But for now, we're just gonna stick with the proposal Id be sure to check out the GitHub for more stuff. Now we want to save this proposal ID, we want to save it somewhere so that our other scripts so that our vote and our queue and execute know what this proposal ID is going to be when we run those. So what we're going to do is we're going to create this file called proposals dot JSON. And it's going to store all of our proposals. So we're gonna say pro
poll, souls dot JSON, it's going to have all of our proposals in here. So what we're going to do and we're going to add this to our helper Hardhead config, and do export const, proposals, file equals proposals dot JSON. And we're going to import this at the top as well as proposals file. And then once we get this proposal ID, we're going to do is we're going to read all the current proposals. So we're gonna say let proposals equals JSON dot parse, and we're gonna do Fs dot read file sync from th
is probe proposals file, and we're going to pass it to UTF eight. Now, this Fs we don't have yet, so we're going to need to import Fs. So we're going to do yarn add Fs like that. If we're looking at package dot JSON. Oops, I should have saved that as Dev, but I didn't Oh, well, doesn't really matter. Now that we have that we can actually import this into our TypeScript. So we're just going to say, import star as Fs from Fs. And now we can actually use Fs F as a way to kind of read from files. No
w we can get this list of proposals. So we got two proposals that JSON right now we're just making a blank JSON. So the first time we run it, it'll just be blank. But later on, it'll have stuff in it. And the way that we're going to save these proposals is we're going to say pro proposals of network dot config dot chain ID, and this little bank to say, yes, there will be a chain id.to string, we're going to store them by their chain IDs, right. So for each network that we have a proposal to we'l
l we'll start like that. And then we'll do dot push proposal, id.to string, and then we'll write it back. We'll do Fs dot right, file sync, proposals file. JSON does string phi, proposals, and awesome. And that's all we need to do. So let's go ahead and actually run this. And then I have some console dot logs in here saying, Hey, here's what the proposal state is, is it open? Is it voting is it canceled, you know, etc. What the proposal snapshot is, you know, again, check my GitHub for that. But
what we can do, now this is done, we can do yarn, Hardhead node, spin up our little note here. And all the contracts are deployed. And then we'll do yarn, run scripts, proposed that TS dash dash network, local host scripts proposed that TS is not found. Pro pose, yarn, hard hat, run scripts, pose IDs, oops, dash dash network, local hosts. Try this again. Now you found it. Yay. Oh, I ran into an issue. Although description Moviebox Cannot read property zero of undefined. Let's see where it got m
ad at me. Poser sheet dot event. It is events, not event shots again, on the localhost. There we go running ran into another issue. Posle already exists. Okay, so great. So the proposal already exists, let's go ahead and just like kill the node, restart the node, so you can't have two proposals that are exactly the same, basically, right. So we can't do that, we would need to change the description or something. So we're just going to kill the node and restart. Now we're going to run this propos
al again. And hopefully this one should work this time. Community Property zero of undefined owes receipt. This needs to be await because it is a promise, kill this one more time we run it once all these get deployed. And we're gonna go ahead and run this. Now you can see how much quicker this is than if you were to actually send this to a test net right to an event a lot of waiting, which is no bueno. And we run into one more Cannot read property, push them undefined. That makes a lot of sense,
too. Because proposals dot JSON as nothing for chain IDs. So 231337. And we'll put a little list in here. Right now it's an empty list. Now we're going to kill this one more time, kill it. And then once this goes, then we're gonna go ahead and do this. Perfect. Now we're going to run this and now it should save and everything should be peachy hunky dory. Awesome. proposal number one store in the box, we move the blocks. And if we look at proposal dot JSON, we now see there's a list of proposals
. And this is the proposal ID of that one we just created. Oh, okay, we made a proposal. Awesome. Nice work, we'll leave that Node running. And hopefully we'll just do things right for the voting. So let's create this vote script now. Okay, so now we proposed it's time to vote, let's do a little voting. So this is going to look pretty similar to that script, we just we just created right. So we're in New async function, we'll call this main proposal index number, and we're calling this main beca
use we're going to have the vote function be a little bit different. You'll see why. And at the bottom, of course, we're going to do main index dot then process dot exit zero, catch error arrow function, console dot error, error, and then process that exit. One main index, we're gonna say our index zero cost index zero. We'll do like this cost index is your postal index. So we're gonna get we're gonna get that bit zero with index, right, the first index in our proposals dot JSON. So whatever is
the first one in this list is what we're gonna use, right? And that's what we want right now. There's only one so it's easy. So we're gonna get that first one in here. So first thing we're gonna need to do is we're gonna need to grab the list of proposals. So we're gonna do const proposals equals JSON dot parse, FS dot read, file sync proposals file, UTF, eight. So of course, we're going to need to import a bunch of stuff. We're going to import proposals file from that a slash a Bernhard config.
And then we're going to do import star as Fs from us. Great. We have Fs, we can read stuff, and we can get those boats. Okay, cool. So we have a list of proposal IDs. Now let's get our proposal idea we'll do const probo. also ID equals proposals of network dot config. And then that's not what we want. We want to actually import network, import network from hard hat, network dot config, that chain ID, exclamation mark of proposal index, which for us is going to be zero, right? We're getting that
first proposal in the list of proposals. Now we're gonna choose how we want to vote. So zero equals against one equals four, and then two is abstain. I don't know why you'd ever abstain abstaining costs gas, you could just not vote, but we're gonna say const vote way and the way we're gonna vote equals one. And we can also do a reason. So if we go back to our governor, there's a couple different functions we get to do to vote, there's cast vote, where we just cast a vote, cast, vote with reason
, and cast vote with signature where we actually do a signature. And I asked this question, Hey, what is cast vote by sick do on the opens up on forum, I was like, hey, what's the what is the purpose of this? My hunch was that anyone could then execute this vote on behalf of me if I didn't send the transaction. And that's exactly what it is. This method implements a meta transaction and allows a project to subsidize voting fees, the voters can generate a signature for free, and the project can s
ubmit those and pay for the gas. So this is incredibly powerful. And this is the function that allows this, this, this cast vote by signature is what allows that snapshot chain link integration that you know, hopefully one of you build, but for us for this, since we're not implementing these meta transactions, these off chain stuff, we're just going to do cast a vote with reason why because we want to give it a reason. That's really it. So we're gonna say const boat TX response equals await. Gov
nor dot cast, excuse me, we need to get the government contract. So we'll do const. Gov nor equals await ethers dot get contract. Gov contract. And then if we don't have ethers, we should get ethers. Great. Let's get ethers. And we'll ignore that. But now we have the contract. So we'll do a weight gov dot cast vote with reason spell this right? With reason. And we'll say proposal ID that way. And then the reason which we don't have a reason here, so let's make a reason. Let's say the reason is
reason, equals I like do cha cha, if you know that film, you should definitely comment it in the description. We have a reason so we're voting for we're saying yes, we want we do indeed want you to change the box to 77. And the reason is because I like a do the Cha Cha makes perfect sense if you don't think about and then we'll do a wait, Kotex response that wait. So I do some stuff, again, checking the state of the proposal where different numbers mean, hey, it's in process, it's voting, etc, w
e could check on that. But we're gonna skip that for now. All we're going to do now, now that we voted, we're going to be the ones to vote. So we're just going to once again move the blocks along. Why because we want to just get to the end of that voting period. So we're gonna do again, if velopment chains, that includes network dot name, then we're gonna do a weight move blocks, voting period, plus one. So we need to import a whole bunch of stuff in here. poses file development, looks like thos
e got auto imported, we need to import this move blocks. So import move blocks from utils blocks, and that network is in here. And then we need voting period from our helper config. voting period. Okay, cool. And then we'll do console dot log, voted, ready to go. Now the reason that I checked the proposal state is because there's this state function in the governor contract. So if we look up state, what this does is it tells us what the state of the proposals in right if it's been executed, retu
rn that's been executed, if it's been canceled, return has been canceled. You have the deadline, check to see if it's active, check to see if quorum reached all this stuff, right? And what you're usually looking for is worm reached and vote succeeded, right? If both of these happen, the proposal state DOT succeeded, right? Otherwise, it's defeated or it's not there yet. I believe this is a one and this is a zero. So if you were to call that function and get the state right, now we should get a z
ero. Or excuse me, we should get a one for this having passed. If you want to do that as a little extra credit, feel free to do so. So let's see if we did this right. Well, actually, I guess we got to change this just to vote. But I just wrapped everything up into main. So let's see if this works. Yarn, hard hat run scripts vote network, local host. So we should get a little console dot log at the bottom that says voted ready to go. So now we're voting. We didn't just go to the Arctic Council, w
e could do yarn, hard hat console, dash dash network, local host. And in here, you can actually just check the state right in here. Why not? We'll copy this line as governor because we either get contract Governor contract. Now we can do a wait, Governor, that's state of go to the proposals dot JSON, grab this, paste it in here. And we get a for the state of this right now is for I forget what four means. It's like a proposal state. The proposal state is actually in the eye governor so the inter
face of the governor We can see, zero is pending, one is active, two cancelled, three defeated, and four have succeeded. So we are in a succeeded state, which is really good. That's exactly what we want. So let's go ahead and quit now. Excuse me Ctrl. C, our proposal is now in a succeeded state. And we've actually moved the blocks along the voting period. So voting is now over because we cheated. So now let's go ahead and queue and execute this to the last bit here. So this is gonna look real si
milar to what we've done already. Right? Let's minimize this, export async, function, Q, and execute. And then at the bottom, we'll just call queue, and execute. And I'm just going to copy paste, but it's that same syntax here, then process exec catch, blah, blah, blah, you get the drill. So in order to queue and execute, go back to the governor contract, not the governor, let's go to the governor. First thing we're going to do is call this queue. Now this Q function is actually in the governor
time lock, which is in this extensions here. So we can find the governor Time Lock controller here, and it does exactly the same as propose we take everything that we did in the proposal, and then we just queue it like so. So we pass the exact same values here. And that's so cute. So what we're going to do is we're gonna need to first get those exact same values, which I told you we're going to use a few times. So we're going to import bunk, new store value, proposal description of our article t
hing, right now that we have all that stuff, we'll say const args equals a new store value, we'll do const box equals await ethers dot get contract, let's get that box contract again, we're gonna have to import ethers from our hat. And this is going to be from we're gonna do TS ignore, then we're once again code this function call to const encoded function call equals Boxtop interface, encode function data. Once again, we're gonna do funk is the function we want to call and args this is like rea
l similar to the our proposed bit that we did. And then we're gonna do content description hash equals ethers dot utils that get GAC 256 ethers dot utils, that to you, TF eight bytes, this will make sense in a second. We're also description. So what's our propose, all we did was pass our proposal description, however, it actually gets hashed on chain, and that's what our view and execute is gonna be looking for, it's gonna be looking for the description hash, instead of just the pure description
, right, and it's gonna be a little bit cheaper gas wise, which is good. So now that we have the description hash, now that we have all the same functions that we did for the suppose it's time to queue them. So do cost gov equals await ethers dot get contract. Gov contract, console dot log will say we're queuing and then we'll do cos Q, dx equals gov dot q. And we're going to pass the exact same parameters we did with the pose except for what the hash instead of the actual proposal, so box that
address zero for eath, and pass that code at function call. And then the description hash rate. And then we're going to do oops, is going to be a weight here. And then we're gonna do a wait. You text Oh, wait, one, wait a block there. And great, then we're all queued up. Now we still have to wait that minimum delay, right? Remember, on our timeline, it's got this min delay thing. It says, Hey, once something gets queued up, you can't just execute it right away. You gotta give people time to get
out. So we're going to speed up time again, we're going to say if development chains develop l meant chains that includes and then it looks like it auto imported for me development chains. Yes, it did. Amazing. That includes network dot name. Let's just make sure we import network from Hardhead. That includes our name, then, of course, we're going to move blocks. But we also actually have to move time here as the minimum delay is looking for some time. So let's create a new util called Move time
. Okay, move time that Yes. And this util is going to allow us to move time so you're learning all the cool stuff. So we'll quickly write a script to do this important network from hard hat export async function move time, how much time will be a number of Mount console dot log, moving time, and let's say await network dot provider dot send EVM increase time and then just by the amount, then we'll just say console dot log, move forward, amount seconds, it goes forward and seconds. Cool. So now w
e have this move time function. That was pretty quick, right? So first, we're going to move time and we're gonna move time by that min delay first, plus one just to be safe. And then we're also going to move blocks. We're gonna do a weight move time, and then a weight move blocks. And we'll just move on block. So got it Import move blocks from utils. It imports move time from those utils as well, time. And then we also have to import this min delay, which we get from our helper. Hardhead config.
Great. So we moved all that stuff. Again, if this were a real chain, you just have to wait. But since we're not a real chain, we can do whatever we want. Yes, love doing whatever I want. Now that it's all cued up, the voters passed, we're looking spicy. Let's drive this home. Xe cuting do a little console dot log executing the const execute TX equals await. gov dot execute. We're going to pass this the exact same set of things we did for the Q TX so I'm literally gonna copy this. paste it down
here. And then we're just going to do a weight SQ TX dot weight. We're going to wait one block. And then the final hour we'll see if the governance updated our box contract const box new value equals await box dot retrieve. And that will do console dot log. New box value. Box new value.to string Oh, so if we did this right, it's new box value to be updated. Let's see if we did it right yarn hard hat run grips Q and execute now work localhost. Did we do it right? Are we successfully done governan
ce? We did. That's okay. We're gonna figure out what we did wrong. Did you mean could check 256 I spelt some stuff wrong. It needs to be spelt like no CK. Just just k. Okay, let's try again. It failed before it actually did. I think that's good. Queuing moving time provider EVM and crit cuz I spelt increased time wrong. Oh, no EVM increase time to just double check. Make sure I'm spelling this right T is actually capital. So I totally messed up. So it's actually already been queued. It's been qu
eued right now on our little node EVM increased team. So we can either delete and kind of restart, or I can just go ahead and I'm just going to comment out a bunch of stuff, we're just going to skip the cueing here. We're gonna run this one more time, because it's already been queued. And now should just execute, we're gonna move time again. But that's fine. Oh, my goodness, we did it. Right. And then normally, you would just do it in one script. But this queue would fail because it was already
queued. Right, you can't queue twice, move forward. In time, we move blocks we executed and we got a new box value completely using our Dow completely decentralized voting completely on chain, no third party trust going in on here. There's no voting booth, there's no you know, spending 1000s of dollars on staff, everything we just voted on happened right in front of our faces. Now, again, I highly recommend go to my GitHub repo, you take a look and you see what's going on here. Again, if you wan
t to see JavaScript stuff, feel free to do some JavaScript stuff. But this goes over how to just get clone and get started if you want to do that as well. But if you walked with me here, if you walked through this with me, you have learned in the absolute Khan, thank you so much for being here. And I'll see you next time. All right. Now, welcome to the final section of our course, the security and auditing section, this one is going to be a little bit less coding and a little bit more explaining
. And most of what we're going to be learning about here is in this Hardhead security FCC section. Throughout this course, we've given you a couple of tips about different security features. One, we talked about reentrancy, we talked a little bit about Oracle Tax, and we're going to talk about those more. And some of the tools we can use to make our code more efficient, to look out for bugs, and to make our code more secure. So we're gonna go ahead, we're gonna go over this hard hat security FCC
code base, and we're going to walk through it a little bit. So one of the first things that we're going to talk about is, what is an audit? Well, an audit is going to be a security focused code review, looking for issues with your code. So for example, let's say we have some code that looks like this, this should be a little bit familiar, because we talked about this in one of our earlier sections with reentrancy, our code, withdraw, goes and sends ether and then updates the balances, this code
is clearly vulnerable to a reentrancy attack here. And this is something that an auditor would catch. Since when we deploy our code, that code is immutable. And that code will always be there, it's really important to have these security reviews done before we deploy our code to a main net, and before we go live, so if you're going to deploy some crazy, massive defy protocol, and you're gonna have billions of dollars of people's money locked into your protocol, you probably want to make sure th
at the money is going to go to the correct places. So audits are incredibly important for the lifecycle of our projects. And we want people to peer review, we want people to review our code to make sure that everything looks good. Now, when we send our code to audit, though, we shouldn't just say hey, here's our code. Can you check them Make sure it's good. That's not going to give an auditor enough information, they need to be able to very easily know what your code does, how to work with it, a
nd what you're looking for. Because auditors aren't going to be kind of this, this failsafe, where if your code is terrible, they're going to catch everything. Auditors are human beings too. They can miss things as well, auditors. Also, don't make sure that your code is bug free. Like I said, audits are security focused peer reviews for your codebase. And when you do send your code to audit, you want to make sure you help out your auditors as much as possible. There's an amazing tweet thread fro
m Tinto and previously was an open Zeplin auditor with a ton of tips and tricks for working with auditors, I highly recommend you pause the video, you click this link and you read through his tweets because they are fantastic. openzeppelin has a readiness guide to try to help you make sure that you're even ready for an audit in the first place. And we've got a link to this readiness guide in the GitHub repository. The summary of them are to add comments to your code, use natspec, which we learne
d about to document your functions, document your functions, document your functions, test, be ready to talk to your auditors, and be prepared to give them plenty of time. They are literally pouring themselves over your code for weeks on end to make sure there's nothing wrong. If you rush your auditors, you're gonna get a rushed audit, and they're going to miss things. So let's talk about the auditing process. In auditing process is going to look like this. First, they're going to run your tests
. That's the first step in order is always going to take and right there, they're gonna find okay, do they have enough code coverage? Is everything passing? What do the tests do? What is the optimal functionality, after an auditor runs tests, they're going to read specs or run your docs. And then they're going to run some fast tools like Slither, linters and static analysis. And that's going to be one of the first things we're going to talk about slither and static analysis. So static analysis i
s the process of just running some program to read over all your code and look for commonly known bugs. One of the most popular static analysis tools is going to be this tool called Slither. And that's going to be one of the first things we're going to do here. So let's go ahead and open up our VS code now. And we'll make a new directory called hardhats security, FCC. We'll cd into it. We'll do code period. And we'll open this up. Now what I want you to do, instead of starting a new folder, and
everything is we're going to get clone, my heart had security FCC. So we'll do git clone, our net security FCC space, and then put a period to clone it into this directory. And we'll get everything like this. Now in here, this comes with a couple of different contracts for us already, that each have a different vulnerability, one of them is going to be bad RNG. This is a contract that picks a random winner of a raffle using block difficulty and message dot sender. This isn't truly random, as the
miners can influence the block dot difficulty, and people can cancel transactions. And there's a ton of ton of different vulnerabilities with creating randomness in this way. We also have this liquid pool as an Oracle, the two most common types of attacks are reentrancy, which we've learned about an Oracle manipulation attacks, which luckily for you, we've taught you about decentralized Oracle's and working with chain link, which should make you a lot safer. And especially for this section, I'm
going to harp on these, please, please, please, if you taking this course, please do not make a protocol that falls victim to one of these, I will feel like I have failed you. If you build a protocol where you use some centralized oracle that gets manipulated, or you build a protocol that has a reentrancy attack. The tools that I'm going to show you right here are going to help you with reentrancy. And everything I've taught you about chain link should hopefully teach you how to not get Oracle
manipulated. So in this contract here, we're using a liquidity pool as an Oracle and this is kind of some advanced defy stuff here. This is a minimalistic decentralized exchange example where people can buy and sell and swap different assets. Now using this singular exchange, to get the swap price is a terrible idea. Because this is a single protocol for a single price. The price from this protocol is a single centralized location, and we don't want to get our price from a single centralized exc
hange. We want to get it from many exchanges. Getting the price of any asset from a single decentralized exchange is not decentralized, is somebody manipulates the market doing some crazy advanced defy things that will ruin the price of your assets. So getting the price of your assets from a centralized location is a terrible idea. We have a metamorphic proxy here. The issue here is that it's initialized double, and we don't guarantee that the contract has been initialized. We have a classic ree
ntrancy issue here. And then we have and then we have a vault here where some password is stored on chain and we're crossing our fingers that nobody reads this password to unlock it. So we're going to run some static analysis on these contracts, see if that static analysis can spot some of the bad things in here. To get started, we're going to use a tool like I said called slither slither tool was created by this Crytek team, aka the trilobites team. Now, trilobites is one of my absolute favorit
e auditors in the space. And I absolutely love all the tools that this team puts out, they put up open source security tools for any of us to use such as slitter. Now to get started with Slither, we actually need to install Python first. So you can also run it with Docker. But I'm going to show you how to how to work with Python first. So if you haven't worked with Python, before, you can come to python.org/downloads and download Python right from the website, you'll know you've done it right. A
nd you can run python three dash dash version, like this. Or if you have an older version of Python, you can run Python dash dash version. Once you install Python, you should also have this tool called PIP three installed and you can check by running PIP three dash dash version, or PIP dash dash version. And we also want to install this sock select package just in case we're using weird versions of solidity to install. So select, we run PIP three, install sock select, like that. And then we can
do sock, select, use. And then we can choose the version of solidity or slither to work with. Once you have those tools, you can just run PIP three install slither analyzer like so. And you can install slither into your Python environment. I'm not going to run it because already have. You can also learn how to do this all with Docker and we'll learn how to do this with Docker in a little bit. Now in our package json, we actually have command script in our package. JSON for running Slither, you'l
l know you've installed slither correctly. If you can run Slither, dash dash help you get an output like this. Now we can use slither to run it on our contracts folder by running this big command here. So we'll say Slither. And we want to run it on dot slash contracts, we need to tell it that it has some psaltery mappings, and every time it sees open Zeppelin, it should use Node module slash open Zeppelin and every time it sees chain link introduced node modules slash chain link. And I'm just go
ing to read from our package json. And we're excluding a couple of functions that it runs and excluding builder ignore, but don't worry too much about that. We've actually just run that by first running yarn to install all of our packages. And after we've installed all of our packages, we can run yarn Slither. Or you can copy paste that slither command and run it directly. Now we'll get this massive output that looks like this with some red and some green. Let's go through what's actually happen
ing here, the way that we can read Slither, it'll list out a number of lines that have an issue and then a reference to that issue. And each one of these is separated by a new line. So that's a section that's exception, etc. So if we get a red here, that means that there is a high impact issue that we definitely should address. And it even comes with a reference link that we can copy paste and put into our browser and see what the issue is and more information from the slither tool about what th
at issue is and how to correct it. We can see it catches our metamorphic contract issue. It says metamorphic contract is never initialized. It is used here in metamorphic dot kill. The reason that this is a massive issue, if we go to our metamorphic contract outsole is that if we deploy this contract, somebody else could initialize this code, become the owner, and then automatically kill it before we even have a chance. This is actually something that has happened in the past and has caused a to
n of issues. So if we see red in the terminal, this means Hey, massive issue, we should absolutely check it out. Now there's gonna be a ton of green in here. These are detectors that are probably low impact, and they're probably okay. And in fact, we can see, it's even just calling out some opens up on stuff here, saying, Hey, we see some inline assembly. Inline assembly is kind of scary, maybe don't use that. So you can think of green as kind of a warning that there's a low likelihood that this
will impact anything, but you might want to check it out, we get this different versions of solidity used, which is just saying, hey, there's a couple different versions of solidity that might be something you want to keep in mind, maybe you should use the same versions of solidity. We have this allow old versions. And this is actually why throughout this whole course, we've been using zero point 8.7 Because zero point 8.4 and zero point 8.7 are considered more stable versions of solidity. So i
f you're using versions outside of there, so there will say hey, maybe you want to work with a different version. We have some flags in here about maybe Hey, you should make a variable constant because it never changes which is great. Uses literal with too many digits saying hey, this Just kind of hard to read, maybe you screwed up some of the zeros, loud old versions. And what's this reentrancy in ether store dot withdraw. So just by running this slither tool, we can catch a reentrancy vulnerab
ility in one of our contracts, which is fantastic. So running the static analysis caught at least two huge vulnerabilities in our metamorphic contract. And in our reentrancy contract, it didn't catch the issues involved at sole liquidity pool, or bad RNG, though, which is why we don't only want to rely on slither because it's not going to catch everything, but it will catch a lot of major vulnerabilities. So that's how we can use Slither, at least from a middle middle stack point to get started.
So great, we just learned how to work with Slither. That's one of the first tools that are really fantastic in our audit process. And that's going to be considered a fast tool for static analysis, running tests, linters, etc, are also types of static analysis. After we run a tool like that, we enter some manual analysis where we walk through the code ourselves manually, and maybe we do it in tangent with running some slower tools, like a kitna Manta Corp, and other symbolic execution tools. Sym
bolic Execution is where we simulate executing transactions on the blockchain. And one of these symbolic execution tools that we're going to work with is this a kidmin tool. Again, this is a trail of bits tool for doing something called fuzz testing. Now in programming, fuzzing or fuzz testing is an automated software testing technique that involves providing invalid unexpected or random data as inputs to a computer program. In a lot of our code, oftentimes, we're going to get people interacting
with them in ways that we will never think about. So we want to be able to provide random data and random information to our test to see if something weird happens that we weren't expecting. So we can actually build our own fuzz tests in our hard hat projects and run these fuzz tests, I've actually created a sample of fuzz tests, we write our fuzz tests in solidity, actually, as opposed to writing our tests in JavaScript. So let's say for example, we've built this vault contract. And we think t
hat at first glance, hey, nobody should ever be able to know the password, and no one should ever be able to unlock this contract. Which obviously, we know is ridiculous, because we know that anybody can read anything in a storage variable. So we know that this should fail, but it might be hard to write a test. To catch that this actually would fail. A good approach to testing this would be to just send a ton of random bytes 32 objects to this unlock function to see if we can unlock it. We can w
rite a fuzz test to do exactly that. So in my vault, fuzz test dot Sol, we're importing vault outsole. And so we're saying vault fuzz test is vault and we have a password of 123, ASD 123. And now we have a function called a kid and a test find password, where it's going to send a ton of random data into vault to try to make s locked equal false. So we just say s locked equals true here, and our first test will try to make s locked equals false. Now we could install just the kitna, but at this po
int, it's a good idea to bring up our the security toolbox from trail of bits. So trail of bits has a package called the eath security toolbox, which has all their security tools in one single container kitna, Ethan o Manta core, slither, rattle, and not so smart contracts, it has all these in the same exact package. Now to work with this toolbox. We're gonna need Docker installed. So we're gonna do a little bit of installation here. And again, sometimes this can be the hardest part of the cours
e is just installing these packages. So we've left a link to Doc's dot docker.com, get Docker to install Docker, to actually work with these tools, you're just going to come you're going to click whichever one of these is appropriate for you to install Docker, once we have Docker installed, we can run the E security toolbox by pulling it down from the Docker equivalent of GitHub. And we're going to use a whole bunch of Docker commands that I'm not going to explain here because this isn't a Docke
r course, if you're looking to get into the security stuff, I would definitely recommend reading up on all these commands afterwards. And we're going to leave a ton of links for you to learn more. And in the package that JSON associated with this lesson. We even have the command to get set up right in here. So we can just run yarn toolbox, which will run our Docker command like this. So I'm just going to run yarn toolbox. And if you get something like this saying cannot connect to the Docker dae
mon is the Docker daemon running, because I need to have my Docker daemon running. Since I installed Docker desktop. I need to have my Docker engine started and running for it to actually be working. Again to work with this. There's a lot of Docker setup and configuration that needs to happen, which I'm going to leave a ton of instructions on how to get started with Docker. Once we have Docker setup. Now we can run yarn toolbox, which will stick us into a new shell to work with any of these tool
s that trilobites has Out of the box. Now our vault fuzz test comes with a config as well. This is in a Yamo file with all our arguments for running a kidnap. So it has a test limit, which is how many different runs, we should do a time delay, block delay. And then of course, some re mappings in here. This darker shell will already have the security tools already installed like the Kidner test. So we'll run a kinah test on SRC slash contracts slash test slash fuzzing slash fault fuzz test dot So
l dash dash contract will be vault fuzz test, dash dash config will be SRC slash contracts slash test slash buzzing slash config dot Yamo. And we'll go ahead and we'll hit enter here, and it'll say analyzing contract, it'll give us an output like this, it will give us an output that looks like this. What it's saying is it found a use case where it could make s locked equals false. And the use case was 123, ASD 123. So when what seemed like almost seconds, it found the password to unlock our cont
ract. And this is why running a fuzz tester can be so powerful, we thought our contract was secure, but it immediately found the password, which means anybody else could immediately find the password. And this would be an indicator that what we're doing there is not a good setup. So we'll hit CTRL C to escape. And to leave our Docker setup here, we'll just write exit. Now again, I'm going to leave a ton of links to work with a kidnapper and work with this fuzz tester in the GitHub repo associate
d with this lesson, so that you can go ahead and learn more. Now, if you take anything away from this whole section, it should be this right here. The two most common tasks are reentrant. See, and Oracle manipulation. So if you're not going to be an auditor, and you just want to deploy things to main net, always, always before you deploy anything, the absolute minimum that you should be doing is always running Slither. And then looking manually for Oracle manipulation and reentrancy attacks. If
you see in your code that you're getting pricing information. Price is a piece of data that we as humans have assigned to something if you're getting pricing information from a centralized location, rethink that scenario, rethink what you're doing there. If you're getting a random number, if you're doing any type of automation from a centralized location, rethink it and change your strategy. The chain link Oracle network has been created for a reason to prevent getting hacked like this. So pleas
e keep these in mind before you deploy anything to main that with any type of security guarantees. Okay, great. So we've learned about the fast tools, we've learned about some of the slow tools. We didn't look into Manta Corp or Mythix. But these are also tools that you can use Manta Corp is going to be another tool from the trilobites team. And Mythix is actually a smart contract security service from the consensus team, you basically send a bot that they have running in the cloud your contract
s and will do some automated process to check for security vulnerabilities. This is a paid service. But if you're going to be deploying a protocol that's worth millions of dollars, spending a few $1,000. Spending a few $1,000 to make sure it actually does. What it says is going to do correctly is definitely something that you want to invest in. After you run through this whole process. You the smart contract developers and the auditors should discuss their findings. And if there's any issues, re
peat the steps, repeat all the steps again after changes are made. So this audit process and making sure your contracts are secure is a long process. And then afterwards, an auditor will finally write your report with all security vulnerabilities and everything that they found in your contracts. Typically, you'll organize reports in a chart that'll look something like this, you'll label issues that have a high chance of happening and have a high impact as critical things that have a high impact,
but a low likelihood as medium, and etc. I'm also going to leave some examples two audits that have been done in the past so that you can take a look at them. And you can see what a full audit looks like on certain code. We'll be looking at openzeppelin sigma prime, and trilobites, because these are three of what I think are some of the best auditors in the space. Now in the GitHub repo. We also have a ton of other tools that you can use Mythix, mithril ethers play and consensus security tools.
If you want to learn more about security and auditing, I highly recommend that after this course you play the Ethernet game and damn vulnerable Defy. These are two games that will teach you a ton about security. And we'll test the chops and we'll test everything that you've learned in this course. There's also a couple of security focused blogs that I really like. One of them in particular is wrecked dot news. They keep a running list of some of the largest hacks that have ever happened in the
space and then retrospectives on why those actually happened. And they usually make it very entertaining as well. We have some articles in here as well. One of the best places to look at is this known attacks section where they talk Talk about reentrancy, Oracle manipulation, front running and a ton of other attacks that you should absolutely be aware of when writing your smart contracts, we're not going to go over them here because they do a great job in these resources explaining them, you sho
uld also check out this article because I helped write it. So definitely check that out. And then we've got a list to even more sections. So this is going to be a living section here. So please feel free. If you find more things in the future, please feel free to make pull requests and update this repository so that other people can learn and know more about security and auditing and have contract examples on what bad code looks like and how to actually catch them. Even though this was one of ou
r quickest sections. From a video standpoint, this actually is going to be one of the longest sections of your career. Security is something that is always going to be on your mind. And there's always going to be new tools to help with security. And there's always going to be new things to think about. So even though we went through this very quickly, I would 100% want you to pause this video, and work with and try out some of the tools we tried here. And then maybe even try coming up with your
own vulnerabilities as well. And with that being said, you have just finished the last section of this massive master course on learning smart contracts, solidity, web three and blockchain development, you should be incredibly proud of yourself. Congratulations, I and the web three 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 finish
ed the course, go back and finish it before 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 web three 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 three in the blockchain community. Now a lot of people ask, Well, where do I go? Now, I didn't have all this newfound knowledge. I'm armed with the i
ntelligence of the web three developer space. Well, I've left some links in the GitHub repository to lead 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 bootcamp 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 into 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 hand holding you is where you're going to learn 10 times as much as what you've learned here. I've walked through 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'm so excited to see you in the community and see what you build and see what we can create with this technology.

Comments