Feb. 28, 2024

Solidity, Blockchain, and Smart Contract Course – Beginner to Expert Python Tutorial



Published May 23, 2023, 5:20 p.m. by Courtney


When it comes to learning how to code, there are a lot of different options out there. But if you're looking to learn Solidity, blockchain, and Smart Contract development, then the FreeCodeCamp.org python tutorial is the perfect place to start.

This tutorial is designed for absolute beginners, and will walk you through everything you need to know to get started with coding in python. You'll learn how to install python, write basic code, and even create your own smart contracts.

Best of all, the entire course is absolutely free. So if you're ready to start your coding journey, head on over to FreeCodeCamp.org and check out the python tutorial today.

You may also like to read about:



hello everybody and welcome to the free

code camp blockchain and solidity

beginner to expert full course python

edition we're going to go through

everything you need to know for

developing on a blockchain using

solidity and engaging in the future of

finance we're going to cover topics that

will teach you all the skills you need

to become a smart contract expert that

you can take with you no matter which

blockchain you're developing on

blockchain engineers are in extreme

demand and they're building billion

dollar applications almost every day at

this point at the time of filming

protocols like ave yearn.finance and

synthetics have billions of dollars of

locked value in them allowing people to

engage in decentralized finance or defy

this allows people to make censorship

resistant moves and so much more some of

these protocols with billions of dollars

are even less than a year old so whether

or not you're brand new to this space or

you've been in here a while hi my name

is patrick collins and i live in the

smart contract world i'll be taking you

through your journey to becoming a

blockchain and smart contract expert a

little bit of background on myself i'm

an engineer and developer advocate on

the chain link protocol and i also have

my own blockchain infrastructure company

called alphachain where i run different

nodes and different infrastructure for

blockchains including one of the main

technologies we're going to be talking

about today which is ethereum i love

being a pioneer in the smart contract

ecosystem and i love taking new users

like yourself along to the journey with

us and we are going to teach you to

become a smart contract expert building

blockchain and solidity applications is

building a world of more trust and

accountability it means building a

financially free future and we get to be

the ones that will go down in the

history books as the pioneers of this

space additionally blockchain and smart

contract engineering skills are some of

the most sought after in the world with

an average salary of a solidity

developer being between 150 and 175 000

in this video we're going to teach you

how to become one of these developers

and go out into the world and

participate in the world of smart

contracts in the world of blockchain

this course is ideally for engineers who

know a little bit of python programming

and you can have any level of smart

contract engineering whether you're a

complete beginner to blockchains and you

don't even know what one is or you're an

advanced solidity engineer and you're

looking to learn more this is the

perfect place for you having a little

bit of experience in other

object-oriented programming language

like javascript as well will be helpful

here too and if you're brand new to

coding in general that's all right

because we're going to take you step by

step through everything if you do want a

little bit more in-depth python coding

video there is a fantastic free code

camp video in the description if you do

prefer javascript we will also be

releasing a javascript edition of this

video as well but everything that you

learn here will be applicable there and

if you watch both you'll learn even more

you can find the entire itinerary for

this entire course along with all of the

code associated with everything that we

do and additionally discussions and

support and everything else in this

smart contract kit

full blockchain solidity course pi

github repository it has a table of

contents and then the entire itinerary

of everything that we're going to go

over in this course and like i said with

helpful tips resources for getting

support and resources for getting help

now for your convenience every single

piece of code that we're going to go

over in this video has a github

repository associated with it so be sure

to grab the link in the description grab

that github repository and look through

all the different repos that we're going

to give you if you ever get lost or need

to refer to some code or want to copy

paste some code all of it will be there

for you it'll also be a great place to

reference in the future when you're

working on some project and you want to

remember how to do something so be sure

to start and refer back to it as you

watch this video so let's talk a little

bit about some best practices for

watching this video this space moves

really quickly so if we show you some

documentation it might be a good idea

for you to open that documentation up as

well read through it as we do so you can

stay up to speed now we've packed a ton

of information in this video and studies

have shown if you try to digest a

massive amount of information in a short

period of time your retention isn't as

good so it's highly recommended that

every 25 minutes to half an hour you

take a five minute break and then every

two hours maybe you take an additional

30 minute or an hour long break you can

pause bookmark areas and come back later

and learn at your own speed there are

timestamps in the description that will

help you come back to where you left off

and you don't even have to go in order

if you want to bounce around from topic

to topic you're absolutely free to do so

we're also going to get really technical

with the fundamentals of blockchain and

if you want to just jump right into

solidity you can jump down the

timestamps below and get right into it

and if you're watching this on youtube

you can adjust the speed that i talk and

then i give this presentation so if i'm

talking way too quickly for you you can

slow it down or if i'm talking too

slowly for you you can have me speed up

so be sure to set me at the pace that

you like best you are highly encouraged

to pause come back and ask questions the

blockchain in smart contract world is a

very collaborative community so if you

have questions some of the best places

that you can go going to stack overflow

and tagging your question with the

specific technologies that you're

working on make an issue on the github

repo that we're working with go to stack

exchange eth and make a question there

as well jump into the discord of the

technology that you're working with or

even on github discussions if those are

there learning to become a blockchain

and solidity engineer is actually a lot

more than just learning solidity

becoming comfortable with all the tools

in the space is going to be just as

essential as becoming familiar with

solidity itself and continuing the

conversation on maybe twitter or reddit

or any of these other channels and maybe

even showing your stuff in the next

ethereum or chainlink hackathon are

going to be majorly beneficial to

increasing your skill as an engineer

now before we get actually coding a lot

of people want to understand what is

actually happening with all this

blockchain stuff what is blockchain what

is a smart contract how did this all get

started and understanding these core

fundamentals will actually shape the way

you code and architect your smart

contract applications so learning these

is really really critical

however if you're already familiar with

blockchain and you just want to jump

into the solidity feel free to grab a

timestamp from the description and jump

to that section

now since you're here though you've

probably heard of bitcoin before bitcoin

was one of the first protocols to use

this revolutionary technology called

blockchain the bitcoin whitepaper was

released by the pseudo-anonymous satoshi

nakamoto and it outlined how bitcoin

could be used to make peer-to-peer

transactions in a decentralized network

this network is powered by cryptography

and allows people to engage in

censorship resistant finance in a

decentralized manner due to some of the

features of bitcoin a lot of people took

it to be as a superior store of value

over another asset like let's say gold

and that's why it's commonly referred to

as digital gold similar to gold there is

a scarce and set amount of it on the

planet and people use it to buy and sell

similar to other assets you can read

more about the original vision in the

white paper and there's a link to it in

the description

now this was a fantastic breakthrough

and in a little bit we're actually going

to look through how blockchains can

actually work and how all of this is

possible but some people took this and

saw this technology and thought that

they could do even more a few years

later a man named metallic buterin

released a white paper describing a new

protocol called ethereum which used this

same blockchain infrastructure but

with an additional feature and in 2015

they released this project called

ethereum him and a number of other

co-founders took this blockchain

technology and applied it in ways that

people can make entirely decentralized

applications decentralize organizations

and build smart contracts and engage in

agreements without a third-party

intermediary or centralized governing

force their idea was to take the same

pieces that made bitcoin great and add

smart contracts to it and in fact this

technically wasn't even a new idea back

in 1994 a man named nick zabo proposed a

technology called smart contracts a

smart contract is a self-executing set

of instructions that is executed without

a third party intermediary they come to

life on a blockchain and these smart

contracts are really going to be the

core thing that we're going to be

working with and we're going to be

developing smart contracts are similar

to regular traditional contracts that

people make between each other but

instead of writing these contracts down

on pen and paper or typing that on the

computer it's entirely written in code

the terms of the agreement are written

in code and automatically executed by

the decentralized blockchain network

instead of being written pen and paper

and executed by the two parties or three

parties or however many parties involved

this is one of the main differentiators

between the ethereum protocol and the

bitcoin protocol now technically bitcoin

does also have smart contracts however

they're not touring complete meaning

that they don't have the full range of

capabilities as a turing complete

application like ethereum this is

actually an intentional move by the

bitcoin developers they view the bitcoin

network as an asset whereas ethereum and

the ethereum and developers viewed that

acid as an asset and also a utility for

people to build these smart contracts

now these smart contracts are

revolutionary technologies and we're

going to talk a little bit more about

what their advantage is in a little bit

but they actually come with a fatal flaw

with what's known as the oracle problem

these blockchains are deterministic

systems and we'll learn why they're

deterministic very soon and this

determinism means that they're a walled

garden meaning that everything that

happens in these smart contracts and on

this blockchain happens in this little

box now of course if you want these

smart contracts to actually be these

digital superior agreements then they

need some way to interact with the real

world and get real data and external

outside the blockchain computation this

is where oracles come into play oracles

are devices that bring data into a

blockchain or

execute some type of external

computation so great so oracles are the

solution now blockchains can talk to the

real world right

well not quite our blockchains and smart

contracts are these decentralized

applications and in order for them to

stay decentralized that means they would

also need to get their data and external

computation from a decentralized manner

as well your on-chain logic will be

decentralized on the blockchain but

you'll also need your off-chain data and

external computation decentralized as

well combining these on-chain logic

settlement layers and these off-chain

data and external computation

builds what's called hybrid smart

contracts and a large majority of d5

applications in the largest applications

today are these hybrid smart contracts

this is where the protocol chain link

comes into play chain link is a

decentralized modular oracle network

that allows you to bring data into your

smart contracts and do external

computation and it's these hybrid smart

contracts that can have this on-chain

settlement and interact with the real

world in some meaningful way chain link

is an incredibly powerful oracle network

because it allows us to get data get

randomness do some type of upkeep or

really customize our smart contracts in

any way we want and elevate them to do

anything that we want them to do now

throughout the course when we're talking

about smart contracts oftentimes we are

also talking about hybrid smart

contracts smart contracts is used a

little bit interchangeably with hybrid

smart contracts but just know that when

we say hybrid smart contract we're

talking specifically about smart

contracts with an off chain component

now throughout this video you'll hear

people say smart contract you'll hear

people say decentralized protocol

decentralized application or dap and

they kind of all are a little bit

interchangeable a decentralized

application is usually a combination of

several smart contracts

and when we start coding some solidity

you'll see what a singular smart

contract or singular contract looks like

smart contracts are going to be what we

code write and deploy for the majority

of this video and learning some of these

fundamental concepts will allow us to be

better smart contract and better

solidity developers now since its

inception the ethereum protocol has

given rise to many new paradigms and

industries including d5 nfts

dows or decentralized autonomous

organizations

layer twos and so much more

and a couple of other protocols have

taken this ethereum vision and gone in a

different direction with it like polygon

polka dot or avalanche if we learn the

core basics of smart contract

development on the ethereum platform all

these skills translate to these other

chains as well so don't worry about

learning a specific tool or chain

because most of them work together

pretty seamlessly

now there are a few exceptions to this

rule and there are some smart contract

platforms aka blockchains that don't use

solidity however learning the

fundamental skills here will still

translate to every single other

blockchain

and ethereum is by far the most popular

and most used smart contract blockchain

or smart contract protocol you'll also

hear those words used a little

interchangeably as well sometimes i'll

say blockchain or sometimes i'll say

smart contract platform smart contract

protocol and the like similarly chain

link is the most popular and powerful

decentralized oracle network and is

going to be the one that we're going to

focus on here chain link is also

blockchain and smart contract platform

agnostic meaning it'll work on ethereum

avalanche polygon polka or really any

blockchain or smart contract platform

out there

even in this introduction we've already

learned a lot so let's do a quick

summary of what we've talked about

bitcoin was the first application to

take the blockchain technology into the

limelight and into a meaningful way

bitcoin is a sort of digital gold able

to make transactions between users as

almost a sort of currency ethereum takes

this blockchain technology one step

further but you can also build smart

contract or decentralized applications

decentralized autonomous organizations

and more because you can code with smart

contracts these smart contracts can then

access external data and external

computation outside the blockchain using

what's called oracles chain link is the

most powerful decentralized oracle

network and allows us to build these

hybrid smart contracts which is a

combination of decentralized on-chain

logic settlement layer and any

decentralized external off-chain data or

computation hybrid smart contracts and

smart contracts are often used

interchangeably now you're probably

asking yourself a lot of questions right

now like what makes bitcoin so

interesting what makes it like a digital

gold and how are these smart contracts

going to add any value to the real world

and that's what we're going to go into

now so before we get into the

nitty-gritty of how these blockchains

and how these smart contracts actually

work from a low level let's go

high level and talk about some of the

features and massive advantages that

blockchains and smart contracts have

over our traditional environments the

first feature that these have is they

are decentralized and you'll hear this

term used a lot because it has a massive

benefit blockchains are decentralized

meaning there's no centralized source

that controls the blockchain the

individuals that make up blockchain are

known as node operators and they are the

independent individuals running the

software that connects the whole

blockchain together it's all these

different independent individuals that

make the blockchain and blockchain like

networks decentralized we'll dive deeper

into that concept later great example of

why this is so fundamentally

groundbreaking is if we go back to what

happened recently even with robinhood

and gamestop gamestop shares were no

longer allowed to be bought because a

centralized entity didn't want them to

be bought anymore so they

flipped a switch and nobody could buy

that stock anymore essentially having a

single entity controlling the entire

financial market the fact that a single

entity has the power to make these

choices for us is a travesty and

blockchain is here to solve that there's

a narrative here called the bankless

narrative where users can actually live

in a world where they don't have a bank

banks while good in their own right have

a history of doing some shady things

they also have the power to potentially

freeze your funds not letting you

withdraw or move or do anything because

they are a centralized entity that again

can

flip a switch and control how you

interact with your life every day being

free of these centralized entities have

this much power and this much control

over your life has widespread positive

ramifications transparency and

flexibility

everything that's done on a blockchain

and all the rules that are made can be

seen by everyone there's no backdoor

deals there's no shady happenings

everything that happens on chain you can

see this means that there's no special

information that a few have

everyone has to play by the same rules

and everyone can see exactly what those

rules are

now additionally this doesn't mean that

everything you do is tracked the

blockchain is pseudo-anonymous so you

can create different accounts and you

can interact with it in many different

ways this leads me to my freedom point

but i'll get there in a second speed and

efficiency have you ever tried to make a

withdrawal from the bank and it took

three to five days

all the bank is doing is adding and

subtracting numbers

basic first grade math

so why does it take so long because

blockchains are verified by a

decentralized collective the settlement

or withdrawal period in this case is

substantially faster and depending on

the blockchain that you're using it can

be from

10 minutes all the way down to just a

couple of seconds in the stock trading

or hedge fund world it can actually take

up to a week for your buy or sell of a

stock to go through security and

immutability blockchains are immutable

which means they can't be changed and

because of this it means that they can't

be tampered with or corrupted in any way

shape or form this allows us to have

massive security on our data on our

transactions and anything of the like if

your computer goes down and your backup

computers go down

in the regular world your data is gone

if all your data is on those two

computers you're out of luck on a

blockchain if several nodes go down it

doesn't matter because as long as one

node and the entire system is running

the data is safe and secure there are

thousands or hundreds of thousands of

nodes running these blockchain softwares

meaning that everything that happens

happens and is immutable and won't

change

hacking the blockchain is nearly

impossible and substantially harder than

hacking a centralized entity and this is

also much more secure in the asset sense

as well instead of having gold in a

vault or contract written on a piece of

paper or on your computer you have a

asset that is

locked on the blockchain forever and all

you need to do to access it is have a

private key or mnemonic

which is essentially a password so you

don't have to lug your gold around or

lug your contracts around with you it is

always on the blockchain smart contracts

in particular remove a massive conflict

of interest in the traditional world

when we engage with users or individuals

they don't always have our best

interests at heart

a lot of them are usually self-motivated

in some sense and there's nothing wrong

with that that's how a lot of people are

however when we make an agreement with

them this agreement can have a massive

conflict of interest with the user who's

supposed to execute that agreement

let's take insurance for example if i

pay an insurance provider 100 a month

i'm paying them a hundred dollars and in

the event that i get hit by a bus we've

made an agreement or a contract that

they're going to pay my medical bills or

bail me out however they have this

massive conflict of interest insurance

companies aren't in the business of

giving out money they're in the business

of making money so even though they've

signed this agreement when this event

occurs they still don't want to pay this

money out to me and if they can find a

loophole in the contract they will

because that is what they are motivated

to do so they sign this agreement but

it's not in their best interest to do so

so they have this massive conflict of

interest and this is native in all of

the agreements that we make today they

are the ones who decides whether or not

they're going to execute their agreement

giving execution power to the party that

doesn't want to execute something has

often led to frustration now the

follow-up is you can always sue them and

go through this process but now you're

wasting all this time going through this

long process to get something that you

should have originally gotten in the

first place

this leads me to one of the biggest

value adds to smart contracts smart

contracts allow us to engage in

trustless and trust minimized agreements

we currently live in a world of

brand-based agreements

if i engage in some agreement and i

don't like the service that i'm provided

my alternative to this is to waltz down

the street to another brand to another

service who's going to make the exact

same set of promises to me and then i

have to trust them that they're going to

execute faithfully smart contracts allow

us to move from this brand based

agreements to

math-based agreements these math-based

agreements we don't even have to trust

that they're going to do the right thing

hence the name trustless one plus one is

always going to equal two in a math

world whatever the code determines is

the input output that's exactly what's

gonna happen every single time

now for me these really all add up to

two major pieces

freedom

and trustless all these pieces allow us

to live in a world that's more

accountable more trusting more friendly

and

just better it allows us to work in an

environment and a universe where things

just

work

it allows us to do the freedom to engage

with other people how we wish because

there's no centralized controlling body

influencing every action that we make

all the rules are the same and nobody's

getting special treatment

this brings out this new world of

economic opportunity as well and as our

lives become more and more digital we're

constantly being bombarded with

centralized services that want us to use

their interface so they can profit on

how we interact and force us or push us

to making the decisions that they're

motivated for us to make smart contracts

decentralized applications and

blockchain

allows us to be free of these repressors

and live in an environment that's truly

free and trustless

so with all that high level being said

let's do a quick summary of what we just

learned blockchains are decentralized

meaning that they are not controlled by

a single centralized entity it is run by

a network of independent users

transparency blockchains are transparent

everything that happens on a blockchain

everybody else can see and everybody

else can work with and see that

everyone's playing by the same rules

blockchains are quick and efficient

especially when it comes to monetary

policy settlement on blockchains are

fast and easy immutability and security

blockchains can't be changed or tampered

with or corrupted and are incredibly

incredibly secure smart contracts remove

the massive conflict of interest

traditional agreements have smart

contracts allow us to move away from

political brand-based agreements to

secure

math-based agreements smart contracts

allow us to engage in trustless and

trust minimized agreements

smart contracts are a set of

instructions which when placed on a

blockchain are self-executing pieces of

code not run by any centralized

intermediary in addition smart contracts

are typically paired with some type of

oracle to get some information about the

real world when smart contracts are

paired with an oracle they're called

hybrid smart contracts chain link is a

secure decentralized modular oracle

network used to bring data into your

smart contracts and also make some type

of external computation i also briefly

want to mention dao's or decentralized

autonomous organizations you'll hear

this referred to a lot as well

decentralized autonomous organizations

are organizations that live online and

live in these smart contracts they're

similar to a regular organization in the

traditional world however they have

people who maybe hold governance tokens

to make voting decisions or they do all

their governance on chain

on this decentralized settlement layer

giving us the freedom to engage with

each other as we please

so now that we've taken our first dive

into blockchains and smart contracts and

at least from a high level understood

why they're so advantageous let's jump

in let's get an ethereum wallet and

let's make our first transaction on a

live blockchain are you ready now let's

jump into ethereum we're going to make

our first interaction with the ethereum

blockchain and once we do this

interaction once we make this

transaction

then we're going to go back and look at

what actually happened what were the

technical implications that allowed this

transaction to go through so in order

for us to interact with the blockchain

the first thing that we're going to need

is an ethereum wallet

so i'm going to go ahead and go to

metamask 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 at any

time what we have in our wallet

this will store all of our ethereum

based currencies

so i'm going to go ahead and install

metamask 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 going

to go ahead and get started

and we're going to create a brand new

wallet so we're going to 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

phrase 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 a password now

when i'm doing my testing when i'm doing

my coding i actually use a separate

account from the account that i actually

have real money in however if you want

to use this account and actually put

real ethereum and put real money into it

you absolutely 100

need to back this up so we're gonna go

ahead and click reveal secret words i'm

showing you guys here because

uh 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 funds

so everything that we're gonna do in

this tutorial we're gonna use fake money

we're gonna use not real money so it

doesn't matter however if you're going

to actually put money in here you

absolutely need to have this written

down because if you lose access to this

and or 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 somewhere

i'm just going to go ahead and hit

download this for now and i'm going to

save it on my computer 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

but again because we're just demoing

here

i'm going to show you it here and we're

not going to put any real funds into

this

so we're going to go ahead and hit next

and we're it's going to ask us to

make sure we 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 it 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 gonna use

test money so it's not as big of a deal

but if you put real money in you

absolutely need to back up this seed

phrase or secret phrase or we're going

to refer to it as our mnemonic phrase

awesome now we can see the user

interface of this wallet

and depending on your browser if you

actually go ahead and look in your

extensions you can pin it to your

browser and you can even just click it

and get the same interface here let's

take some inventory of what is actually

going on in here and what we actually

have our mnemonic phrase that secret

phrase that we got

has given us access to a new account and

here's the address of our account we can

use a tool like etherscan to view

different addresses and what's been

going on with them so if we look at this

address that we just created on

etherscan we can see that no

transactions have happened it's empty it

has zero ether in it it has zero dollars

worth of value in it and this address

here

is our unique address this address

represents

exclusively this single account that we

just created we'll talk a little bit

more about etherscan in a bit as it's a

tool that we're going to use more and

more now we can even click this

circle here and we can even create more

accounts and give it a different account

name

we'll call it account 2.

this one has a different address so if

we go ahead go back to etherscan and

look this up this one has a different

address here

so we can have multiple addresses in

here and now if i click this i have two

accounts account one

and account two

the mnemonic that we've been given

gives us access to create multiple

accounts with that same mnemonic so

having that mnemonic will give us access

to every single account that's ever

created with that mnemonic this is why

securing your mnemonic is so crucial

especially if you create multiple

different accounts

now each account

has a unique identifier with them as

well so so this right here is the public

address when we copy this this is the

public address of that account

however there's also a private key to

work with this account a secret key

and we can go ahead and view it by

clicking these three dots go to account

details and export private key

put our password in and confirm

so this is going to be our private key

so this is a single

password associated with this account if

you give somebody else access to this

private key they will have access to my

account too they won't have access to my

account one because the private key of

account two is only associated with

account two the mnemonic however is

associated with all accounts and this is

why when people say store your private

keys in a safe place or store your keys

in a safe face they're usually referring

to both your mnemonic and your private

keys

if you lose your private key you lose

access to this account if you lose your

mnemonic you lose access to all your

accounts so long story short back up

your mnemonic since it has access to

everything and back up your private keys

too but just keep in mind they only have

access to the individual accounts and

great those are some of the main

security pieces here

now what else is going on in metamask is

we can see this section here that says

ethereum mainnet if we click it we

actually see a bunch of other networks

in here

so when you buy eth and when you work

with eth you're working on the ethereum

mainnet when you interact with smart

contracts or d5 or any things that we're

going to talk about later on mainnet

with real value you're going to be

working on the mainnet

however since we're engineers oftentimes

we're going to want to test our

applications or do some type of

integration tests or just make sure our

code actually works

so there's also what's called test nets

these are networks that resemble

ethereum and work exactly the same way

as ethereum does

however they're not with real money and

it's just for testing your applications

so we can even go to ether scan and look

up

brinkp ether scan

we can see the rink be test on explorer

we look up at our address and it's the

exact same

information here

nothing has gone on on rink b and this

is totally different so when we make a

transaction these are all different

networks and it says test network it's

made to be made without real money later

on we're actually going to show you how

to work with other evm compatible chains

don't worry about what evm compatible

means for now but we can work with

avalanche polygon and other applications

through this networks interface as well

so remember a testnet blockchain is a

blockchain where the currency doesn't

have any real value but it resembles and

acts exactly like the ethereum mainnet

so we can test our applications

so we can test and practice our

applications

in fact what we're going to do right now

is make our first transaction on the

rink b test net and this will simulate

exactly what it's like to make a

transaction on the ethereum mainnet so

we're going to go to this application

called the rink b faucet this is where

we're going to make our first

transaction ring b is going to be one of

two test nets that we're actually going

to work with the other test net that

we're going to work with is going to be

coven it's important to know how to

switch between test nets and evm

compatible chains which is why we're

going to be working with both for now

we're just going to be working with rink

b

a faucet is a tested application that

gives us free test ethereum hence why it

has no value because anybody can get it

for free from one of these faucets so to

get tested ethereum with this

application we actually have to post a

tweet or a facebook post

with this tweet so i'm actually going to

i'm going to sign in real quick

and now that i'm signed in i can post

this tweet requesting faucet funds into

and this is where i'm going to put my

address

on the rinkby ethereum test network i'm

going to go ahead and tweet that out

now that i have this

we're gonna copy link to tweet

and we're gonna place it in here and

we're gonna hit give me ether and we're

gonna say 18.75 ether for three days and

it said funding request accepted for

patrick alpha c

into this

and what we can do then

is if we take this address again

we go over to rink b ether scan

we now see that the balance is 18.75

and we can even see that

in our wallet on the ringbeat network we

have 18.75 eth but again if we look at

mainnet we have nothing there if we look

at robson we have nothing there if we

look at rink b we have 18.75 right so

these are very different networks and

we've just made our first transaction

we've been given

18.75 eth and if we refresh this page we

also see that this is our first

transaction that was made

some account sent us 18.75 ether

from

this account to us and we can actually

even look at the details of this

transaction

etherscan is what's known as a block

explorer block explorers are

applications that allow us to see

details of things that happen on a

blockchain easily we can see the

transaction details of this transaction

here and whenever we work with smart

contracts we will also see them in a

transaction similar to what we're seeing

right here and again we'll talk about

that soon now we can see a number of

information here we see a unique

transaction hash this hash or this

unique identifier uniquely identifies

this transaction

as the key of what this transaction is

we see that it was a successful

transaction this is the block number

which we'll talk about in a little bit

we see it was from this unique account

which looks like they did a ton of

transactions because this is the faucet

account

to our account that we created

value was 18.75 ether

and then we have these transaction fees

gas price gas limit and gas used now gas

refers to the fee paid to node operators

for successfully including a transaction

in a blockchain

now exactly how this works is actually

going to change pretty soon but the

concept is basically anytime you want to

change the state of blockchain whether

this is sending some ethereum or making

any type of transaction

you actually have to pay a little bit of

ethereum or a little bit of that native

blockchain token to actually execute

that transaction whenever we do

something on the blockchain

it costs gas and if we do something that

would take a lot of energy for the

blockchain to do it will cost more gas

so if i send a single transaction that's

going to cost 21 000 gas however if i

were to do if i were to send a

transaction that called the smart

contract function and did a whole bunch

of other stuff it would cost more gas so

we see here when we got sent

18.75 eth whoever sent us that eth also

paid the blockchain miners or the

blockchain validators a little bit of

ethereum to include our transaction now

we actually get to pick how much of a

fee we want to send with our

transactions so let's look at another

example so

in our accounts in metamask let's even

expand the view here

we have two different accounts we have

account one and account two account one

has 18.75 account two has zero

we can actually send money from account

one to account two and again remember

this is all fake money so so we're gonna

go ahead and hit transfer between my

accounts so we're gonna send money to

account two

and here's where we can see some

transaction details and we see the asset

that we're going to send which we only

have ethereum in this wallet so we're

only going to send ethereum later on

we'll learn how to get different assets

into this wallet we're going to choose

an amount i'm just going to choose to

send one and then we have these pieces

here

associated with the transaction fee so

we have a gas price in guay and a gas

limit so when we send a transaction we

can choose a gas limit we can say hey if

this transaction is going to spend more

gas than

21 000 gas we're not going to do it

we also get to set a gas price in guay

but here's the quick example of guay

versus ethereum

[Music]

one ether is

this many gray

and one gray is this much ether because

if we just said hey could you send me

.00001

that would be

kind of really obnoxious so we just just

say send me one way or send me one way

so i know we've been throwing this gas

term around for a little bit but here is

it basically simplified gas is going to

be the measurement of how much

computation something uses the gas price

is going to be how much it costs per

unit of gas a gas limit is going to be

the maximum amount of gas that can be

used in transaction so for example if we

make a transaction that uses 21 000 gas

and each one gas is one way

in price that means we're going to pay

21 000 way

in transaction fee

so back in our transaction we have we're

saying the gas price

is going to be one way so the

transaction fee is going to be the gas

that we use which will be up to this gas

amount

times the gas price so it'll be 21 000

way will be the transaction fee so then

the question is well why would we ever

bump it up why would we want to pay more

gas price why do i even have the option

to pay more well and this comes down to

block space we'll talk about this a

little bit more when we get into how the

blockchain actually works but the

blockchain can only

process so many transactions at a time

and nodes and blockchain nodes can only

process so many at a time so when i make

a transaction a node has to decide why

they want to include my transaction into

the block and if there are a ton of

people

looking to make these transactions then

the nodes are going to be highly

incentivized to pick the transactions

that are going to give them a high price

that are going to give them a lot of

money for including that transaction

so this is what's called eath gas

station and it is a a gas estimator of

the blockchain it currently says that if

you want to get your

transaction in right away it's going to

cost you 31 way to do so if you want to

get it in less than five minutes it's

going to take you maybe about 21 gway

so the gas prices of ethereum fluctuate

with how much people use it and the gas

prices of all these blockchains

fluctuate with how much people use it

so this is an important concept so

typically when you're setting your gas

price in a transaction you can take a

look-see at you know gas station and say

okay if i want mine to go in right away

i'm going to do asap if i want to go in

fast maybe i'll do you know this fast

amount standard i'll do this standard

amount but it all depends on how many

people are looking to work with this

blockchain at the same time and and as

you can see it fluctuates pretty quickly

right it just went all the way up to 46

so maybe more people are using the

blockchain now this is obviously for the

eth main net and on the test net there's

not going to be that same competition

but we can still change it anyway so if

i go ahead and do 100 for the gas price

and i hit next and i hit confirm if i go

to activity

i now have

this transaction

in my

metamask but i can go ahead and view

this on etherscan as well

and we can see this is what it looks

like when it's still processing this

transaction and now we can see that it's

passed and now if we look at the gas

price we see it's a hundred gray and

this is what we set it as when we were

working with it before so gas prices 100

way here versus our first original

transaction was just one way

now if we look at our metamask we can

see that

the funds have indeed been

subtracted from this account and they

have been added to this account now

there's one eighth in this account

awesome and you can see the activity

there's one ethan here so again the

reason that these gas prices exist is

because nodes can only put so many

transactions into a block so they're

highly incentivized to input the

transactions that are going to give them

a higher fee so in times when a lot of

people are looking to use a blockchain

prices will get very high and when very

few people are using a blockchain prices

will be very low this ether scan tool is

incredibly incredibly powerful and we'll

be using it more and more as time goes

on now here's something that's

incredibly exciting with just this

little bit of information you now know

how to interact with blockchains and

interact with the ethereum protocol so

if you don't want to learn how to code

anything you can go and you can start

interacting with ethereum and interact

with protocols with just this much

information however i know most of you

guys are here to learn how to code so

let's look under the hood of ethereum

and what is actually going on with these

transactions

and with these gas and with these

blockchains and what's really going on

let's learn all the fundamentals of a

blockchain now if you want to just go

ahead and jump into the coding go ahead

and grab a 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

walkthrough blockchain 101 it is right

on their site so if you're looking for

another explanation definitely check out

his video it is absolutely fantastic but

the first thing that we really need to

do in order to understand blockchain in

order to find really anything and

everything that's going on here we first

really need to understand this shot 256

hash or hashing just kind of in general

let's first understand what a hash is a

hash is a unique fixed length string

meant to identify any piece of data they

are created by putting some piece of

data into a hash function

in this example

the hashing algorithm used is sha256 now

ethereum actually uses this this right

here for its hashing algorithm which

isn't quite um sha256 but is in kind of

this shaw family but it's it's really

just another way to hash things and uh

the specific hash algorithm doesn't

matter uh so much so uh this example

uses sha-256 but you can imagine it's

the same as the ethereum hash they're

just gonna you know result in a

different hash

so what's going to happen in this

application here is whatever

data or whatever information we put into

this data section here as you can see

below this hash

changes

so what's happening is this data is

running through 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 you know patrick

collins

this is the hash that's going to

represent patrick collins right and you

can see

even when i put you know tons and tons

of data in here the length of the string

doesn't change

right

so it's always going to be the same

amount we can put

almost any amount of data in here there

is an upper limit on the max size of the

data but for all intents and purposes we

can pretty much put any length in here

and you'll see too that you know every

time i type in patrick collins

this hash is always going to be this

7e5b right i'm going to delete i'm going

to do

patrick collins again

you know seven e5b it's 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 right of putting this

data in here and we can move on to

uh this concept of a block so with this

block concept we're going to take the

exact same thing with this hash this

this data section right but instead of

having everything just being this this

singular data area right here we're

going to split this data up into block

nuns and data so all so what we're going

to do is we're actually going to hash

all three of these to get to get this

hash right we're going to put all three

of these we're going to say all three of

these are combined uh together we're

going to put every all three of them

into this hashing algorithm uh to figure

it out so if i type a bunch of stuff

here

we can see that block one

with nuns you know this nonce and this

data we're gonna get this hash and as

you can see actually

the screen turns red this block turned

red now

what happens when i hit this mine button

when i hit this mine button it's

actually going to take some time it's

going to think for a little bit and we

can see that the nuns here actually

changed right the nuns is different from

what it was before and

this hash now starts with four zeros

okay and then it the the back turned

green when we're talking about mining

we're talking about miners solving some

type of very difficult problem that

takes a lot of time to do now in this

example here the problem that the miners

had to solve was they had to find a nuns

or or a value in this nun 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 three no four or five six okay five

well that started with one zero but it's

not four and they have to keep trying

all these numbers until they uh get to

this one where you know let's hit mine

again

where it has four zeros at the top at

the start

now

this specific problem changes blockchain

to blockchain right ethereum has a

different problem for miners to solve um

bitcoin has different problems for minor

itself but this concept is going to be

the same

so they have to take

one block is going to be this

uh this concept is going to be all this

data it's going to be the block number

and it's going to be this nunce right

and so this nunce is the solution um is

is going to be the the number that they

use to get like the solution to the

problem right so if i go to one

here you know when i do this again

i'm gonna hit mine

and the nuns has changed right it went

from one to

thirty three thousand one hundred and

twenty eight because this is the nuns

that allowed this hash to start with

four zeros and so that's what's

happening

when uh blockchain miners are mining

they're going through this process this

very computationally intensive process

of trying to find a nuns 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 block chain is going to look

like right we have a combination you

know we have back here in the block

section we have one what one block looks

like now here we have multiple different

blocks right each one of these

represents a different block but we have

an additional column here or we have

additional uh variable here so like

before you know we have block nuns and

data

right we have block nun's data but we

also have this thing called previous

right and so this is actually pointing

to the previous hash of the last block

so for example if we go to the the last

block in this blockchain it says

previous is 008 and if we look at the

hash of block number four it's zero zero

zero zero eight e eight and then we look

at its previous it's uh four zeros b9 we

have four zeros b9 and so on all the way

back to our first block which has

previous of just all zeros right and so

the block with the previous of all zeros

is going to be known as the genesis

block so you've probably heard that

before the genesis block it's the first

block in the blockchain where the

previous hash points to a hash that

doesn't actually exist now as you can

imagine kind of the same as how this

block worked how the block nuns and data

all go through the hashing algorithm in

the blockchain the block nuns data and

previous hash all go through this

hashing algorithm to figure out you know

what the hash is okay so if we go to

over here you know for example if i type

in you know patrick

obviously this is now no longer valid

right because this nuns uh combined with

the block the data and the previous hash

aren't gonna solve you know our problem

of having four zeros at the start right

so i'm going to go and fix that and and

that's that's kind of an easy way to 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

trick in here you can see that both of

these

are now red both of these are now

invalid right because the block hashed

with the nuns hash with the new data

which is my name patrick has worked

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 it's pointing to this

previous block and now it is wrong and

it is messed up and now um and now it's

nuns with this previous hash is also

wrong

right and this is where when we talk

about uh blockchains being immutable

this is exactly how it's immutable right

because if i go back and i change

anything you know if i've just

typed a right here the entire blockchain

is now invalidated because none of these

are going to have

nunses that solve this equation anymore

so this is why blockchains are immutable

is because anytime you change one thing

you ruin the rest of the blockchain okay

so however though you know if if an a

was here originally we can go ahead and

mine these

we can mine all these but as you can see

you know this is going to start getting

very

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 harder it

becomes to you know rehash and redo all

these different blockchains here now

this makes a lot of sense right so we

have this blockchain it's really hard to

change something in the past but if we

do we can just go ahead and 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 in the past well okay

great all i got to do is change this

data here and then you know mine each

one of these and you know obviously it's

going to be very computationally

expensive but it's something that i can

do right if i'm the one who owns the

blockchain

now here's where the decentralized

nature or the distributed nature really

uh makes it incredibly powerful so we're

gonna go to the distributed tab here

which i also refer to as the

decentralized tab here

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 distributed blockchain we have you

know our first block chain which is kind

of exactly as the one from here but we

also have

more than one so we have peer a peer b

and peer c and when people are talking

about peer to peer appear to be your

transactions they're really talking uh

this is kind of that concept that

they're talking about right so we have a

number of different peers who are

running this blockchain technology

they're all weighted equally right each

one of these peers or each one of these

nodes each one of these entities running

a blockchain

has the exact same power as anybody else

right so the way that we can tell very

easily which blockchain is correct or

which ones are correct are by looking at

this end

hash here right 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 in which

so this last hash is encompasses

everything in here right and we can look

we can look at the hash of pure c which

is four zeros and then e4b we can look

at the latest hash of peer b which is

four zeros e4b

and then pure a which is for zeros e4b

so all of these peers all of these nodes

all of these decentralized you know

these independent

all these independent users running this

blockchain software they're all matched

up it's very easy for their nodes to

look at each other and say hey great we

are all matched up

now

what let's say that a decides that you

know something happened on the

blockchain that they didn't like and

they wanted to go back and change

something right so let's say they change

here you know obviously

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 go ahead and humor it

let's say that they they did they ended

up catching up

uh they ended up catching up you know

they ended up mining everything

and now they have a valid blockchain

right it solves the equation awesome

however

in block number three

there's something new

right this is here and it shouldn't have

been here this is something that pier a

put in by themselves

all that happens now

is we look at all the blockchains that

are running the software and we're

looking at all the hashes at hash at

block number five so pier a has this new

hash now 009 bc

but peer b has a different hash 0 e4b

right so who's right is it is it pier a

with their new stuff or is it peer b

well that's where the decentralizator

comes in because then we can look at

pier c and pierce c

also has e4b so

pure b and pure c both say hey pure a

you're wrong

get out right and peer a will stop being

able to participate in the mining

rewards because they have essentially

forked uh the blockchain and started

their own little blockchain right with

their own history because they're the

only ones with this this piece of data

in block three whereas peer b

and peer c have nothing in there so that

really shows why uh in these blockchain

worlds in this decentralized world there

really is no central identity you know

pier a you know might have been

maliciously motivated to change you know

this block number three however

democracy rules right the majority rules

in the blockchain peer b and pc both say

hey you know that's cute and all pure a

but

you're wrong right that that's not right

now it might be a little abstract that

you just look at data and you know us

typing kind of random stuff in here and

think okay yeah that's that's data right

that makes sense you know just kind of

random strings in here doesn't really do

anything for us so if we actually go

over to the token section here this is

where everything really starts to make a

lot of sense so we have the exact same

setup here with peer a peer b peer c

except 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 we're sending 25 dollars from

darcy to bingle or to bingley uh force

uh four dollars and 27 cents here uh

1922 right and it's the exact same thing

so this all these transactions are going

to get hashed in the exact same way uh

that the data is going to get hashed and

and this is why it's so powerful because

again you know if i want to be malicious

right if uh if i want to say hey i

really wanted to give jane

a lot more money from elizabeth so i'm

pure a 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 far

so long ago but i'm not going to match

any of these other chains right and so

my blockchain is going to be excluded

from 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

uh miss audrey to have less money maybe

i want to send a dollar and i go ahead

and mind it the same thing here

this hash now this 2a1 is not going to

match

peer b's

pre-b's hash of bba and it's not going

to match pc's hash of bba as well so the

two of them are going to say hey this

your blockchain isn't valid 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 uh to kind of

cryptographically prove

um you know where where stuff lies now

the way the blockchain works is that

instead of random stuff put in this data

section it's actually going to be

solidity code in here to finding ways to

interact with different blocks and

different protocols that are on chain or

as we've said before different smart

contracts

now the next question that you might be

asking is okay well

how do i know how can i be sure that i'm

the one

uh you know let's say this is let's say

i'm darcy right how can i be sure that i

was that darcy was the one to actually

send this money here how do we know that

darcy sent 25

to

bingley well this is where we get into

uh private keys and public keys and

that's what we're going to go into now

let's just do a quick recap of what

we've learned in this section so far

right we've learned that

ethereum actually runs on this ketchup

256 but you know we used shot to v6 for

this demo it doesn't really matter we're

just talking about hashing algorithms so

again a hash is a unique fixed length

string meant to identify any piece of

datum a hash algorithm or a hash

function is a function or algorithm that

computes any type of data into a unique

hash

mining is the process of finding the

solution to the blockchain problem in

our example the problem was to find a

hash that starts with four zeros

whenever a node mines a block they get

paid a little bit of that gas we were

talking about earlier for doing

something a block in 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 essentially what's

going on blockchains are decentralized

and distributed because

many independent users are going to run

this blockchain software and they will

check and they will compare against each

other to see which blockchains are

acting honestly and which ones are

acting maliciously in the blockchain

world majority rules the nuns here is

the answer used or the number used to

get this hash now nuns is kind of an

overloaded term it's actually used for a

number of different reasons in this case

we're using it to solve this problem of

getting you know four or five zeroes at

the stop of the hash however in ethereum

it'll also be often used as the number

of transactions from a given address so

now we're going to talk a little bit

about signing these transactions and

private keys and some other cryptography

pieces right because in this blockchain

demo here we can see we hover these

these fantastic transactions right all

these things went through but how do we

know that it was darcy who was the one

to send 25

to bingley right how do we know that

actually happened and this is where

all those pieces that we just learned

about uh in our our test net in our

metamask account are really going to

start to to come to life here a little

bit here so here we have an example of

public and private keys okay at the top

we have this private key right that was

that was randomly generated a private

key is is you know as it kind of states

is a key that you really want to keep

secret because you're going to be using

this

as kind of your secret password for all

your transactions right i can really

pick you know any

any any private key anything that i want

and with it uh

this algorithm they're going to use an

algorithm you know for ethereum in

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 going to go too deep into it but

we have this private key that we create

and we get this public key now this

public key we want everybody to have

access to right this is yeah whole world

can see this this private key we really

want it to be uh private we don't want

people to see this we're going to use

this private key as like a password to

quote unquote digitally signed

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 going to happen

is this private key that we've created

we can use to sign this data right

remember how in the blockchain demo you

know we were kind of we were hashing

stuff right we were we're using this uh

shay256 hash to to get this hash well

we're doing something similar but

instead of hashing we're we're using

this digital signature algorithm to

create this message signature

now what's really powerful about how

this uh this algorithm works is that you

can create this message signature with

your private key but somebody else can't

derive your private key from the message

signature and that's what makes this

really really powerful however if we go

to verify using this public key right

and so this is the

this is that o four zero three 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 the 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 send

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

hide your keys you know protect your

keys this is what we're talking about

in our accounts here

right if we go to

uh settings and again the only reason

that i'm showing you guys

my mnemonic in my private key is because

this is a

uh this is a dumpster account i'm gonna

throw this away at the end of this video

or i'm just not gonna put any real money

in it

um

but

when we look at our our metamask here we

have this mnemonic phrase which allows

us to

easily get these different private keys

right so

demonic phrase combined uh with you know

whatever account number will get us a

private key so demonic phrase combined

with one we're going to get this private

key and this is when we look at account

details export private key

password confirm this is going to be the

private key that we're going to use to

sign our 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 it works the exact same way right so

this is why it's so important to hide

your private keys and hide your

mnemonics now

your ethereum address is actually

a piece

is actually a piece of your public key

now to get our address in ethereum all

we have to do is take this public key

that we've created with our private key

hash it using that same ethereum hashing

algorithm and then take the last 20

bytes and that's how we'll actually

derive to our um to our address here now

knowing the exact methodology of how to

get the address doesn't really matter

because it could change blockchain to

blockchain and could even change an too

but just know that that is essentially

how kind of these addresses are derived

right there's some derivative of the

public key right because the public key

is public and you know using the public

key in kind of any public way is 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 sign it

create a transaction for us to send

we'll learn later on how to send these

transactions

so that was a lot of information there

too let's do a quick recap your public

key is derived by using a digital

signature algorithm on your private key

right and you want to keep your private

key private at all times because you're

going to use your private key to sign

transactions

signing transactions with your private

key you are the only one who can

actually do this because you can't get

the private key from a message signature

however using your public key you can

anybody can very easily verify that a

signature that's signed by you is in

fact signed by you in our metamask our

private keys are located in this account

details section you just hit

show private keys and type in your

password and you'll get your private key

here

a quick note here is often times when

using your private key 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

in 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 about it 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 awesome so now that we know

all the cryptography pieces and all the

little nitty gritties of how the

blockchain actually works and how our

signatures work and how everything

sticks together let's talk a little bit

about how this works in actuality and

what's really going on now for a lot of

this each different blockchain has

slightly different algorithms and

slightly different metrics and criteria

for doing a lot of the stuff so when

we're talking about these specific

implementations keep in mind the exact

algorithm might be a little bit

different but the concepts are all still

going to be exactly the same hashing and

hash function is going to be the same no

matter where you look a decentralized

blockchain is going to be the same no

matter where you look how it's actually

implemented is going to be a little bit

different now traditionally when you run

an application you know be it a website

or something that connects to some

server you are interacting with a

centralized entity and unlike how we saw

with the blockchain with multiple

different peers it's going to be run by

a single centralized group now it still

could be run on many different servers

but all those servers are still going to

be controlled by the same centralized

group blockchains as we saw run on a

network of different independent nodes

when we saw peer a peer b peer c those

were different examples of different

independent users running the blockchain

technology on their own node now when i

use the term node i'm usually referring

to a single instance of a decentralized

system so when i say a single node when

i'm talking about a blockchain i'm

talking about one of those peer a's peer

b's pcs running that blockchain software

i'm talking about one server running

this technology and again it's this

network it's this combination of these

nodes interacting with each other that

creates this entire blockchain what

makes this so potent too is that anybody

can join the network and that's why

there's decentralized the barrier to

entry is a little bit of hardware

requirements you're getting the correct

materials to run the software and then

you running the software anybody can

join these networks and participate and

that's what makes it truly decentralized

in fact you can go to github right now

and run your own ethereum node in a few

seconds now in the traditional world

applications are run by centralized

entities and if that entity goes down or

is maliciously bribed or decides that

they want to shut off they just can't

because they're the ones that control

everything blockchains by contrast don't

have this problem if one node or one

entity that runs several nodes goes down

since there are so many other

independent nodes running that it

doesn't matter the blockchain and the

system will persist so long as there is

at least one node always running and

luckily for us most of the most popular

chains like bitcoin and ethereum have

thousands and thousands of nodes and as

we showed in our demo if one node acts

maliciously all the other nodes will

ignore that node and kick that out or

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 interaction 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 ethereum

it has an extra additional feature where

it also can do computation in a

decentralized manner now let's talk

consensus proof of work and proof of

stake because you've probably heard

these before and they're really

important to how these blockchains

actually work we went through that

blockchain example and we did that

mining feature this is what's known as

proof of work proof of work and proof of

stake fall under this umbrella of

consensus and consensus is a really

important topic when it comes to

blockchains consensus is defined as the

mechanism used to reach an agreement on

the state or a single value on the

blockchain especially in a decentralized

system i briefly alluded to this

consensus mechanism in our blockchain

example when i said if one changes

something and the other two

don't then majority will rule and kick

that one out this is part of that

consensus mechanism now very roughly a

consensus protocol in a blockchain or

decentralized system can be broken down

into two pieces a chain selection

algorithm and a civil resistance

mechanism that mining piece that we were

doing or or the proof of work algorithm

is what's known as a civil resistance

mechanism and this is what ethereum and

bitcoin currently use please note that

depending on when you're watching this

if eth2 is out then it's no longer proof

of work now proof of work is known as a

civil resistance mechanism because it

defines a way to figure out who is the

block author which node is going to be

the node who did the work to find that

mine and be the author of that block so

all the other nodes can verify that it's

accurate civil resistance is a

blockchain's ability to defend against

users creating a large number of

pseudo-anonymous identities to gain a

disproportionately advantageous

influence over said system

and in layman's terms it's basically a

way for a blockchain to defend against

somebody making a bunch of fake

blockchains so that they can get more

and more rewards now there are two types

of the 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 silver 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 blockchain's riddle of

finding that correct nonsore or whatever

the blockchain system has in place in

proof of work this works because

no matter how many pseudo-anonymous

accounts you make each one still has to

undergo this very computationally

expensive activity of finding the answer

to the proof-of-work problem or the

proof-of-work riddle which again in our

demonstration it was finding a nunce

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 block tone to be if

the system wants the block time to be

very very long they just make the

problem very very hard if they want to

be very short to 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 figure out who the

block author is and be civil resistant

now you need to combine this with a

chain selection rule create this

consensus now there are 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

ethereum 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 decides that whichever

blockchain has the longest chain or the

most number of blocks on it is going to

be the chain that they use this makes a

lot of sense because every additional

block that a chain is behind it's going

to take more and more computation for it

to come up

that's why when we saw in our

transaction we actually saw

confirmations the number of

confirmations is the number of

additional blocks added on after our

transaction went through in a block so

if we see confirmations is two it means

that the block that our transaction was

in has two blocks ahead of it in the

longest chain now i do want to point out

that a lot of people use proof of work

as a consensus protocol and i do want to

say that this is a little bit inaccurate

but sometimes people use it

interchangeably proof of work is a piece

of the overall consensus protocol which

in bitcoin and ethereum one's current

case is nakamoto consensus nakamoto

consensus is a combination of proof of

work and its longest chain rule both

equally and very very important now

proof of work also tells us where these

transaction fees and these block rewards

go to remember how when we made this

transaction we had to talk about gas and

a transaction fee so who's getting paid

who is getting this transaction and this

transaction fee is going to the miners

or the validators in a proof of work

network they're called miners and in the

proof of stake network they're called

validators 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 rule is going to get

that transaction fee they're going to

get paid from that now when a node gets

paid they actually get paid in two

different ways one is going to be with a

transaction fee and another piece is

going to be the block reward remember

how we talked about alternating the gas

price or the way on our transaction well

that's the transaction fee that we're

going to pay to these blockchain nodes

for including our transaction the block

reward is given to these nodes from the

protocol from the blockchain itself

you've probably heard of the bitcoin

having before the having is referring to

this block reward getting cut in half

and it's supposed to be cut in half

roughly every four years this block

reward increases the circulating amount

of whatever cryptocurrency that is being

rewarded for example on ethereum the

block reward is giving out ethereum and

on bitcoin the block reward is giving

out bitcoin so these nodes are competing

against each other to be the first one

to find this transaction to be the first

one to find the answer to this problem

so that they can be the ones to win both

this block reward and your transaction

fee some blockchains like bitcoin for

example have a set time when they are no

longer going to give out block rewards

and the miners or the nodes are only

going to get paid from transaction fees

now this gas fee again is paid by

whoever initialized the transaction when

we got our funds from the faucet there

was some server and somebody else was

paying the transaction fee for us

however when we sent ether from one

account to another our first account

actually paid some transaction fee to

send that ether in proof of stake

there's also a gas fee but it's paid out

to validators instead of miners and

we'll talk about that in a little bit

now let's talk about two types of

attacks that can happen in these

blockchain worlds let's talk about the

first one being the sybil attack the

simple attack is when a user creates a

whole bunch of pseudo-anonymous accounts

to try to influence a network now

obviously on bitcoin and ethereum this

is really really difficult because the

user needs to do all this work in proof

of work or have a ton of collateral in

proof of stake which again we'll talk

about in a bit the other more prevalent

attack is what's known as a 51 percent

attack now as we saw as part of our

consensus protocol these blockchains are

going to agree that the longest chain is

the one that they're going to go with so

long as it matches up with 51 percent of

the rest of the network

this means that if you have the longest

chain and you have more than 51 percent

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 decentrality of the

network by pretending to be multiple

different people although they're just

the same person or entity and like i

said it's really difficult to do in

proof of work and proof of stake so you

can see now that blockchains are very

democratic whichever blockchain has the

most buy-in and is the longest is the

blockchain that the whole system is

going to corroborate when nodes produce

a new block and add to the longest chain

the other nodes will follow this longest

chain that the rest of the network is

agreeing with add those blocks to their

chain and follow up so very small

reorganizations are actually pretty

common when a blockchain picks a block

from a different longest chain puts it

on and then has to

swap it out for another block and

continue with a different blockchain

however if a group of nodes had enough

nodes or enough power they could

essentially be 51 of the network and

influence the network in whatever

direction that they wanted this is

what's known as a 51 attack and it's

happened on blockchains like ethereum

classic which is not ethereum this is

why the bigger a blockchain is the more

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

note as well because you are going to

increase the security of the network as

a whole by running a node so proof of

work is fantastic because it allows us

to very easily protect against these

civil attacks and keep our blockchains

decentralized and secure

however it has some drawbacks as 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 to be a

lot more environmentally friendly and

the most popular one right now is proof

of stake there are some chains that are

already using this proof-of-stake

protocol and that are live and thriving

some of them are like avalanche solana

polygon polkadot and terra and

additionally ethereum has decided to

upgrade to eth2 which will have this of

stake algorithm as well it'll also have

some other features which we'll talk

about in a bit now as a quick aside all

the tools that we're going to learn here

are still going to work in eth2 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 ethereum 2 nodes put

up some ethereum 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 removed some

of their stake

obviously this is a very good civil

resistance mechanism because if you try

to create a whole bunch of anonymous

accounts

then each one of those accounts you have

to put up some stake and if you

misbehave you're going to run the risk

of losing all the money that you put up

as collateral in this system miners are

actually called validators because

they're no longer binding anything

they're actually just validating other

nodes now unlike proof of work which

every node is racing to be the first one

to find the block in proof of stake

nodes are actually randomly chosen to

propose the new block and then the rest

of the validators will validate if that

node has proposed the block honestly as

we saw with our cryptography lesson it's

usually very easy for other nodes to

verify if a proposal or a transaction is

honest now randomness is a really

important topic when we're talking about

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 determinic

system by definition can't have random

numbers so how do we choose the random

validators in the system well it changes

from blockchain to blockchain and

actually choosing the node will change

blocks you to blockchain but in eth2

they're using what's called randow at

least for the original implementation

this is a decentralized 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 in

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 costs to participate

now this gets into a little bit of a

philosophical battle on how

decentralized is decentralized enough

and i think that's up to the community

to decide and as we progress i think

we'll learn more and more about how

decentralized is decentralized enough

the general consensus amongst blockchain

engineers though is that proof of stake

is very very decentralized and very

secure this massive environmental impact

improvement is one of the two main

reasons why eath is shifting to eth2 it

reduces the environmental impact by up

to 99 percent 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 block

space and the nodes can only add so many

nodes 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 more 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

ethereum 2 is not only attacking the

environmental impact of proof of work by

switching to proof of stake but they are

also implementing this new methodology

called sharding and sharding is a

solution to this scalability problem a

sharded blockchain really just means

that it's going to be a blockchain of

blockchains there is 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 1.

now there's another term that might be

the first time you heard it a layer 1.

we're going to talk about layer ones and

layer twos in terms of scalability

really quickly as well a layer one

refers to any base layer blockchain

implementation bitcoin's a layer one

ethereum's a layer one avalanche is a

layer one these are the base layer block

chain solutions a layer two is any

application that is added on top of a

layer one added on top of a block chain

some examples of layer twos are going to

be chain link arbitrarily or optimism

arbitrary and optimism are very

interesting because they are layer twos

that also look to solve this scalability

issue arbitrary and optimism are what's

known as roll-ups and they

roll up their transactions into a layer

one like ethereum we're not going to go

too deep into rollups and how they

actually work but all you really need to

know is that a rollup is kind of like a

sharded chain they derive their security

from the base layer from the layer one

like ethereum 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 ethereum 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 arbitrary optimism for example

is going to be just about as secure as

ethereum there's some fantastic guys in

there that go a little bit deeper into

rollups 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 ethereum

and bitcoin are currently both

proof-of-work blockchains that follow

nakamoto consensus however ethereum is

moving to ethereum two which will be a

proof-of-stake sharded blockchain civil

attacks are prevented due to protocols

like proof of work and proof of stake 51

attacks grow increasingly harder with

the size of blockchain so you should run

a node consensus is the mechanism that

allows a blockchain to agree upon what

the state of the blockchain is sharding

and rollups are solutions to scalability

issues on layer ones

a layer one is any base blockchain

implementation like bitcoin or ethereum

a blockchain scalability problem is that

there's not always enough block space

for the amount of transactions that want

to get in them this leads to very high

gas prices and again gas prices are how

much it costs to interact with a

blockchain

so we've learned a ton in this video so

far

everything that you went over is going

to make you 10 times better as a

developer because yes being a good

developer means you understand the code

at a very technical level

but if you can understand the overall

architecture as well you can make the

informed decisions about how to

architect your design or how to build

your software in however you want to do

so so with all that being said it's

finally time to jump into some solidity

and jump into some code so let's do this

now again

in the description of this video there

is a link to this github repository

that's going to be the home base for all

the code that we work with in this

tutorial we scroll down to this main

section this readme there's a table of

contents in here

we can go to lesson one simple storage

and we'll have links helpful tips the

itinerary of what we're going to learn

and everything else that you need to

work with here all the code that we're

going to be working with is located in

this simple storage link that we can go

ahead and click it's in its own

different repository we can go ahead and

click the file to see all the code that

we're going to be working with so let's

jump into it additionally back in our

full blockchain solidity course right at

the top

there's this resources for this course

section if you have questions engaging

in github discussions stack exchange

ethereum and stack overflow are going to

be great places to get help and get

support i highly recommend making a

stack overflow

stack exchange ethereum

and a github account so you can

participate and engage with the

community

welcome to the remix ide or the remix

integrated development environment this

is going to be where we're starting to

teach you how to work with solidity and

work with smart contracts and deploy to

blockchains we're going to use remix to

get us up to speed as it has a lot of

nice features that allow us to really

see and interact with blockchains and

really see what's going on but

eventually we're actually going to move

off of remix to another platform

but all the solidity that we're going to

learn here obviously is going to apply

everywhere as well when you come to

remix there's a whole lot of different

plugins like solidity learn eth soul

hint linter and a whole bunch of other

plugins as well i'm going to go ahead

and start by clicking the solidity

plugin but we're not going to use any of

these plugins for now but later on you

can kind of go back and learn a little

bit more about what these plugins do so

let's start perusing let's start coding

some things on the left hand side over

here is where we're going to interact

with everything so let's go ahead and

click the files up here now you can

always go back and peruse this a little

bit more and in fact i highly encourage

you to because that's how you're going

to learn the most the quickest but for

us we're actually just going to go ahead

and start with our own brand new file

we're going to create a little

application that can store information

on the blockchain for us and this is our

first project that we're going to do in

solidity so we're actually going to

create a new file

and we're going to call it

simple

storage dot soul all solidity has an

extension of dot soul at the end stands

for solidity now let's take inventory of

what we're going to be working with here

this is the solidity compiler tab

it compiles all the solidity code down

to machine understandable code or

machine language here there's a whole

bunch of different parameters we can

choose when working with sliding we

choose the compiler version we can

choose the language which we're only

going to be working with solidity the

evm version don't worry about this for

now so let's code our first solidity

contract here

now we are going to use something a

little bit special here when we actually

deploy these we're going to use a

javascript virtual machine

so we're going to use a virtual machine

that's going to simulate actually

deploying to a test net or a real

network we're not actually going to

deploy on a real network we will

in a little bit but just to get started

we're going to work with a javascript vm

which is kind of a fake environment for

now okay

testing locally and understanding how to

test locally will make your

coding experience a lot faster as you

saw when we sent some transactions some

of them actually took some a lot of time

to actually deploy we don't want to have

to spend that much time waiting around

for our tests to actually finish so

we're going to use a javascript vm to

kind of dummy it for now but let's just

start coding and go from there

so the first thing that you're going to

need in any solidity program is the

solidity version so that's always going

to be at the top of your solidity code

it's defined by doing pragma solidity

and the version

we're going to be using some version

between

0.6.0

and 0.9.0

so we're saying we want to use anything

between 0.6

and 0.9 and and as a force of habit i

just automatically hit command s

whenever i write anything so that's why

you saw some of this pop up here we can

hitting command s or control s depending

on if your windows or not we'll hit this

compile button and we'll compile

everything for us

now if we want a specific version of

solidity we can also do 0.6.0

and if i go ahead and hit command s or

compile

our compiler will automatically convert

to 0.6.0

however if i try to do 0.8.0 with my

solidity at 0.6.0 it's going to give us

an error it's going to say the source

file requires a different compiler

version

we're using 0.8.0 and this is 0.6.0 so

we're going to go ahead and hit compile

and it's going to automatically move

down to 0.6.0

we can also

do carrot 0.6.0

and this will allow us to work with

really any version of 0.6

it'll work all the way up to 0.7 where

if we hit command s or control s there

it'll give us an error so this only

works with any version below 0.7 and

above 0.6 we're going to be using

version

0.6.6 however in future contracts that

we work with we're actually going to

work with different versions of solidity

the reason we're going to be changing

versions throughout this course is that

solidity is a constantly updating

language being good at switching between

versions is going to make you an

incredibly powerful smart contract

engineer the next thing that we're going

to do is we're going to define our

contract

so contract is a keyword in solidity

which stands for our smart contract that

we're going to create you can think of a

contract similar to a class in java or

any other object-oriented programming

language so we're going to give our

contract a name here we're going to call

it simple storage

and we're going to add this little curly

bracket to say this

is the contents of our contract simple

storage

and i went ahead and hit command s and

we can see it is compiling successfully

you could hypothetically deploy this

right now and this would be a valid

contract so great job for making it this

far now in solidity there are many

different types that we can work with

let's go into some of the types of

solidity we can have integers aka whole

numbers they can be uint as in an

unsigned integer meaning they're not

positive or negative we can also have an

int

and we would define a variable by doing

you in 256 favorite number

equals 5.

so we have

an unsigned integer you went 256 means

this is an integer of size 256 bits

so we can have this be upped this number

be up to 256. you can also do uint

favorite number equals 5 but if you want

to be a little bit more precise a lot of

protocols and a lot of smart contracts

will do the whole name like you and 256.

we can also have

booleans booleans are true false so we

can have boolean

favorite bool

equals

true so this favorite bool would be true

it could also be

false

we can have strings

string

favorite

string

equals

string

a string is a string of text here right

it's going to be some word or phrase or

really any of these keystrokes here

similar to the unsigned integer we can

have an int

256

favorite

int

equals negative 5

so it could be positive or negative we

can have an address

which is going to be some type of

ethereum address

so we could do address

favorite address

equals

and then we can even copy right from our

metamask

and just paste it right in here

this is going to be a valid address here

you'll also notice that we end all of

our statements with a semicolon

we can have a bytes object

size 32 bits

favorite bytes

for our example

we're just going to use the word cat

because cat is a string which can be

converted down into a bytes object by 32

means that there's 32 bytes in this

variable favored bytes we can also do

bytes 2 bytes 3 bytes 5 etc with the

maximum size of bytes 32

for example we can't do bytes 64. we're

going to be talking about some other

variables as well like arrays and

mappings but let's just stick here for

now if you want to learn more about the

different types and the different

variables that you can use head over to

the solidity documentation and there's a

link in the github and the description

to show you this section for now for our

simple storage let's say we only want to

store numbers we don't want to store

anything else

so we're just going to go ahead and

delete everything and just have uint256

favorite number

at the top now in solidity if i do this

favorite number actually does get

initialized even though i didn't have it

initialized to 5. if i leave it blank it

gets initialized to the null value in

this case it would be initialized to 0.

so for now let's just not initialize it

to anything that way it'll get

automatically initialized to zero this

means that when we deploy this contract

as of right now favorite number will

start off as zero if you get confused

you can also make a comment on this you

could say

this will get initialized to zero

this double slash here is the way to

make comments in solidity and it won't

get executed as code so we can write

whatever we want as long as it's

preceded by two backslashes

now let's go ahead and create our first

function

functions or methods are self-contained

modules that will execute some task for

us and in solidity it's the exact same

thing they're defined

by the keyword function

let's make a function called store

that will change the value of this

favorite number here

so we're going to call store and we're

going to allow it to be past a variable

so we're going to allow it to be passed

a variable of type unsigned integer 256

and we're going to call it underscore

fave

or it

number we're going to 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

equals to whatever variable we passed in

favorite number so this in its simplest

form is how you can define a function

now just to visualize what we're working

on so far let's go ahead and deploy this

contract so we can actually start to

interact with it so if we hit this

button this will bring us to the deploy

tab and will allow us to deploy our

smart contract here

using our javascript vm it's given us a

fake account with some ethereum in it it

has 100 ethereum in it to start and same

as before anytime we want to interact

with the blockchain we have to pay a

little bit of gas even in our fake

virtual machine here and we want to

simulate that so you'll see it has some

of the same parameters here as making a

transaction like gas limit for example

when we deploy a contract it's going to

cost a little bit of ethereum or a

little bit of gas to do so

so let's go ahead and hit this deploy

button and see what happens so once we

deployed with this virtual machine a few

things happened

we have

remix kicking out this section down here

saying great job you've deployed

something and if we scroll down it says

transactionsrecorded1 we can look at all

the transactions we've recorded

and we can see it says deployed

contracts and we have a contract here

that we've deployed now let's zoom out

just a hair here so we can see

everything a little bit better in this

simple storage contract we see this big

store button because there's one public

function that we can actually interact

with so we can add

this number here and we'll hit store and

you'll see again we have a completed

transaction

and if we look at our contract

we'll have paid a little bit more gas

right we'll have paid a little bit more

to interact with this function because

again anytime we want to make a state

change in the blockchain we have to pay

a little bit of gas the reason metamask

isn't popping up is because we're kind

of doing it in this simulated

environment so this is great however it

looks like we can't actually see

what our favorite number is we can't

actually look at it so how do we

actually make sure that we can view this

favorite number well let's add another

parameter to this as well

if we add public

to our favorite

number we recompile by hitting command s

or hit the compile button

we delete this contract and we redeploy

and scroll down

now we'll see two buttons pop up

this blue button to show us favorite

number which again is initialized to

zero

and we have the store function

so let's talk a little bit about why

this public variable allowed us to see

this new button this new favorite number

button this public keyword defines the

visibility of the variable or the

function there are currently four

different types of what's called

visibility in solidity there's external

public

internal and private we're mostly going

to be working with public for now but

it's important to know how the rest of

these work public functions can be

called by anybody including variables

so oddly enough variables are a function

call to just look at them and return

whatever that variable is an external

function means it can't be called

by the same contract it has to be called

by an external contract so if in this

contract

i had this be external

i couldn't call

the store function

i couldn't call the store function

inside this function

because the function is external it

means somebody outside of the contract

has to call this function internal

functions however can only be called by

other functions inside of this contract

or in its derived contract

and then private is the most restrictive

as private functions and state variables

are only visible for the contract they

are defined in and not derived contracts

now the reason that we didn't see

favorite numbers show up in our original

contract deployment is that if we don't

give a state variable a visibility it

will automatically get set to internal

so if we want other people to be able to

read it we have to change it to public

now let's see how this interaction

actually works

if we hit the favorite number button

right now we'll get this call thing that

shows up and it'll show us right here

that

the value of

favorite number is zero

now this function however is set so that

whatever value we pass it is going to

change the favorite number to whatever

we pass it as so if we pass one two

three hit store

that transaction goes through

and then hit favorite number we can see

the value is now one two three

now i will also be using transactions

and smart contract interactions and

function calls a little bit

interchangeably that's because on a

blockchain whenever you call a function

or whenever you make some state change

to the blockchain you're actually also

making a transaction that's what makes

this whole thing so powerful and again

that's why making a function call or

deploying a contract costs a little bit

of gas now the reason we can access this

favorite number variable inside this

function

is because favorite number has this

global or contract scope so even if we

made union 256 tests equals 4 or

equals equals 4 we wouldn't be able to

use this variable outside of this

function

right because it's self-contained it's

self-contained inside this bracket

and

if i were to make another function

store two perhaps

public

2 doesn't know that this test variable

exists

functions only know about the variables

that are in the same scope as them so

favorite number is in this global scope

because the only bracket that's above

them is simple storage and test is in

this store scope because it has two

brackets above it it has it's inside of

the store function and inside of this

contract simple storage

store two isn't inside of this store

function or this store scope so it can't

access this test variable

so let's go ahead and make this back to

public

and we'll compile again i'm hitting

command s to compile but you can go

ahead and click the button if you like

and let's get rid of this now as you saw

when we deploy this

there's this button here that we can

click called favorite number we can also

make a function called

retrieve and make it a public function

that is of type view

and returns

uint256

and all this is going to do

is return

favorite number so we're going to talk

about views and returns here

so i'm going to go ahead and compile

i'm going to go ahead and delete delete

this contract i'm gonna go ahead and

deploy it now

and we can see

now we have

two functions or two blue buttons here

we have retrieve and we have favorite

number

if i change favorite number by calling

the store function favorite number and

retrieve will both now say it's one two

three

so then the question might be well why

is this one orange and these two are

blue

and the key relies in this view function

or this view keyword there's two special

keywords that define functions that you

actually don't have to make a

transaction on

and those keywords are view

and pure

a view function

means that we want to read some state

off the blockchain so we're just reading

off the blockchain if we're reading off

the blockchain and we're not actually

making a state change then we don't need

to make a transaction

these blue buttons are blue because they

are view functions public variables also

have view functions that's why both of

these are blue

this technically is a view function and

when i click it i get to view and i get

to read the state off the blockchain

retrieve is the same way we could have

this without a return but it wouldn't do

anything pure functions are functions

that purely do some type of math we'd

have you in 256 favorite number public

pure and just have favorite number plus

favorite number

so we're doing some type of math here

but we're not actually saving state

anywhere

we're going to do this math but we're

not going to save this favorite number

anywhere we're not going to save

anything deploy this now this pure

function

we would have this retrieve function one

two three it's blue as well because it's

again not going to change the state of

the blockchain so view functions and

pure functions are both can have this

blue color

now the reason that nothing shows up at

the bottom is because we didn't return

anything

all we're doing is we're saying add

these two numbers together and that's it

in order for this function to give us

something back we need to have it return

something so if we go back

to this retrieve

to this retrieve function we have to

define what we're going to return when

we're defining this function so we're

going to say this is a public function

it's a view function because we're going

to read some state and it's going to

return a unit 256.

so favorite number is of u 256 so that's

what we're going to return

our public variable favorite name is

also a view function that returns a

un256

for now let's just remove that so we can

work with this retrieve function

so let's go ahead and deploy

so now we see we don't have this

favorite number button anymore because

it is no longer a public function

because again it gets initialized to

internal so we can't actually view it

now keep in mind later on we're going to

talk about how everything on chain you

actually can see

and we'll talk about that a little bit

later though so retrieve is going to do

0

we can call store

and now retrieve is going to be 1 2 3.

now this application is great so far it

allows a single person to store a

favorite number and then go ahead and

retrieve it

later which is fantastic but what if we

want a list of people or a group of

people

and store their favorite numbers or what

if we want to associate a favorite

number with a single person well what

can we actually do now we have a whole

number of different choices but the one

that we're going to talk about is using

a struct structs are ways to define new

types and solidity they're almost like

creating new objects as well

so we can create a struct

called type people

and allow it to start storing a favorite

number associated with a certain people

so inside of our struct we can have

different types as well

so we have a uin256

favorite number

and we could also have a string

name

now we have a new type of type people

that has a favorite number and a name

inside of it now what we could do

with destruct is we could say

people

public

person

equals

equals people

and then inside we add the variables so

we could say

favorite number

favorite number is

2

and name

is

patrick

and of course the semicolon at the end

and again i'm hitting command s to save

but you can also go ahead and compile

in the compile tab

so let's go ahead and delete this

contract and see what this looks like

now

so now we've deployed this new contract

and we have this person struct which at

the zero index

is the favorite number and the variable

stored in the first index is going to be

the name storing variables and solidity

always works in this numeric index

fashion in fact in contract simple

storage uint 256 favorite number is at

index 0. if we were to add another

object here like

boolean favorite bool

this would be at index one

if we were to add bool

favorite

bool2 this would be at index

two zero

one

two

and it works the same in structs this is

at index zero inside the struct this is

at index one inside the struct

so we can see the variables associated

with this person we're gonna go ahead

and delete this for now because

instead of just creating one person we

actually want to create a whole list of

people so how do we create a list of

people let's delete that contract

and what we can do is we can make what's

called an array an array is a way of

storing a list or a group of some object

so as you're starting to see the way the

syntax works for defining any type of

variable is going to be the type of the

variable

the visibility of the variable like

public or if you don't declare it it

gets initialized to internal

and then the name of the variable

it works the same with arrays so we'll

make a people array the people array

is the type

we'll make it public

and we'll call it people

now if we deploy this contract

we go and see we now have a people array

but if we click this button

you'll see that

nothing shows up

the reason is because it's an empty

array to start with right we don't have

anything inside of it

now this type of array that we've

created is what's known as a dynamic

array it's a dynamic array because it

can change its size right now it's a

size 0 and if we added something to it

it's of size one you can also create

arrays of a fixed size so if i were to

do people one public people this array

could only have a maximum of one person

inside of it

so we're going to work with a dynamic

array though because we want to add an

arbitrary number of people into here so

let's go ahead and create a new function

called add person where we can add a

person to this array

so we'll do function

add person

string

memory name i'll talk about this memory

keyword in a minute

uin256

favorite

number

and then we'll make this a

public function

and inside we'll do we'll add this

person to our array the way to add a

person to your arrays is using the push

method

so we're going to push

a new people or a new person

and we're going to give it

those variables again

so we're going to give it so we're going

to give it favorite number

is this variable that we passed in here

oops this needs a bracket

and then we're going to give

the name

going to be this underscore name

and then end bracket

oops

zoom out again here just so i can see

stuff

this needs a semicolon

and perfect

now in that last clip we saw this little

red box pop up whenever a little red box

like this pops up after you compile it

means you have a compile error this

means that there's something wrong with

your solidity code or your salinity

syntax and it won't compile and deploy

properly red is going to be this compile

error now we're going to see a bunch of

yellow warnings in the future if you get

a little yellow pop-up these are okay to

ignore but they usually have some

helpful tips about something that might

be going wrong in your code so to

summarize if it's red if it's red it's

broken if it's yellow you might want to

check it out but it could be okay so we

can see we have our new function add

person

where we pass a string memory name and a

unit 256 favorite number and then we

create

this people person

this people object here and then we push

it

onto our people array

and i'm going to show you another way we

can actually create a people person

is just by passing

favorite number and name

and getting rid of this other bracket by

passing favorite number and name

because we know

that

the zeroth index of people is favorite

number and the first index of people is

name so we can also create a new person

by adding it like this now let's talk

about this memory keyword here now in

solidity there's more or less two ways

to store information you can store it in

memory

or in storage

when you store an object in memory it

actually means that it'll only be stored

during execution of the function or of

the contract call

if we hold it in storage

that means that that data will persist

even after the function executes a

string in solidity is actually

technically not a value type a string is

actually an array of bytes a variable of

type string is actually a special type

of array that we can append text to so

because it's technically an object we

have to decide where we want to store in

memory or in storage and since we only

need this name during the execution we

can have it be string memory name and

then when we create this new people

object we will create a new copy of this

name variable into storage memory means

that after execution delete this

variable and storage means keep it

forever if this is a little bit

confusing for you just know that for now

when you use a parameter that's going to

be a string for one of your functions

you need to call it string memory so

let's go ahead and deploy this contract

and see what happens now

now we have this new function add person

and since we are making a state change

here we can see that this indeed

is a orange button instead of being a

blue button so we can add in here a

string name we'll add

patrick and we'll say his favorite

number is 2.

again right now if we look at people

we see people 0 there's nothing in here

if we retrieve there's nothing in here

so we're going to add person patrick and

now if we hit people of 0 we can see

that the person at the zerowith index in

this people array

is going to be

string patrick

if we try at one there's nothing in here

let's add another person

we'll add

becca and her favorite number will be

24.

let's add her now if we hit one we see

favorite number 24 string name is becca

and retrieve is so showing up blank

because we haven't touched favorite

number awesome this is great we can just

keep adding people

however there is kind of an issue here

what if i'm looking for a person what if

i'm looking to find

becca and find her favorite number in

this array

what if i know her name but i don't know

her favorite number is there an easy way

for me to find that favorite number

without having to triage the entire

array there's another data structure

called a mapping so let's create this

new data structure

so this data structure is going to be of

type

mapping a mapping takes some type of key

and spits out whatever variable it's

mapped to so in this case if we're

saying we want to use the name becca to

find her favorite number we would say

the string becca

is going to be mapped

to the uint 256 favorite number and

similar to

all the other variable declarations the

first part is going to be the typing so

this is going to be a type mapping of

string

mapped to un256

we're going to give this public

visibility and we'll call it

name

to favorite number and without adding

any other functions that work with it if

we deploy this we can see we have this

blue button because we're not making a

state change name to favorite number and

if we type in becca in here

obviously nothing's going to happen

because we haven't added this

mapping in yet

so in our ad person down here let's even

have this ad person also add to the

mapping so we can do name

to favorite number

and then the key is going to be this

name so of becca we're going to say

we're going to map the name becca

to

the favorite number

now we're going to go ahead and compile

again i'm hitting command s

deploy

we can scroll down here

if we look up backhand here

we're going to get nothing

however

if we add

becca

and her favorite number being 24

this add person is going to add it both

to the array

and to this mapping now if we look up

name to favorite number we see that

becca returns 24. now one other thing i

want to show you guys just because

compilers are going to yell you if you

don't have them is typically at the top

of these contracts you want to add an

spx license identifier basically

solidity and the ethereum community

found out that

trust in a smart contract can be better

established if source code is available

and

in terms of legality and copyright it

just makes life a lot easier if you add

that license identifier right at the top

of your solidity we're going to use the

mit license identifier because it's the

most open license out there it means hey

anybody can use this code and we don't

care so you'll see a majority of

salinity contracts have this spx license

identifier mit at the top and compilers

will yell you a lot less awesome we now

have a contract that we've decided that

we liked it's got mappings it enables us

to actually store people and their

favorite numbers this is fantastic we've

done all of our testing in this

javascript vm and we've decided you know

what we want to deploy this to an actual

test net or an actual mainnet how do we

actually deploy this so that other

people can interact with this contract

we are again going to use rink b because

that's what we use to make our first

transaction

now again you will need some type of

test ethereum in your test and wallet so

again if you get lost

you can always just google rink b

faucet

or ring b test net faucet

and find a faucet or a better

alternative would be to come to the link

token contracts in the chain link

documentation at

docs.chain.link and

scroll down or just look up rink b this

linked token contracts page has the most

up-to-date faucets for any test net that

it supports so for example we get a test

and eth faucet right here which also

just happens to be that exact faucet

that we used earlier the only thing you

need to change

in remix is we need to change from

javascript vm to injected web3

and metamask will actually pop up and

say hey would you like to connect to

this application

anytime you're working with a web3

application or a web application that

wants to access your funds or work with

your metamask metamask will pop up and

ask for authorization first this is

really good so that we know which

applications we're actually connected to

so we're going to go ahead and say next

connect and we can see here

that we've even connected here and that

our account on the main network

has zero eth

and remix even tells us hey you're on

the main network so let's go ahead and

switch

to the rink b network

and we can now see

we're on the rink b network and we have

17.74 eth on this ring b test network

injected web 3 means we're taking our

meta mask and injecting it into the

source code of the browser here and

that's the difference between injected

web 3 and javascript vm web web3

provider is if we want to use our own

blockchain node or our own web3 provider

when we do injected web3 we're saying

our web3 provider is our metamask which

will work perfectly for what we're

trying to do so since we already have

some tests on ethereum let's go ahead

and deploy this and see what this would

actually look like if we deployed to a

mainnet the process is going to be

exactly the same right the only

difference was we would be on the main

net instead of rank b so let's go ahead

hit deploy we'll uncheck publish

published ipfs

hit deploy metamask will pop up asking

if we want to do this transaction

because remember

we are deploying a contract we are

changing the state of the blockchain so

we have to pay a little bit of gas fee

for it so we're going to go ahead and

hit confirm

and we get

a link to ring the ether scan similar

exactly as we saw before when we made a

transaction the difference here

is that instead of sending ethereum to

somebody we're actually making a

transaction on the blockchain to create

a contract after a short while it will

show up here on etherscan with a success

the number of block confirmations which

again is the number of blocks appended

to the block that included our

transaction

we see from which is our account here

and we see two is this new contract that

we just created and we can even click it

and we see

that

there's this unique transaction hash

that created a new smart contract and

same as working with the vm we have all

the exact same functions in here and you

can see if i hit retrieve

these three functions since they're not

making a state change you can just click

them and no transactions will be made

however what do you think is going to

happen if i hit store

if you guessed metamask will pop up you

guess correctly

again we see the familiar pieces here we

have a gas price gas limit

go ahead and hit confirm

we get another transaction here and once

this transaction goes through

we should be able to call our retrieve

function and see a new number

if we call it now

nothing shows up because our original

transaction hasn't succeeded but i bet

if we look at it now

okay it's still indexing but it looks

like it's been included if we hit it now

we do indeed see this value here

and we can do the same thing with adding

a person we'll add becca we'll say her

favorite number is 24.

metamask will pop up we'll go ahead and

confirm the transaction and if i look up

becca and the name to favorite string

right now it's going to show nothing

because our transaction hasn't gone

through yet

but if we wait a little bit i should

probably spell her name right we do see

24.

and if we look at the zeroth index we

also see becca's been added here as well

now all the solidity code that we wrote

and when we interacted with this

blockchain here

all this solidity was compiled down to

the evm also known as the ethereum

virtual machine

a lot of the blockchains out there today

are what's called evm compatible

and that means that all this solidity

and all these functions that we're

creating

can still compile down to evm and

deployed on their blockchain you'll find

out a little later when we look to work

on a non-ethereum based chain that we

can still deploy our solidity smart

contracts to these other chains as well

but that's a term you'll hear more and

more the ethereum virtual machine or ebm

now take a break give yourself a high

five because you just deployed your

first smart contract and you learned the

basics the fundamentals of solidity so

huge congratulations on how far you've

gotten now in our second projects we're

going to take the fundamentals a step

further and start going into the more of

the intricacies of solidity but just as

a quick recap the first thing you always

got to do in your smart contracts is

name the solidity version

then you'll have to name your contract a

contract in solidity is like a class and

defines all the functions and parameters

of your contract

there's many different types in solidity

like unsigned integer 256 boolean and

bytes

we can create structs in solidity we can

create arrays in solidity we can create

mappings in solidity we can create

functions in solidity

view functions don't make a state change

memory and storage are two different

ways to initialize where a variable is

going to be saved

all the solidity code that we're working

with gets compiled down to the ethereum

virtual machine and last but not least

congratulations on taking your first

step in learning solidity let's move on

to the next project

all the code tips and links that we're

going to be working with can be found in

our course repository

we can scroll down to lesson two

storage factory

click it here and we can see all the

code we're going to be working with good

luck all right so we've done it we've

got our first contract out of the way

we're understanding some of the basics

of solidity now let's move onward let's

get a little bit more advanced with what

we're going to do

with our smart contracts and let's build

what's called the factory pattern of

smart contracts so we have our simple

storage contract here which is great it

allows us to store

numbers and store favorite numbers

associated with different people and

this is great what if though i want to

have a lot of these simple storage

contracts deployed i want to give people

the ability to generate and deploy their

own lists based off of this contract

this is where the factory pattern comes

into play so let's go ahead and create a

new contract so in this contracts folder

i'm going to do new file

we're going to call this

storage

factory

dot sol

and now we'll have a storage factory.sol

now the way that we're going to do this

is that you need simple storage and

storage factory in the same folder

i have both of them in this contracts

folder but if you have them outside or

in a different folder that's okay just

make sure wherever they are they're in

the exact same folder so let's figure

out how to get a contract to actually

deploy another contract we're going to

add those basic pieces that we added in

that simple storage.sol we'll add the

spdx

license

identifier

which will be mit

we'll choose our solidity version which

will be pragma

solidity

and we'll say anything in the six range

and then we'll create our contract we'll

say contract

storage

factory

and we'll create our brackets here and

i'm going to do command s or compile

whatever you want to do things are

looking good here great so how can this

contract

deploy a simple storage contract well

the first thing that we're going to need

to do is actually import this simple

storage into our storage factory

contract

we need to import it so that

our storage factory contract knows

what a simple storage contract even

looks like

the way that we can import it is by

doing the command import and then the

file path that the simple storage is

located so the file path for this is

going to be at dot slash

simple

storage dot soul

this means that simple storage is in the

exact same directory as storage factory

doing this line is equivalent to copying

everything in this contract bit

coming over to storage factory and

pasting it above

you can even save and compile and have

two contracts in the same file now

what's interesting about having two

contracts in the same file is that when

you go to deploy

you'll actually have a choice of which

one you want to deploy and it's the same

thing if i do that import statement so

if i delete all this

and i go back to import dot slash

simple storage dot sol in our deploy tab

still

you'll see that we still have our choice

of which contract we actually want to

deploy

so this is how we actually import a

contract or import any type of file that

we want so that our contract knows what

that contract looks like and can do so

if we want this contract to then be able

to deploy a simple storage contract

we're of course going to have to create

a function that can do that

so we'll do function

we'll call it create

simple

storage contract

we'll make this a public function

we'll do our little open and close

bracket in here the way we can generate

a contract of simple storage type is by

using a new keyword so let's create a

simple storage variable

we'll say a variable of type

simple storage contract we'll name this

variable

simple storage

with a lowercase s

equals

new

simple

storage

what this line is saying is we're saying

we're going to create an object

of type simple storage contract

we're going to name it simple storage

with a lowercase s

and we're going to say this is going to

be a new simple storage contract and

we're saying this simple storage

contract takes no input parameters of

course if we deploy this contract as is

by going to our deploy tab

choosing the storage factory

staying on a javascript vm

deploying

scrolling down

we have this function that doesn't

return anything

so we're creating new contracts but we

can't really read where those contracts

are being created we'd have to look on a

block explorer like etherscan or

something

so let's make a way for us to keep track

of all the different simple storage

contracts that we deploy

let's put them in a list or in an array

so what we can do

is we can say

simple storage

array

of visibility public and we'll call it

simple storage

array

we'll initialize this symbol storage

array

and every time we deploy we create one

of these new simple storage contracts

we'll add it to our simple storage array

so we'll do simple storage array dot

push

and we'll push

this simple storage variable

so again i'm compiling or hitting

command s

delete that most recent contract

we'll choose the storage factory and not

the simple storage

and we'll hit deploy

now if we scroll down to our storage

factory

we have this blue button which stands

for our simple storage array

if we try to see what's at index 0 we

get an error of course because we

haven't added anything to it yet

if i click this create simple storage

contract

orange button here

now i've created a transaction that's

going to create a new simple storage

contract and push it onto our simple

storage array

now if i try to access the zerowith

index or the first index of this array

i'm going to get this address here

this is the address that this simple

storage contract was deployed to so

we've successfully deployed

a contract

to the blockchain from another contract

and this of course is really exciting

now we can actually do more than just

deploy the contracts we can actually

deploy contracts from another contract

and then call those functions as well

so let's create a new function where we

call

this store

function and we'll also create a

function where we call the retrieve

function from our storage factory so

we'll do function

storage factory store

we're going to shorthand it by saying sf

store we'll have it take unit 256

simple

storage

index

and a uint256

underscore simple

storage

number

we'll make this a public variable as

well in our little brackets here

and the reason i'm choosing a simple

storage index is because we're going to

choose which simple storage contract in

our list that we want to interact with

and then we're also going to pass a

simple storage number

to call

on the store function which of course we

need to pass a favorite number to any

time that you interact with a contract

you need two things

you need the address of the contract you

want to interact with and you also need

the abi for us we figured out that

we're going to push and get this address

from this simple storage array

we can get the abi or the application

binary interface from this import

we'll explain the application binary

interface a little bit more later

for now just know that in order for us

to interact with this simple storage

contract we can just do

simple storage

and then

we'll pass this simple storage the

address of that simple storage

contract

to get the address of that simple

storage contract

we'll say

grab the address

inside the simple storage array

at index simple storage index this will

return that contract that we want to

interact with

so we could even say

simple storage

simple

storage

equals simple storage

at that address in the array

once we get this contract we can then

call

any and all of its functions

so we could call

simple storage

dot store

this simple storage number

now if we compile this

we go to our deploy tab deploy the

factory

hit deploy

open this up we can see we have a couple

different functions here we of course

have our create simple storage function

which creates the contract and adds it

to our array

we now have this sf store

which stores

a number

to one of those contracts on this array

and then we have

a lens

into that simple storage contract

so if i create a simple storage contract

i can now store

on that zerowith contract on that first

contract any number that i want like 55.

of course i can't really see that 55

because we didn't add a retrieve

functionality we didn't add a way to

actually listen or read or retrieve that

favor number that we got

so let's add that now so

we'll create a new function

called

sfget and this will take a uint 256

simple storage

index

and as a parameter and we'll choose one

of these contracts on this array and

return

its favorite number

calling the retrieve function on that

contract

so since we're just going to be reading

state

this can be a public

view function

that will return

a uint256

to do this

we need to access that contract once

again

so we'll say simple

storage

simple storage

equals

simple storage

at that address

of

simple

storage array

at index

underscore simple

storage index

and we can return

return

simple storage

dot

we call this retrieve function

i'm just going to copy paste it so i

don't spell it wrong

simple storage we'll put the semicolon

here too

and here

now if we compile this go to our deploy

tab delete the most recent

choose the storage factory and hit

deploy

we can see we now has have an sfget

function

so let's go ahead

create a simple storage contract we'll

store a function on the zeroth contract

we'll store 55 as its favorite number

and we'll hit that

and then for s of get we'll see if we

can get

the favorite number of the zero with

contract

and we do indeed get 55.

awesome we can actually even refactor

this code to be a little bit simpler

here

we don't need to save

this simple storage contract is a

variable here we can actually just call

retrieve

on this whole section here

paste retrieve at the end

and just

return

like this

the same goes for our sf store

we can delete saving it as a variable

we can copy this dot store

paste it at the end here

and delete this as well

now we'll compile

delete the most recent

we'll deploy the storage factory

and if we go into it create a simple

storage

store the number 55

see what's at the zeroth index and we do

indeed see 55.

so

this is really cool this is a way for us

to actually deploy contracts and

interact with contracts from another

contract now to deploy a contract we do

need all the functionality of that

contract

imported however to interact with the

contract we don't need all of the

functionality we'll learn about

interfaces in the next lesson which will

allow us to actually interact with the

contract without having all the

functions defined and now i'm going to

show you something really cool now i'm

going to show you something really cool

simple storage has got a lot of really

cool functions and maybe i want all

these functions inside my storage

factory i want my storage factory to be

able to create simple storage contracts

and i want it to be a simple storage

contract itself

well what i can do

is my storage factory can actually

inherit

all the functions of simple storage

without me having to copy paste all

these functions and all these variables

over to storage factory what i can do

is i can do solidity's version of

inheritance

i can say contract storage factory

is of type

simple storage or is of contract simple

storage

and just by doing this line right here

my storage factory contract now will

have all of the functions and variables

of simple storage so it'll have

a store function a retrieve function an

add person function

a people array a name to favorite number

mapping it'll have everything because i

will inherit it with this is syntax

so if i go to my deploy tab now

[Music]

let's look at what our last storage

factory was

all we did to change this was add is

simple storage and we can see just the

four functions that we originally added

if i delete this now

if i save and compile the storage

factory let's go ahead and deploy

storage factory

if we open this up now

we can see

not only do we have all the functions

originally defined in our storage

factory but we additionally have all the

functions from our simple storage and

awesome you've completed the second

lesson we've learned about some

incredibly powerful tools here we've

learned how to import entire chunks of

code from other files into our files

we've learned how to do inheritance

we've learned how to deploy contracts

from our contract

and then we've learned how to interact

with different contracts from outside of

our contract well done now is a great

time to take a breath take a breather

and review what you've learned

the github repository associated with

this course also has all the code for

this lesson so let's jump into it so

we're back in remix now and we're going

to go to contracts and same as before

we're going to create a new file we're

going to call this fundme.sol

now same as last time we're actually

going to add this spdx license

identifier mit right at the top and then

we're going to choose our solidity

version

so we're going to go pragma solidity

and for this we're just going to do

greater than equals to

0.6.6

and less than 0.9.0

and great

this should look pretty familiar

now we're going to do contract fund me

and we're going to start working so what

again do we want this contract to do we

want this contract to be able to accept

some type of payment so let's create a

new function that can accept payment

we'll call it fund

so we'll do function

fund

public and we'll add a new keyword in

here called payable when we define a

function as payable we're saying hey

this function can be used to pay for

things when you call a function

every single function call has an

associated

value with it whenever you make a

transaction you can always append a

value

this value

is how much whey or gray or fini or

ether you're going to send with your

function call or your transaction

as we mentioned before

whey way and ether are just different

ways to talk about how much ether you're

going to send

so if we look at a way to ethereum

converter one each is

this much way

one way is the smallest denomination of

ether you can't break up ethereum into

anything smaller than one way this is

why when you're talking about how much

something costs everything always

defaults to whey or the smallest unit of

measure in ethereum so again for us to

test we're going to stick with the

javascript vm for now if we hit deploy

we get a new contract and this button is

now red it's red because it is a payable

function so now if i hit this fun button

[Music]

i can add

a value associated with it so what do we

want to do with this funding what do we

want to do when people send us something

well let's keep track of who sent us

some funding so what we can do is we can

create a new mapping between addresses

and value

so let's do a mapping

of address

to

uin256 which will represent the value

we'll make this a public mapping

and we'll call it

address to amount

funded

now in this fun function let's keep

track of all the people who sent us

money or all the addresses that sent us

some value

to do this we can use some keywords that

go along with every transaction so we'll

say address

to amount funded

of message.sender

equals

or

plus equals

message.value message.sender and

message.value are keywords in every

contract call and every transaction

message.sender is the sender of the

function call and message.value is how

much they sent

so whenever we call fund now somebody

can send some value because it's payable

and we're going to save everything in

this address to amount funded mapping

so if we deploy this now

in our javascript vm

we now have again a new view function

called address to amount funded and we

can even hit the drop down to see the

full name

now if i hit fund nothing's going to

happen right because my address is going

to be sending zero

in order for me to send something i have

to add some value along with my

transaction

so let's send for example one way

which is going to be equal to

1

1 2 3 4 5 6 7 8 9 this much way so

before i hit fund here if i copy this

fake account which is up here

and i put it in this address to amount

funded

it's going to return zero

but now if i add

1 1 2 3 4 5 6 7 8 9 in here

and we go ahead and hit fund now we've

now just called this fun function with a

value of one gray associated with it

so if i call

this address to amount funded now with

the same address i can now see

how much we've funded this smart

contract and we can even add more gray

we'll add

we'll add 11gway for example we'll call

fund and if we call this now we can see

that even more has been added when we

send our funds to a contract this

actually means that this contract

wherever this is deployed now is the

owner of this

amount of ether

so this is fantastic we now have a way

to fund our smart contracts now here's

the thing

in this smart contract in this funding

that we're doing we want to create a

minimum value for people to be able to

fund our endeavors which whatever they

may be we want to set some minimum value

here

and ether is great but for whatever

reason we want to work in usd or maybe

we want to work in some other token so

how are we going to get the conversion

rate from that currency to a currency

that we can use in this smart contract

well the first thing that we're going to

need to do to set this value is we're

going to need to know

what the eth

to usd

conversion rate is

because if i want to

accept ethereum as the token but i want

it in its usd currency well then i'm

going to need to know what that

conversion rate is so how are we going

to get this data into our smart contract

where are we going to get this data from

now remember how we talked about

blockchains being deterministic systems

and and oracles being the bridge between

blockchains and the real world well this

is exactly where oracle's come in when

we're talking about these systems you

know these blockchains they can't

connect to real-world events they can't

connect to external systems they can't

do external computation they're

intentionally these deterministic

systems these walled gardens so in order

for us to make this connection we need a

blockchain oracle we need some type of

network here now just to get a little

bit more technical for you if we look at

a blockchain a blockchain can easily say

one plus one

equals two and every other node can

easily verify this

however a blockchain can't easily say

okay let's all grab the same random

number because each node is going to get

a different random number they also

can't say hey let's make an api call

because if one node calls the api at a

different time another node calls it or

specifically an http get there could

potentially get very very different

results

and if another node tries to replay

these transactions by calling these apis

again

maybe 10 years in the future there's a

good chance that that api is going to be

depreciated

and they could be hacked they could be

malicious et cetera et cetera

the other reason that blockchains

intentionally can't make api calls is

because then they would be making

assumptions about the real world and

layer ones typically don't want to have

an opinion on any political or

geopolitical issue whereas an oracle

network on the other hand can make those

assumptions the other main thing we need

to talk about here is centralized

oracles being main points of failures if

you or i say hey i'm just going to be

the oracle i'm going to be the one to

put this data on chain we now have this

massive centralized point of failure

we've done all this work to make our

decentralized computation decentralized

and on chain but we ruin all the

decentrality by having a single point of

failure remember one of the whole

purposes of blockchain is so that not a

single entity can flip a switch and

restrict our freedom to interact with a

centralized oracle a single entity can

flip a switch and restrict our freedom

to interact with each other we also need

to get data from many different

decentralized sources or do any type of

computation in a decentralized manner

this is where chain link really shines

chain link is a modular decentralized

oracle infrastructure and oracle network

that allows us to get data and do

external computation in a highly civil

resistant decentralized manner it can be

as customizable as you want as you can

run with one node or many nodes or do as

many nodes as you like

now currently one of the most popular

features of chain link is their data

feeds or their price feeds we can even

go check them out

over at data

dot chain dot link

we can see a number of different price

feeds and the networks that are

providing the prices for these specific

pricing powers

we can see here by looking at the ui

there is a whole number of decentralized

different oracles returning data for

different price feeds this one for

example is fusd and it's also exactly

the price view that we're looking for

having a decentralized network bring

this data on chain and have it as a

reference point of definitive truth

allows users to all collaborate and use

this common good and it will be cheaper

more secure more efficient than anybody

even running their own centralized

oracle so these price feeds are

incredibly powerful additionally they're

being used by some of the top protocols

in the defy system right now

like synthetics which at the time of

recording is securing around 2 billion

sushi swap for leveraging trades set

protocol commodity money ave for

understanding the price of an underlying

collateral now this is an example of an

out of the box decentralized solution

that's already been packaged in the

decentralized manner for you to consume

and for you to use this makes going to

production a thousand times easier than

building everything yourself

however if you want to make api calls

and build your own decentralized network

you absolutely can with the chainlink

api calls

we're not going to go into that here

because using the chainlink price feeds

chainlink vrf keeper network and all

these other pre-box decentralized

services are going to make going live

and going mainnet a lot easier you can

always make a chain link http get call

as well we're not going to go over this

though because putting this into

production is a little bit trickier and

working with chainlink vrx if you ever

want to try them out by themselves you

can always head over to docs.chain.link

and head over to get the latest price

feed there's usually a remix button

actually that we can click and it will

kick us out to a remix edition with all

the code already ready to go for us if

we just hit this just right here this

will include all of our code which we'll

go into in a second

but let's go ahead and compile it

we're going to deploy it

to a real network here

this one looks like it's actually for

covin so we're going to go ahead and

switch to coven looks like i don't have

any covent ethereum so we're going to

grab

a covent faucet we can usually find

different faucets in the chain link

documentation

let's look up kovin here

there is a coven faucet here

it looks like in order for us to get

some covent ethereum here we have to log

in with github then we can add our

address in here and get the ethereum in

the interest of time i'm going to skip

ahead for me doing that

great it looks like i've got some covent

test that now being able to switch

between test nets is going to make you a

lot more effective as an engineer as

well because you're going to be able to

understand how each network actually

works so now we've compiled this

let's deploy this

again metamask is going to pop up

and let's go ahead and click to get the

latest price and we can see that this

function does indeed return the latest

price of ethereum

now you might be asking

why does this number look so big

well remember how we talked about whey

and gray and ether

well the reason that those exist is

because decimals don't work in solidity

so we actually have to return a value

that's multiplied by 10 to some number

so this value is actually 2614

times

10

raised to the eighth now the next

question you might ask is well why did

we work with this on a test net why

can't we do this on a local network and

the answer to this is because there is a

network of nodes looking at this test

net and delivering data onto this test

stem when you spin up a local network or

do a simulated vm there are no nodes

actually doing that we'll learn later

how to actually mock these interactions

and mock a chain link node returning

data onto our blockchain but for now

let's head back over to the contract

that we're working on so we can learn

how to implement this in any contract

that we ever want to another contract

called in this case called price feed

has a function called latest round data

which returns a lot of data it returns a

round id which defines how many times

this price feed has been updated it

returns a price which is the actual

conversion rate between the two assets

it returns a started at which defines

when this was last updated

it returns a time stamp and it returns

an answer in round don't worry about

answered in round for now if you want to

dive a little bit deeper into what these

rounds mean and what answered in round

means you can definitely check out the

chain link documentation and some of the

faqs to learn more now how do we

implement this data feed into our fundme

application well the first thing we're

actually going to need to do is we're

going to need to import the chain link

code

so we're going to do import

at chain link

contracts

source

v 0.6

interfaces

slash aggregator

v3

interface

dot soul

now let's talk about what this is

actually doing

oops looks like i spelt aggregator v3

interface wrong

all right great now it's actually

compiling

so let's talk about what imports

actually do

as we know an import will take whatever

code you're importing and stick it at

the top of your project so when we

import from at chainlink contracts we're

actually importing from the at chainlink

contracts npm package

we can look up at chain links contracts

in npm

and we can see and read more about this

repository

this links us back to the github which

will tell us a little bit more about

what's really going on if we follow that

import path that we got from the

documentation we'll end up on this file

in front of me now we have what's called

an interface you can see these contracts

don't start with the contract keyword

but they start with the interface

keyword they have the exact same pragma

solidity at the top but the main

difference is that you can see that

their functions aren't completed they

just have the function name

and its return type

now just to be a little bit more

explicit here i'm actually going to go

ahead and delete this import statement

on the top and replace it with that

interface code from github just to show

you exactly what's going on however if

you've already typed that at import

syntax feel free to leave it in there

and just remember that it's going to be

the exact same as me copy pasting the

interface code in our code here solidity

doesn't natively understand how to

interact with another contract we have

to tell solidity what functions can be

called on another contract this is where

interfaces are actually going to come in

similar to structs what we can do with

interfaces to find a new type so if we

copy all this code

from this section and place it at the

top of our code here

above where we're declaring a contract

we can actually then

interact with contracts that have these

functions

if we go ahead and even compile this we

can see this does indeed compile

correctly remember how we said before we

talked a little bit about abis well

interfaces actually compile down to

what's called the abi or the application

binary interface the application binary

interface

tells solidity what functions can be

called on another contract

we need solidity to know what functions

it can use and what functions it can

call other contracts with and if that

was a little bit confusing just know any

time you're going to interact with

another contract in solidity or smart

contract programming in general you're

going to need that contracts abi we'll

go into what these apis look like a

little bit later anyways to simplify it

interface compiles down to an api we

always need an api to interact with the

contract so how do we actually work with

this contract here to interact with an

interface contract it's going to work

the exact same way is interacting with a

struct or a variable let's define a new

function called getversion and we're

going to call this version function on

this other contract

so we'll start out doing function

get version

public

remember it needs to be a view since

we're just going to be reading this

state and even in the interface it even

defines it as a view returns

so we'll even grab

this whole bit right here

view returns unit 256. now the exact

same way we define variables and structs

we define working with other contracts

and interfaces so the first thing is we

name the type which in this case is

aggregator v3 interface

then we'd name the visibility but since

again we're inside of this contract

we're going to skip it then let's give

it a name

we'll call it

price feed since this aggregator v3

interface is going to be giving us a

price fee then we can do equals and this

is where we're going to initialize the

contract so how do we actually choose

where to interact with this contract

well we just type aggregator v3

interface and then we put in here the

address of where this contract is

located in order to find

where this fusd price feed contract is

located on the rink b chain we can look

at the ethereum price feeds chain link

documentation

it has a ton of different price feeds

and even more not price related data

let's scroll down to rink b

because again

on each different chain

the contract address that has all this

price feed information is going to be

different

let's scroll down and find fusd which is

right here

and we'll copy it

and we'll paste it into here

now what is this line saying

it's saying that we have a contract that

has

these functions defined in the interface

located at this address if that's true

then we should be able to call

price feed

dot

version

and we should be able to return it

whoops looks like we forgot to add

those here

and we need a semicolon here

i hit ctrl s or command s compiled it

looks like we're compiling successfully

and we do need to deploy this on a test

n

remember this address here is located on

an actual test tent it's located on an

actual network it's not going to be

located on our simulated chain here so

we do need to deploy this to injected

web 3. we do need to deploy our contract

to rink b because the rink b chain has

this address

we'll learn later on how we actually can

work with a simulated chain and work

with these price feeds but that's much

later in this course so let's go ahead

and save

we'll deploy

make sure we're on injected web 3.

now we can go ahead and hit deploy

metamask is going to pop up per usual

confirm

we're going to get a transaction link to

etherscan showing us our contract

and once it actually is confirmed we can

see we have our contract right here now

we have our familiar functions with one

additional function

we have our fund button which is red

because it's payable we have our address

to amount funded mapping which is blue

because it's a view

and we also have this get version button

that's also blue if we go ahead and

click it we can see that the version of

our aggregator v3 interface is version

3. this is the third version of the

aggregator interfaces hence the name

aggregator v3 interface so we just made

a contract call to another contract from

our contract using an interface this is

why interfaces are so powerful because

they're a minimalistic view into another

contract so this is great we have a get

version function but this still isn't

the function that we want we want to

call the get price function which if we

look at our interface we can see there's

a latest round data function that

returns

an answer this is the function that

we're going to want to call on this

contract so let's go ahead and make a

function that calls that instead

so we're going to do

function

get price

public

view

returns

uint 256.

uh oh

this latest round data function though

returns

five variables so how do we actually

work with that well let's find out to

work with this contract we're gonna do

the exact same thing

we're gonna do aggregator v3 interface

because this is the type of the contract

price feed

equals

aggregator v3 interface

we'll do this same address in here

because this is the fusd address

then we'll do price feed

dot

latest round data

now since this is going to return

five different values

we can actually have our contract also

return these five different values

we can copy paste like this

and literally do

this

these five values equal price feed that

latest round data

and you can see

that even compiles correctly let's

adjust the formatting a little bit here

so it looks a little bit nicer a tuple

is a list of objects of potentially

different types this is the syntax for

getting a tuple we can define several

variables inside one of these tuples

although our compiler is going to give

us some warnings it's saying unused

local variable because we're not

actually using these for anything we'll

come back to this

now we can go ahead and do return

and we can pick one of these variables

that we want to return answer is going

to be the price so we're going to do

return

answer but uh-oh we're going to run into

an error return type argument in 256 is

not implicitly convertible to expected

type answer is an int 256 and we want to

return a uint 256 so how do we rectify

this we can fix this by using what's

called typecasting if we just return

answer we're going to be returning the

wrong type however integers and solidity

are really easy to cast into each other

so we can just do uint 256

and wrap it around this answer

and then compile and save that instead

as you can see now our compiler is happy

because we've changed this answer into a

unit 256

awesome so now this get price should

return the latest price of ethereum in

terms of usd let's go ahead and deploy

this new contract with this new function

so same thing we're going to come to our

deploy section

hit the deploy button up remember we got

to go to the fundbean.sol

let's deploy it

confirm with metamask here

and let's scroll down to our newly

deployed contract

as you can see we have our get version

function which still works exactly the

same but we have a new function too

called get price and this should return

a uint 256 answer let's go ahead and

click it

amazing we've actually returned an

answer now again if you're a little

confused on why this number looks so big

you have to remember that this actually

has eight decimals we could call this

decimal's function on the contract to

learn that one two three four five six

seven eight and we know that the current

price of ethereum in terms of usd

is two thousand four hundred and

eighty-two awesome so now that we have

the price we can actually get the

conversion rate but let's clean up this

function a little bit before we go on up

there as you can see one thing that the

compiler is complaining about is we have

a lot of unused local variables

but latest round data returns

five different variables

so how do we actually return the five

variables but make our compiler happy

with us well we can actually just return

blanks for each one of these sections

with commas in between each other to say

hey there is a variable here but we're

not going to use it

this will also make our code look a lot

cleaner

because now this function's a lot

smaller

we say

something's here we're ignoring it

in 256 answer we're going to use some

things here ignore it something here

ignore it and ignore this too and we can

even test this out by compiling it

deploying it

checking on rank b

scrolling down

hitting this

and hitting get price and you can see

indeed it's the exact same as before

awesome so now we're all done cleaning

things up right not quite yet

see the other thing that's really

annoying here we have this massive chunk

of code at the top

that is probably a little redundant

there's a good chance that a lot of our

contracts are going to want to use this

aggregator v3 interface so let's just go

ahead and add that at chain link

contract syntax back in because it's

going to look a lot cleaner here and do

at chain link

contracts if you ever get a little bit

confused with what you should be

importing to work with their contracts

we can see right in the documentation at

the top this at syntax is what this is

going to use

now you can also go ahead and browse

that npm package of at chainlink

contracts see what other applications

are in there and what other files are in

there

or you can just peruse around the github

now the third way we can actually do

imports is we can import from contracts

that are in the same file system as our

contracts well awesome our contract is

starting to look more and more put

together now one other thing that i

usually like to do with these is i

usually like to put everything into the

gray

way standard so as we saw

this get price had eight decimal places

however

the smallest unit of measure aka whey

if we look at it has 18. one two three

four five six seven eight nine ten one

two three four five six seven eight

so typically in these i like to try to

make everything have 18 decimals as well

you don't have to do this and it'll save

some gas if you don't but i usually like

to multiply everything so that

everything has 18 decimal places so

since i know this has 8 i can just do 1

2 three four five six seven eight nine

ten

and now this will return

the price with eighteen decimal places

instead of ten now we have the price of

ethereum in us dollar which is fantastic

so we could set the price of our funding

function to anything that we want here

for example let's say 50

we could convert whatever value that

they send us to its us dollar equivalent

and see if it's greater than or less

than fifty dollars

all we have to do is make a new function

that converts that value that they send

to its us dollar equivalent so we could

do function

get conver

generate

and it will take a u 256

f amount let's get this out of the way

for the rest of this

it'll be a public view function since

again we're not actually going to have

it make any state change

we'll do returns you want 256

and then in this function

we can do uint 256

f price

equals

get price

and we can call

this get price function up here

now we have the price in here

what we want to do is we want to convert

whatever value that they send

as f amount let's say they send one way

or again that's going to be this much

way

what how do we convert this

to fusd

well

we can now do unit 256

s

amount

in usd

equals

this f price

times

the f amount that they sent

this is actually going to

result in a much bigger number than

we're looking for and then of course

we're going to return it

let's test this out and see why we have

to do one more thing here

so let's again

fund me we'll deploy

rank

b we'll scroll down and we have this new

function called get conversion rate

let's grab this one gray and put it in

here whoa

this seems like it's a really big number

we're saying that

one gray

is equal to one two three four five six

seven eight one two three four five six

seven eight nine ten

this many dollars

now i don't know about you but i don't

think the price of even one ethereum is

that many dollars maybe in the distant

future but definitely not right now the

reason that it's off is we have to then

actually divide by

this number the reason that we have to

do this is because both f price and f

amount

have an additional

10 raised to the 18th tacked on to them

so now we have to divide it out in order

to get the right number

so we're going to compile

compile

deploy

confirm

we can scroll down

and now let's try this one way

we'll get the conversion right here

and we can see we get a number that

makes a little bit more sense now

remember this has 18 decimals as well so

the real number is 1 2 3 4 5 6 7 8 1 2 3

4 5

6 7 8 9 10.

and we know that this number is actually

accurate because we can go ahead and

pull up a calculator

pop that into here

and we know that this is one way in us

dollar

if we get the conversion rate

we're saying that this many gray equals

one each

so we can check it back by multiplying

this number by that and we see that we

do actually get the price of one

ethereum in us dollar

so our math here checks out

awesome now since we're on the topic of

math i do want to talk briefly about

some of the pitfalls of solidity

especially when it comes to math prior

to solidity 0.8 if you added to the

maximum size a uint number could be it

would actually wrap around to the lowest

number that it would be and in fact you

can even demo this with a contract here

now you don't have to follow along with

this contract but just watch to see the

example we're going to call this

overflow

dot sol

now in here we're going to add all kind

of the normal stuff

contract

overflow

and we're going to add a function

called

overflow we'll make a public

view and we'll have it return a uint 8.

i'll show you why in just a minute a

union 256 is a really really big number

and it's hard to kind of imagine going

over the maximum cap of a u and 256

but a uint 8 is a lot smaller with the

maximum number actually being 255. so if

we create a uint 8 and we call it

big

equals 255 and then we just do return

big

what do we think we're going to get here

for this we can go ahead and use

javascript vm because we're not

interacting with any other contracts

let's deploy this

and we'll see in our contract if we call

overflow now we're just going to get

255.

however what happens if we add 1 to this

number or try to add 1 to this number if

we do it just like this solidity

actually knows that there's an issue

here and says hey

try not to do this

but if we typecast this as a uint eight

solidity gets a little bit more confused

and goes ahead and lets us do this

now what do we think big is going to be

it should be 256 right

but big is the uint 8 and this is the

maximum size that it could be so what

happens when we deploy this

we look down

we actually get zero

what happens if we do 100 and we deploy

that

we actually get 99

and this is because integers can

actually wrap around once you reach

their maximum cap they basically reset

this is something we need to watch out

for when working with solidity if we're

doing multiplication on really big

numbers we can accidentally pass this

cap luckily as a version 0.8 of solidity

it actually checks for overflow and it

defaults to check for overflow to

increase readability of code even if

that comes a slight increase of gas

costs you can use this unchecked if you

want to have it keep that wrapping

functionality so just be aware if you're

using a lower version than 0.8 you're

going to have to do something to make up

for this and we could write a whole

bunch of code here basically to check

all of our math

or we could just import something called

safe math from another package

similar to how we imported chain link we

can go ahead and

import a package called

safe math

from a tool called open zeppelin

now open zeppelin is an open source tool

that allows us to use a lot of already

pre-built contracts

we can go ahead to the documentation and

go to their utilities and see safe math

and they even have a little sticker here

saying safe math is no longer needed

started with solidity 0.8 safe math is a

tool and a way for us to avoid some of

these problems with doing math and

solidity now i'm not going to spend too

much time on the contracts that actually

fix this but we can actually import

right from the chain link directory as

well

a solidity file called safe math chain

link and what we can do is right after

our contract

we can do using

safe math chain link

for

uint256

and what this will do

is it will use safe math chain link for

all of our unit 256

and safe math chain link doesn't allow

for that overflow to occur libraries are

really similar to contracts except that

they're isolated code that can be run in

a reusable context

in this case we're attaching the safe

math chain link library to uint256 so

that these overflows are automatically

checked for just keep in mind if you're

using anything less than 0.8 you're

going to want to use some type of safe

math just to check for your overflows

now this is for those of you who are

familiar with safe math and integer

overflows and underflows we are not

going to be calling the functions that

safe math provides us like div add mole

you know all those functions simply

because in 0.8 moving forward we no

longer have to use those and we can just

use our regular operators like plus and

minus so this is great our contract is

coming along really well we now have a

way to get the conversion rate of

whatever f is sent and turn it into us

dollar

now we can set a threshold in terms of

us dollar but how do we guarantee that

whatever amount that the users send when

they call fund is going to be at least

fifty dollars well first we might want

to set a minimum value so we can do unit

256

minimum usd

equals

let's say 50

and again since we're using everything

in way terms we want to then multiply

this by 10

raised to the 18th

and just want to take a pause for a

second because this line is actually

wrong this should be raised to the 18th

so this line should really look like

this where it has the double star so

apologies the rest of this has that

single star but it should be the double

star here if you do have the single star

though the rest of the contract will

still work fine so this will be the

minimum value it'll be 50

times 10

raised to the 18th so that everything

has 18 decimals now that we have a

minimum amount how do we actually make

sure that this minimum amount is met in

the value that they send us well if

you're familiar with if statements we

could do something like if message.value

is less than minimum usd

then

revert

or

we could do something a lot easier and

better practice and much cleaner we do

what's called a require statement when a

function call reaches a require

statement it'll check the truthiness of

whatever require you've asked so in our

case the converted rate of message.value

needs to be greater than or equal to

our minimum usd

this line

says that if the conversion rate of

message on value to usd if they didn't

send us enough ether

then we are going to stop executing

we're going to kick it out we're going

to say hey this doesn't count and we're

going to do what's called a revert we're

going to revert the transaction this

means that the user is going to get

their money back as well as any unspent

gas and this is highly recommended we

can also then additionally add a

revert error message something like

you need to spend more eath

so now let's try this out as we saw one

way

is going to be way less than fifty

dollars so if we send one way along with

this fund contract call it should kick

out and say you need to spend more eth

so let's actually try this let's go to

the deploy tab

we'll get rid of our overflow

we use injected web 3 because again we

are working with the chain link

aggregated contracts that are on chain

we're going to move to

fund me

and we're going to hit deploy

metamath's going to pop up and we're

going to hit confirm

now if i try to hit fund

let's see what happens we're getting a

gas estimation

failed since gas estimation error failed

with the following message

execution reverted you need to spend

more eth

so

the contract isn't even letting us make

the transaction we can go ahead and try

to send the transaction but here's

what's going to happen

on ether scan

once this goes through

you can see that once this transaction

finished we got this status fail with

error you need to spend more eth we

don't want to force these transactions

to go through if we look at our metamask

we can even see this failed bit here

so whenever you see these gas estimation

failed errors usually that means

something reverted or you didn't do

something that was required however if

we go to value here and we spend a lot

more

let's say

0.1 ether

which if we take out our calculator 2500

times point one it's going to be 250

dollars this should easily be well and

beyond past our 50 threshold

so let's add 0.1 ether remember we got

0.1 by adding it in the converter and

grabbing the way again the way is the

smallest denomination now if we change

this to way and hit fund this should go

through we're gonna hit fun now you'll

see men and mass pops up because

metamask goes oh yeah this transaction

isn't going to revert and that's what we

want so we can go ahead and hit confirm

and now we'll finally have sent some

funding to our contract

now that this is confirmed we go ahead

and grab our address here

pop it into our address to amount and we

can see that indeed our funding has gone

through

now we can be part of this crowdsourcing

application with our minimum value which

is fantastic awesome great job

awesome so now we can fund this contract

with a certain minimum usd value in this

case it's going to be 50

now you'll notice though that right now

we don't do anything with this money so

we're going to fund this contract

however that's it and we don't have a

function in here to actually withdraw

the money so there's no way that even

though we just sent this contract some

money there's no way for us to get it

back so how do we fix this well we can

add a withdraw function in here so let's

go ahead and add that

function

withdraw

and this is also going to be a payable

function because we're going to be

transferring eth

we'll make this public

and we can do

message

dot sender dot transfer transfer is a

function that we can call on any address

to send eth from one address to another

this transfer function sends some amount

of ethereum to whoever it's being called

on in this case we're transferring

ethereum to message.sender so all we

need to do now is define how much we

want to send well we're going to send

all the money that's been funded so to

get all the money that's been funded in

this contract

we can do address

this

dot balance

now there's a couple of special things

going on with this line

first we're saying address of this

this is a key word in solidity whenever

you refer to this you're talking about

the contract that you're currently in

and

when we add address of this we're saying

we want the address of the contract that

we're currently in whenever you call an

address and then the balance attribute

you can see the balance in ether of a

contract so with this line we're saying

whoever called the withdraw function

because whoever calls the function is

going to be the message.sender

transfer them

all of our money so let's go ahead and

try this let's deploy fundme

and now let's fund this with a lot of

ether so that we can see it we'll fund

it with one whole ether

so that we can see it go into the

contract and get pulled out of the

contract

we'll hit the fun

button and you'll see we're sending one

whole ether into this contract

now if we look at our balance it's gone

down from 17 to 16. or if you're still

at 18 it went down from 18. so let's try

to get it back

if we call this withdraw function now

confirm

once this transaction goes through we

should get all of our ether back

let's look at our metamask and boom

indeed we have got all of our eth back

however looking at this contract we can

see that hmm well maybe we don't want

anybody to be able to withdraw all the

funds in this contract that seems like

it might be a really bad idea maybe we

only want the funding admin to be able

to withdraw funds so how do we set this

up in a way that only the contract owner

can actually withdraw funds well we

learned before

that the require function can actually

stop contracts from executing unless

some certain parameters are met we can

do the same thing here with require

message.sender

equals

the owner

but we don't have an owner to this

contract yet so how do we get an owner

to this contract the instant that we

deploy it well we could have a function

called create owner but what happens if

somebody calls this function right after

we deploy it

well then we wouldn't be the owner

anymore

so we actually need a function to get

called the instant we deploy this smart

contract and that's actually exactly

what the constructor does so typically

at the top of your smart contracts

you'll see a constructor

and this is a function that gets called

the instant your contract gets deployed

you don't even need to do add function

here we can literally just call it

constructor

because it's what constructs the smart

contract so we'll make constructor

public and whatever we add in here will

be immediately executed whenever we

deploy this contract so one thing that

we could do

is we could have an owner be set the

instant we deploy the smart contract so

in the top we could add address

owner

and in our constructor

we could say owner equals message.sender

because the sender of this message is

going to be us it's going to be whoever

deploys this smart contract we can even

test this out in the javascript vm to be

a little bit quicker because we're not

actually going to be calling the fund

or the getprice function for now oops

let's also make this public so that we

can interact and see this owner variable

so now if we go to fund me we deploy

this in the javascript vm we should be

able to see who the owner of this

contract is and it should be our address

because this constructor function should

have been immediately called the instant

that we deployed the smart contract

awesome we can see the owner of this

smart contract is indeed our wallet

because remember we're working with the

javascript vm our wallet is these fake

wallets that they kind of give us

we can even try this with an injected

web 3

with deploying this

and the owner

should be this

ox 757 etc address

let's go ahead and look at fundme see

the owner and we do indeed see the owner

is us okay great

now we have an owner

we can go down to our withdraw function

and use that same require

so we can call

acquire

message.sender

equals equals

owner equals equals is the way that

solidity understands true false we're

saying that message.sender has to equal

owner now let's go ahead and try this

and we'll try with the javascript vm

again for speed reasons

let's deploy this funding

and if we go down here

we try to call the withdraw function and

it looks like it is successful because

currently

this is the address that deployed the

contract and it's also the address that

is calling withdraw

however

if we switch to a different account

and call withdraw you'll see

that remix actually freaks out down here

it says uh oh something wrong happened

and this is essentially the require

statement kicking out if you want to try

it with injected web 3 as

well can absolutely do that too and

remember the way to switch accounts in

metamask is to either create a count

right here or just switch like this

and then we'll connect with account two

so if i try to withdraw

from this

second account

that didn't call the contract and i hit

withdraw now

it's going to give us gas estimation

failed because the required statement is

going to kick out but again if we switch

back to account 1

and we call withdraw

metamask is going to pop up and it's

going to allow us to withdraw now

obviously there's nothing in this

contract right now so we're going to

withdraw nothing but we can still call

it it's going to do message.transfer

0.

so this is great

we can now require this withdraw

function is only callable by the owner

now what if we have a ton of contracts

that want to use something like this

they require the message.sender to be

some owner or maybe it's more

complicated than this is there an easier

way to wrap our functions and some

require or some other executable well

this is where modifiers come in we can

use a modifier to write in the

definition of our function

add some parameter that allows it to

only be called by our admin contract

modifiers are used to change the

behavior of functions in a declarative

way let's create our first modifier

we'll call it modifier

which is a keyword

only owner

and we'll add this require statement in

here

require message.sender equals owner

then after this we just add an

underscore and a semicolon

what a modifier is going to do

is it's going to say hey before you run

this function do this require statement

first and then wherever your underscore

is in the modifier run the rest of the

code

so we could also do a modifier where the

underscore is up here and then this is

afterwards but but we want to run the

require first

so now what we can do

is we can make this function withdraw

payable

only owner public

and what's going to happen

is before we do this transfer we're

actually going to check

this modifier we're actually going to

run this require message.sender equals

owner and then again where this

underscore is that's where we'll add the

rest of the function

so again

for speed reasons and since we're not

actually going to be interacting with

the chain link data contract we can go

to javascript vm

switch to funding

deploy

and we can call withdraw

obviously we can call withdraw from our

account but if we switch accounts and

try to call withdraw

we're going to get an error which is

perfect because that means our modifier

is working correctly

awesome now we have a fantastically

succinct fund me contract here

the only thing that we're really missing

is that when we withdraw from this

contract we're actually not updating our

balances of people who funded this

so even after with we withdraw this is

always going to be the same so we need

to go through all the funders in this

mapping and reset their balances to zero

but how do we actually do that we can't

actually loop through

all the keys in a mapping when a mapping

is initialized every single key is

essentially initialized now we obviously

can't go through every single possible

key on the planet

however what we can do is create another

data structure an array something we're

already familiar with so let's go ahead

and create a new funders array that way

we can loop through them and reset

everyone's balance to zero we'll do an

address array

because it's going to be an array of all

the funders addresses

we'll make it public

and we'll call it

funders

now when somebody funds a contract

what we're going to do is we're going to

do funders

now whenever a funder funds this

contract we can go ahead and push them

onto our funders array

so we can do funders

dot push message dot sender

now if somebody funds multiple times the

funders array is going to be a little

bit redundant but we're going to ignore

that for now now that we have an array

of funders when we withdraw everything

we're going to want to reset this to 0.

when we withdraw everything we want to

reset everyone's balance in that mapping

to 0. so we're going to do what's called

a for loop a for loop is a way to loop

through a range of numbers to do

something so we're going to say

4

you and 256

funder index

equals zero because we want to start

with the zeroth index

we're going to give it a max size to go

to we're going to say the funder index

has to be less

than funders dot length

dot length is how we get the length of

our array

and then we're going to say funders

index

plus plus this means that we have an

index variable called funder index

and it's going to start from zero

this loop is going to finish whenever

funder index is greater than the length

of the funders

every time we finish a loop we're going

to add one to the funder index that's

what that funder index plus plus does it

adds one to the funder index and every

time whatever code is in this for loop

executes we're going to restart at the

top and all we're going to do in here is

we're going to grab

the address of the funder

from

our funders array

funders

so the funder

at the index in our funders array

we're going to use this

as the key in our mapping

so we're going to take

address to amount funded

of funder

and we're going to set it equal to zero

so now our mapping is going to be all

updated to people having xero funded in

there

we do have to do one more thing as well

we have to reset our funder array as

well

now there's a couple ways to do this but

a really easy way is just to

set funders equal to a new array so we

could do funders

equals a new

blank

address array

so all right it looks like we've got

everything in here we need right away

when we deploy this we are set as the

owner

we can allow anybody to fund whatever

public good that we're doing

and they have to fund it with the

minimum usd value that we actually set

whenever they fund we'll keep track of

how much they're funding and who's been

funding us we can get the price of the

ethereum that they send in the terms of

usd

and we can convert it to check to see if

they're sending us the right amount

we have our only owner modifier so that

we're the only ones who can withdraw

from the contract and when we do

withdraw everything from the contract we

reset all the funders who have currently

participated in our crowdsourcing

application

awesome let's see if everything works

end to end

so we're going to go to fundme

we're going to deploy it

we're going to confirm from metamask and

remember if you're ever confused about

what's going on or or something weird is

happening in your transactions or your

deployments you can always go into

etherscan and read more about your

transaction and what's going on

now that our transaction has been

deployed let's go ahead and just take

inventory as what's going on

we have our owner

which is our address right here

we have the aggregator v3 interface

version which is version 3 which we can

kind of ignore

we have the price of ethereum in terms

of usd

with 18 decimals instead of 8. we have a

function that allows us to get the

conversion rate of any ethereum amount

to its us dollar equivalent

we have an array of funders which right

now starts out as empty

we have a mapping of addresses which

also right now starts out as empty let's

go ahead and try to fund this contract

we'll use way just that we're always on

the same page

and we'll fund it with 0.1 away

remember everything has 18 decimal

places so if we want to do 0.1 we just

do 17. so we can do one one two three

four five six seven eight one two three

four five six seven eight nine and

that'll be 0.1 ethereum now we can go

ahead and hit fund

and we're going to send 0.1 eth to this

contract

great so if we look at the zeroth index

of funders we can see that indeed

we have funded this contract

let's even have

our second account fund this contract

so all we got to do is switch

to this contract in metamask

we can go ahead

and put point one eth back in here

for value

and hit fund

now as you can see we're deploying this

from account two

let's go ahead and hit confirm

funder at index zero is going to be our

admin and the funder at index one is

going to be our second account

and if we go ahead

and we add

this funder in here we can see we've

indeed sent point one ether with this

account if we go back to our count one

and put this in here

we can see that that address also has

0.1 ether

fantastic

so let's try to be malicious let's try

to have account number 2 actually

withdraw all the funds in here

let's hit this withdraw function

uh-oh

the transaction has failed we're

relentlessly malicious we want to send

this transaction regardless so even

though i'm not the admin of this

contract i've gone ahead and still tried

to send those withdrawal so what happens

now

we can see that remix is saying hey

something went wrong

and again if we look at ether scan we

can see that there is a fail here since

in our modifier we didn't give a reason

here

nothing shows up but we could have

always put a reason in there and

something would show up

so all right let's go ahead back to the

actual admin

and now let's try to withdraw everything

so if we hit withdraw now

we can go ahead and confirm what should

happen is everything in here should be

back to zero and this array should be

back to zero as well and if we watch our

address we can see it literally just

went from point four to point six

because it got point one from the

original funding that this account put

in

and the 0.1 that our second account put

in

so now if we look at funder 0 we can see

it actually errored because it is now a

brand new array and there is nothing at

index zero if we try to see how much

this address now is funded it's back

down to zero awesome you've now learned

how to deploy a relatively simple yet

effective crowdsourcing application

where users can fund and an admin can

withdraw those funds to go spend them on

things

now we've been working with remix so far

to start our smart contract in our

solidity development journey remix is an

incredibly powerful what's known as a

web ide or an integrated development

environment and in my opinion remix

should always be the starting ground for

anybody looking to start their smart

contract journey because it is a

wonderfully friendly way to really show

what's going on behind the scenes and

it's really easy to see everything we're

doing with ethereum with chain link and

with our smart contracts now it does

have some limitations though it's really

hard to integrate other parts of

different projects it has some limited

support for testing or custom

deployments it's a little tricky to save

files locally you need an internet

connection to actually interact with it

and it doesn't have python so in order

for us to deploy test and automate

everything about our smart contract

development cycle we want to connect our

solidity and our smart contracts with a

more traditional programming language

like python this way we can customize

our entire development environment in

any way that we like we're first going

to teach you all how to work with what's

known as web3.pi which is an incredibly

powerful python package for doing

everything that we want to do with smart

contracts then once we learn some of the

basics of web3.pi then we'll move on to

browning which is a smart contract

development framework built on top of

web3.pi which makes our lives even

easier however it's still really

important to learn web3.pi first because

this will teach you what's going on

behind the scenes of brownie

now for the rest of this course i'm

going to be working with visual studio

code which is an incredibly powerful

text editor that will give us a lot of

formatting and a lot of really nice

tools to work with deploying and

interacting with our smart contracts if

you've already got vs code and python

and your entire coding setup set up the

way that you like it feel free to use

the timestamps in the description to

skip ahead to the next section you'll

often hear people referring to this as

vs code or visual studio code but just

to point out this is not what you're

looking for right in front of you here

visual studio is a different application

make sure you're on visual studio code

if you want to be a total hardo and just

work with vim or emacs or whatever else

you want to do you absolutely can but

i'm going to go through setting up

visual studio code the way that i like

it and if you guys want to follow along

i highly recommend it because it's going

to make your life a lot easier there's a

link to download visual studio code in

the github repository basically all you

have to do is come to the site right

here and you can hit this big download

button it should recognize what

operating system that you're on be it

windows be it mac or some other

operating system and if it doesn't you

can go ahead and hit this little drop

down and pick one there so let's go

ahead and download visual studio code

and open it up

awesome once you've downloaded visual

studio code this is approximately what

you should be seeing

there's a fantastic getting started

section here where if you're brand new

to vs code and you want to learn a

little bit more quickly you absolutely

can and we have some links as well in

our github repository giving you a crash

course in vs code if you want to learn

more let's set this up though so it's

going to be really friendly for us to be

doing our smart contract development

here so first we want to go to this

extensions tab it looks like these

little blocks thing right here

and first we're going to look up python

and you want to install this python

extension right here this is going to

make our lives a lot easier for

interacting with python and doing a lot

of things with python

then you're going to want to go ahead

and download this and install this

solidity extension this is going to make

formatting our solidity a lot easier now

we want to download python if you

haven't already so go ahead to

python.org

let's go to downloads and it should

recognize what operating system that

you're on and you can just go ahead and

hit the download button and then follow

the steps to download this i've already

got it download so i'm not going to walk

through this

okay great now that we have python

installed one of the other amazing

things about vs code is you can actually

open a terminal up inside a visual

studio code the way you can open your

own terminal if this is your vs code

you can go over on this top bar to

terminal

and select new terminal

and you'll see something that looks like

this

it might be a bash it might be a zch it

might be a powershell there's a lot of

different types of terminals that you'll

be able to see by looking right here we

can now test to see if python is

installed correctly if we type in python

space

dash dash

version

we should get something that looks like

this the exact version of python doesn't

really matter here but ideally you're at

least on python 3.8 if python dash

version doesn't work you can also try

python

3-version now if neither one of those

works we actually have a number of

troubleshooting tips in the github

repository for this course and

oftentimes a quick google search on

whatever error that you have you'll get

a link which will lead you to the answer

but if that google search doesn't lead

to the answer then just go ahead and

drop an issue or conversation associated

with your issue on the github repo

associated with this course in

particular there are a couple of common

errors that i've definitely seen a

number of times so if you see an issue

on your instance that matches something

on the screen here definitely 100 be

sure to check out those troubleshooting

tips sometimes just installing some of

these applications is really the hardest

part of doing the entire coding journey

here so please make sure you have python

and vs code installed correctly before

moving on and don't be discouraged if

this doesn't work exactly the way that

it should right away now if you're on a

mac you can actually hit control back

tick and it will toggle back and forth

between having the terminal open and

closing it i find this really helpful

and i use it all the time instead of

hitting

the buttons a key tip for productivity

is going to be using keyboard shortcuts

instead of clicking around all the time

you'll be much faster okay great we have

python installed we have python and

solidity extensions of visual studio

code installed let's start working on a

new project so in our terminal so in our

terminal we can create some folder i've

already created a demos folder here

you can create one as well if you'd like

by doing mkdir

demos

since i've already done it the file

already already exists

and then cd into demos

you can type clear or if you're on a mac

command k to clear the terminal now

here's what we're going to be doing

we're going to be working with

simple storage again the exact same

contracts but instead we're going to be

using web3.pi

so we're going to make a new directory

inside of our demos folder slash

directory called web3

pi

simple storage

and we're going to cd

into this new

folder right here now again all the

completed code is going to be in our

github and there's going to be a link to

everything that we do in this folder in

this github so you can always refer to

that if you get lost and the next thing

that we want to do is we want to have

our visual studio code know that we're

in this folder so we can go ahead and

click this files icon and hit open

folder

and i'm just going to go to this web 3

pi simple storage and hit open and

another vs code will actually pop up we

can see on the left hand side here

we have a folder this will show all the

different files and folders in our web 3

pi simple storage directory let's go

ahead and create a file

dot sol we can right click on this area

and select new file and do

simple

storage

dot soul and then we can go back to our

simple storage dot soul in remix copy

everything and then paste it into here

if you don't have it up remember you can

always refer back to the github

repository which will have it in there

for you awesome now we have our solidity

in its own file called

simplestorage.soul you'll notice that

some of the words are actually

highlighted different colors this is

known as syntax highlighting and it's

due to the fact that we added the

solidity extension in it makes reading

this code a lot easier now this file is

in here we'll see that we have this

little dot here

whenever you see this little dot this

means that your vs code file isn't saved

so we want to always save it otherwise

when we compile or we go to write a

script things might not work correctly

so we can save it by going up to file

and then selecting save or again you're

going to want to learn how to do the

keyboard shortcuts because you're going

to want to hit save often for mac it's

command s and for windows it's ctrl s

now the other thing that you'll see is

you get this red line here this is vs

code's way of telling us it thinks that

there's an error at this position so

this is really just the extension being

a little bit confused here and we can

safely ignore this and normally when i'm

coding i do just ignore it we're often

going to be flipping back and forth

between compiler versions so oftentimes

this isn't really a helpful warning here

but if it is really bothersome you could

right click it and do something like

solidity change global compiler version

or we can go to code

preferences

settings

let's close this so we can see some more

things in here we'll look up solidity

and we'll come to this solidity

extension config what we can do then is

scroll down

and we can see solidity compile using

remote version this will allow us to

choose what version we want to compile

with if we do 0.6.0

and hit save

and go back to simple storage you'll see

the red line is now gone while we have

this up another really helpful piece

that we can do here is we can add what's

called a formatter so if we scroll down

to solidity formatter you'll see that

this enable slash disables the solidity

formatter we can go from none to

prettier then we'll also look up format

on save and we want to make sure we have

this editor format on save check marked

what we can do then is we can come over

to simplestorage.sol

and

maybe i've got some bad formatting in

here we'll move over favorite number

string name and put a whole bunch of new

spaces in here or something

now if i hit save it automatically

reformats our file to look a lot nicer

so to recap we want to turn on format on

save and if you get issues with a red

line under pragma solidity you can just

change the compiler version in your

settings here now while we're in here

we're also going to go ahead and set up

our python formatting as well

so the first thing that we're going to

do is we're going to install the black

python formatter so we're going to open

up our terminal here

and whenever you install python it comes

pre-installed with this package called

pip to check to see if you have pip

installed correctly run pip dash dash

version

now we can install the black formatter

by running pip

install

black

i already have it installed so it's

going to be pretty quick for me

then we'll come to our settings

and we'll look up

python

formatting

and we'll scroll down

to python formatting provider you might

have autopet bait or none in here you're

going to want to change it to black

this way whenever we save our python

files now they will also get

automatically formatted to be very

readable and really nice and just to

note for my demos in solidity i don't

always have format on save for solidity

i do have format on save for my python

but i'm still going to highly recommend

you have format on save for both your

python and for your solidity anyways so

how are we going to actually deploy this

well this is where our python is going

to come into play

let's go ahead and create a new file on

the left here

and we'll call it

deploy dot pi now let's go into this

deploy.pi file and let's start actually

figuring how we can deploy this in

python and this is the part of the

course where we start using python here

if you're unfamiliar with python or a

little bit weaker on python there is a

fantastic free code camp course that

goes through all the basics of python if

you want to learn more i definitely

recommend checking it out however we are

going to walk you through all the

scripts that we write anyways so don't

be afraid to just jump in and follow

along with what we're doing here even if

you have no experience so the first

thing that we're going to want to

actually do is read this simple storage

solidity file we need to get this into

this deploy script so that our python

file knows what it's going to deploy so

how do we do this well we're going to

type with

open

quote dot slash

simple storage dot sol

comma r

as file

simple

storage file equals file dot read now

what is this actually doing

well it's saying that we're going to

execute some code

inside this indented area

after the colon and then once this code

is finished we're actually going to

close this file because right now we're

opening it we're going to close it once

it's done

the file that we're going to open is

going to be this simple storage.sol

which is located right here in this same

directory that we're in we're going to

only read from it and we're going to

call it file and then we're going to

read all the contents of this file and

place it in a variable simple storage

file

so then we can go ahead and write a

print statement print simple storage

file and if you hit save here you'll see

that it automatically gets formatted

which is really nice if you want to run

black yourself you can just type black

dot and it'll automatically format all

the python files in your folder here

you'll know that you're doing it right

if you add a whole bunch of new lines

and then save it anyways enough on

formatting let's head on down to the

terminal and let's call python deploy.pi

and we can see

our terminal printed everything in

simple storage file

which is perfect now our python script

has what it needs to actually get

started working with our solidity now

something you'll see i do a lot is i

save a lot and if you're looking for

some keyboard shortcuts you can always

do command p add a little bracket here

and look

up keyboard shortcuts reference

and click this

it'll bring you to this keyboard's

reference page based off of what

operating system that you have all right

great so now that we can actually read

from our simple storage.soul file we

actually have to compile it because

remember back in remix every single time

we did anything with our files we had to

compile them first

so we need some compiler in python

luckily there is a fantastic python

package called pi silk x that does

exactly this now i also want to point

out though that pi silk x is actually a

fork of this package called pi silk now

you can still use pysol however i'm

going to highly highly recommend that

you use pi silk x instead as pike sulk x

is a lot more actively maintained than

ethereum pixel we can install it with

pip install pi sulk x we could even hit

this little copy button move back on

over here paste it in and hit enter

again i've already installed it so it's

pretty quick for me the way that we can

use it now is by importing it into our

python here so we'll say from

sulk x

import

compile

standard compile standard is going to be

this main function that we actually use

to compile this code so let's go ahead

and compile

our solidity

we're going to save our compiled code to

a variable called

compiled soul

this is going to be equal to

us calling this compile standard

function

but we're going to add a lot of

variables and a lot of parameters into

this function here first we have to add

is a language

which in this case is

solidity we're going to add in some

sources

which we're going to say our sources are

going to be simple

storage.soul

and it's going to have some

content which is equal to this simple

storage file variable that we made

oh excuse me this all has to be in a

bracket piece as well

and see if i hit save here it auto

formats which is really nice and another

quick tip you can see how even my

brackets are highlighted in these fun

colors if we go down to extensions and

look up

bracket

you can add this bracket pair colorizer

which will help make the brackets look a

little bit nicer kind of as you see here

you can go ahead and install that as

well anyways then we'll add some

settings

and a lot of this is a little bit lower

level stuff than what you're really

going to have to know or use so i'm not

going to go too deep into everything

that's actually going on here for now

but in our settings

we're going to choose an output

selection

which is going to choose what we output

when we compile this

we do a little star here

and in the star we're going to do

another star

we're going to choose our output list

we're going to get an abi out that's

incredibly important which we've talked

about before

we're going to get some metadata

we're gonna get an evm dot byte code

we're gonna get an evm dot

source map

that's pretty much it again i'm not

gonna go too deep into what this output

selection and what these settings are

actually doing but if you want to learn

more you can go to the home page of pi

sulk x

scroll down to the documentation section

and read more in the docs on what you

can actually put and all the different

features that this actually has the last

thing we're going to do is we're going

to add a sulk version or solidity

version we're going to say

sulk

version

equals and then we'll choose the version

that we want to use so we'll put in

0.6.0

and then what we should be able to do is

print out

this compiled soul

and we'll see just a whole bunch of

really really low level stuff

so let's go ahead and run this we'll run

python

deploy.pi

and you'll see we get this

massive object here which has a whole

bunch of basically unreadable pieces but

this is a lot of the low-level code that

actually gets compiled whenever we use

the compiler in remix or now in python

remix actually does the exact same thing

once we compile something on remix you

can actually copy the bytecode if you

hit this little

copy button and copy the bytecode and

come back to your vs code and create a

new file a keyboard shortcut to create a

new file is command n and we paste

everything

we can see there's a whole bunch of

stuff in here these op codes are the low

level code that our contract is actually

doing that actually governs how this

code works this is what our written code

is getting compiled down to so solidity

can actually read it and understand

what's going on you'll also see this

thing called abi which is in remix and

we're even going to output it right here

we have this abi thing now in remix if

you hit copy the button on the api

come back

create new file paste it you can see we

have this long json object this is that

application binary interface that we've

talked about so much you can see that

it's actually describing all the

functions and variables

so for example

we have a function

called add person

and it takes two parameters a name

and a favorite number

so we have this input section for the

function and we have this section that

describes what the function can is

actually doing so the name is ad person

it doesn't have a return type it's

non-payable and it's a function and we

can see that for pretty much everything

in here this is the lowest digestible

way to say hey here's where all the

functions are here's what the parameter

types are here's what the return types

are going to be and everything like that

so we're going to close it out for now

though so this is fantastic we've now

compiled our solidity typically i

usually also like to output it and print

it out to a file as well so to do that

we'll do with

open

compiledcode.json

and this time instead of reading we're

going to write

and we'll call this as file as well

instead of doing file.write we're going

to do what's called a json.dump

compiled soul file

we do need of course to import

json also just a note i know it says

we're using sulk here but please use

sulk x still i ended up filming a little

bit of both versions so i did a little

bit of a mix and match but please use

sulk x even if you see seoul what this

line is going to do

is it's going to take our compiled soul

jason variable and just dump it into

this file here

but it's going to keep it in the json

syntax so it's still going to be json e

so now if we run python deploy.pi we'll

see we have a new file in here called

compilecode.json

the other reason that i wanted to do

this was because

if i hit control s

it actually formats this into a readable

way now again we can go into these

settings here

we can look up

json and we can do enable json formatter

and this will automatically make it so

that we format this json so it's a lot

more readable again the reason i like to

output this is because this abi is so

important and we're going to use it so

much that i like to kind of be able to

see it and and read through it really

quickly the rest of this lower level

stuff like evm and byte codes and op

codes we don't really work with so much

however as you learn more and more about

solidity you'll probably see more and

more of opcode so if you really want to

learn a lot of really low-level stuff

look into opcodes but for the purpose of

this tutorial we're not going to be

going too deep into it okay awesome so

we've compiled our solidity we've even

stored our solidity code to this

compiledcode.json file

now what do we do we probably want to

deploy it and test it out

so how do we actually do that well first

we actually have to get the bytecode we

need the bytecode of the file so that we

can actually deploy it so we're going to

do

bytecode

equals

compiled soul

contracts

simple storage dot sol

simple storage

evm

white code

object

all right great there we go so now we

have our byte code we also need to get

our abi so we need to get the api so

what we're doing here when we're typing

in all these words like contract simple

storage simple storage

is we're walking down the json here so

when we say we want to get the byte code

in this compiled solidity json we want

to go to contracts

simple storage symbol storage evm byte

code

so contracts inside this contracts json

you got to go to simple storage inside

this simple storage dot soul there's

another simple storage

inside that there's an avi but that's

not what we want we want the evm so

we're going to scroll down

we're going to get the evm then what do

we want then we want the bytecode great

and then we want the object so this

is the bytecode of our contract

it's the really low level stuff that

the ethereum virtual machine or the evm

is going to understand now we also need

the avi when we deploy this to a chain

this is what we're going to need we need

the byte code and the abi the abi we can

of course get from this kind of same

method here so to get this we can do abi

equals

compiled soul

same thing

contracts

simple storage dot soul

simple storage

and as you can see

we're right here and then we can just

grab this api object

avi

and we can even do print api we'll do

python develop.pi

and indeed our abi is printed here

awesome so now that we have our two main

pieces to deploy this now all we have to

do is deploy it but the question then

becomes is where are we going to deploy

it to which blockchain are we going to

deploy to in remix

when we were first playing around

we were using a javascript vm

or a fake or a simulated environment we

absolutely could and we absolutely will

learn to deploy this to a test in

because that's going to be the same way

that we're going to deploy to a mainnet

but before we do that we should learn

how to deploy this on a simulated

environment or something similar to that

javascript vm so it's much faster and

easier to test things and this is where

ganache is going to come to the rescue

ganache is a simulated or a fake

blockchain that we can actually use to

deploy our smart contracts to and have

it interact like it's a real blockchain

ganache is going to allow us to spin up

our own local blockchain

and it'll look something like this now

the user interface is really nice

because it allows us to kind of do this

one-click blockchain to create our own

local blockchain

that means that this blockchain isn't

connected to any other blockchain out

there but it'll act like a blockchain

but it'll be a lot faster than us having

to interact with a testnet and we

control the entire blockchain because

it's only one node we're the only node

so ganache great way to test things

quickly now we're going to mainly we're

working with the user

but i'm also going to show you how to

work with the ganache command line you

can really use either one depending on

what you want to do but a lot of the

tools actually have built-in ganache

command lines so it's definitely really

useful to learn that as well so again

ganache is going to be our simulated

environment here so what we're going to

do

once we get into ganache we can just go

ahead and hit quick start this will

automatically upload and get started

with our own local fake blockchain you

can even see it gives us some accounts

this should look pretty familiar it

should look very meta-masky right we

have an address here

and each one of these addresses has a

private key in your ganache you can go

ahead and just click the key and hit

show keys and it'll show you the account

address and the private key but of

course these are for development

purposes only each one of these accounts

has a balance associated with it we can

see a mnemonic or your secret phrase you

can see blocks transactions and a whole

lot of other really useful features here

and it even tells us

how to connect to this blockchain

and these are the connecting features

that we're going to want to use let's

learn how to connect to this ganache

blockchain from this user interface

first and then we'll learn how to do the

command line version this is when we

finally start working with web3.pi you

can just do pip

install

web3

and now we can start working with

web3.pi right at the top a little

confusingly

we're going to do import

web3

from

web3 whoops and this should be

from web3 import web3 sorry about that

now to connect to this blockchain we

choose what's called an http provider if

we look at this ganache instance we have

this rpc server which has this url http

0.0.0

this is the url that we're going to use

to connect to this blockchain in remix

we're actually using our metamasks

directly to connect to the blockchain

however we want to connect directly to

our simulated our fake blockchain right

here so what we're going to do is we're

going to do

w3

for

connecting to ganache

w3 equals

web3 web3.http

provider

of http

0.0.0.0

and it was on port

845.

port 845. now with everything that we

show you you're probably going to want

to get really familiar with the

documentation because even after being a

pro you're going to want to use it more

and more if you want to learn more about

other providers you can go to the

providers page of the documentation the

next thing that we're always going to

need as well is we're going to need the

chain id or the network id what is the

id of this blockchain

and for ganache it's one three three

seven

supposed to be a funny leat reference so

we'll do chain id

equals

one three three seven

now

we're also going to need an address

and address to deploy from

we can go ahead and grab one of these

fake addresses in here to work with

similar to how in remix when we were

working with the javascript vm we were

given a bunch of fake addresses we're

doing the same thing but with ganache

and then we're also of course going to

want a private key

we need the private key of course to

sign our transactions

so we'll do private key equals

this

now just note whenever you import a

private key in python you need to add an

ox to the front python is always going

to look for the hexadecimal version of

the private key awesome now we have all

the parameters that we need for

interacting with and connecting to our

ganache local chain it's time to finally

deploy our simple storage.soul contract

let's do it so the credit contract that

we're going to deploy with web3.pi we're

going to do simple storage

we're going to call this variable

w3

dot f

dot contract

and we're going to give it abi equals

abi

and byte code equals byte code great

does this mean we've deployed it well no

this just means we have a contract down

so we can do print simple storage and

you'll see if we run python

deploy.pi

we'll see we have a new type here

class web3.utils.datatype.contract

this is another type that if you want to

learn more you should definitely check

out the web3.pi documentation so we have

a contract object

awesome how do we actually deploy this

well we need to actually build our

transaction

because again whenever we interact with

the blockchain whenever we make a state

change and in this case we'd be

deploying a contract we're going to make

a state change so we first need to build

a transaction sign a transaction

and then send a transaction and to do

that we need to talk about that nuns

thing again remember way back in our

blockchain demo when we used a nuns to

solve the answer to that really

difficult mining problem well the

definition of nuns is just a word coined

or used for just one occasion and in

cryptography it's an arbitrary number

that can be used just once in a

cryptographic communication so this nuns

that's used to find the answer is going

to be different from another nuns that

we're actually going to need to make our

transaction see if we look at our meta

mask and we look at our activity

and we look at one of the transactions

we've made recently on etherscan

if we scroll down we'll see nuns

here as well this nunce is the number of

transactions that our account has

actually made every time we make another

transaction our transaction is hashed

with a new nuns this is what's going on

behind the scenes with our transaction

and we need this to send our transaction

we can actually get our nuns by just

grabbing our latest transaction count

get

the latest

transaction we can do

nonce equals w3

dot eth dot

get transaction count and we'll put in

my address

this will give us the number of

transactions and it'll effectively give

us our nuns

we can even test it out with a print

python

deploy

we can see we can see that the answer is

zero because on our local blockchain

this address that we're using hasn't

been used before we can even go to the

transactions tab we can see that there

are no transactions that have ever

occurred on our local blockchain now to

deploy this contract we need to make a

transaction remember everything that we

do every time we change the state of a

blockchain we're going to do it in a

transaction let's create a transaction

object to do this we can do

transaction

equals

symbol storage which again is this

contract object

dot

constructor

dot build transaction

now as you might have pointed out our

simple storage.sol doesn't actually have

a constructor every contract technically

has a constructor this one's is just

blank we're not telling our simple

storage.soul to do anything

we saw back in our fund me

example that the fund me example does

have a constructor so now we want to put

in some parameters for the transaction

in web3.pi we always have to give at

least a couple of parameters

we always have to give the chain id

which we already got from above which is

one three three seven

so we can just do chain id

we need a from

address in this case

my address

and then

we need a nuns

which in our case is just nuts

great now we have a transaction object

let's even print this out and see what

it looks like

whoa what's this we can see there's even

more parameters in here than just what

we made

so we have value which is the ether or

the ethereum that we're going to send we

have gas we have our gas price which we

could arbitrarily set if we'd like

we have the chain id we have from

address we have the nuns

and then we have this giant data object

and then two is just empty because it's

sending it to the blockchain this giant

data object here is encompassing

everything that's happening in this

simple storage dot sol now that's just a

transaction and anybody could actually

send this transaction as long as it's

signed by them so we have this

transaction but we need to sign it from

somebody since we're sending it from our

address

our private key is going to be the only

key that's going to work to sign this

remember back when we were talking about

public and private keys we right now

have a message that is defining how to

deploy simple storage but it's not

signed yet so we're going to need to use

our private key to sign it to create

this unique message signature that we're

the only ones that can create the

private key but anybody else can verify

that it was us who signed it so now

signed

transaction

equals web3

dot eth

dot account

dot sign transaction

and the parameters it takes are going to

be transaction

and then private key

we're gonna say the private key equals

private key because above we've actually

gone ahead and added our private key in

here now guys a really really important

note about putting a private key in your

code this is really bad practice if you

push this to source or you push this to

github somebody else can see your

private key and steal all your funds so

we don't want to hard code our private

keys in our code like we're doing here

so let's take this time to talk about

environment variables and how to set

them environment variables are variables

that you can set and that we set in our

terminal and in our command lines the

following is a way to set an environment

variable in macos and linux only don't

worry we'll show a way to make an

environment variable in windows as well

you can set an environment variable by

running something like export

private key

equals

and then adding whatever variable that

you want

now if you type echo

dollar sign private key

this variable actually shows up to set

environment variables with windows the

process that we're going to do is

actually a little bit different

i've left a link in our github to

actually set environment variables in a

windows setting

and we've left a couple of really

helpful links for working more with

environment variables you should

definitely check them out it's important

to note that this export method that

we're doing here for creating

environment variables only works for the

duration that our shell is live so if we

were to close out of our shell and then

reopen it our environment variable that

we set would be gone so we'd have to

re-run that export command we're gonna

show you a way to set environment

variables so that you don't have to keep

doing that now it's also not great to

have in plain text on your computer

however it's a lot better than hard

coding it into our script here now

remember if you're using an account that

has real money in it which i highly

recommend you do not do don't send this

environment variable or this private key

or any of this code anywhere because

then people can steal all your funds

once we move to brownie we'll show you a

more effective way for private key

management but for now be cautious here

but if you followed along and set up a

brand new account that has no real money

and only test that money in it then

great who cares because it's test and

it's fake money anyways

i think i've talked about it enough

anyways let's get back to it we can

actually access this environment

variable in python using os.get env

we just need to import os

and now we can access our private key in

our script without actually hard coding

it in

let's see what happens if we do print

private key python deploy to pi

you can see our python script was able

to pull our private key from our

environment variable the other thing

that we can do is create a dot env file

a dot emv file is typically where people

store environment variables it's

important to not push these to source if

this is what you're going to do in this

dot envy file in python we can just do

export

private key and then same as what we did

before

add the 0x at the start and then private

key so we could put 100 environment

variables in here

export

some

other var equals

seven

if you're going to do it in this way

please please please

always set a dot git ignore

and make sure dot env is in here this

will help make it harder for you to

accidentally push your env folder or

your emp file to github python actually

has a way of loading directly from a env

file without having to export our

environment variables or run source.env

or export or really anything and we can

do it with this python.env package

if we close our shell and then reopen it

if we run echo

some other var

we're going to get none here and in fact

if we run

python develop.pi when we print this

environment variable we're going to get

none

however we can use this.env to have it

pulled directly from our.emv so we just

do pip

install

python.env

i've already downloaded it so it just

says requirement already satisfied and

then

what we can do at the top of this we can

do from

dot env

import

load.enb and we can run

a load.enb function right at the top

this load.env looks for this.env file

and automatically imports it into our

script so if we run this now you'll see

that the environment variable was

successfully imported into our script

and now we can use it so let's let's use

it for example with our private key

private key

equals os that get

private key now we can even print it out

just a test

we'll run our script

and awesome

we can see our private key is being

successfully pulled in and we didn't

hard code it into our application

all right let's get back down to our

signed transaction here now let's go

ahead and print this out and take a look

at what this looks like now we can run a

script and great what we see here is an

example of a signed transaction remember

this is exactly what's happening when we

were looking back at public private keys

we are signing a transaction that is

actually deploying a contract to the

blockchain that anybody can easily

verify all right so we finally have our

signed transaction now we want to send

this to the blockchain so it actually

can deploy let's send

the signed transaction

we can do transaction hash

equals

web3.eth

here's a little helpful tip if you see

this little box underneath with

suggestions show up and you just hit tab

it'll auto complete the rest of your

text here that's send raw transaction

and we'll give it

our sign transaction

dot

broad transaction this will send our

transaction to the blockchain now if we

look at our local ganache and we look at

transactions right now it'll be empty

but let's see what happens when we run

this script

okay so we didn't print anything out but

if we go to our ganache we can see that

a transaction actually did go through

it was from the address that we put in

here we created a contract at this

address

this is how much gas it used

and this is how much value was sent with

it we can even click on it to see more

information about this now this is the

other advantage of doing this locally is

that the transaction automatically went

through we've sent our first transaction

to a local blockchain and this

transaction is deploying a contract

great work you can already see how much

faster this is than working with a test

net one other thing that's really good

practice whenever sending a transaction

is we wait for some block confirmations

to happen

so we can do

transaction

receipt

equals web3 dot eth

wait

for transaction receipt

txhash

this will have our code stop and wait

for this transaction hash to go through

awesome so i just ran it again and if we

go to transactions

we can now see that there are two

transactions here

and our code waited a little bit longer

for this one to complete so of course

we've deployed a contract but how do we

actually interact and work with the

contract let's start doing that so when

working with contracts and we're working

with on chain whenever we work with a

contract we always need two things

we need the contract address and the

contract abi often times if you're

looking for a specific abi of a type of

contract you can usually just google it

so we need to make a new contract object

to work with contracts let's go ahead

and create this simple storage contract

so we can actually interact with it

so we'll do simple storage

equals

dot w3.eth.com now we need our address

which we can get from ganache

but that might be a little bit hard to

always be checking the blockchain for a

transaction

it's actually also in this transaction

receipt address

equals transaction receipt dot contract

address

and then since we've compiled this we

also have our abi already

abi

equals abi

sometimes you'll see people have a file

called

abis.pi or abis.json or something like

that and they'll load apis in directly

from there and great now that we have

the address and the api we can start

interacting with this contract exactly

as we did in remix so let's do a print

statement to get that initial value that

is returned from our retrieve function

remember it should be initialized to

zero

so if we do print

simple storage dot functions

dot retrieve

let's see what happens here

huh what's this

we get this function retrieve bound to

in these parentheses here

so what's going on when making

transactions in the blockchain there's

actually two different ways that we can

interact with them we can interact with

a call

or we can interact with a transact when

we use a call

this is just to simulate

making the call

and getting a return value

calls don't make a state change to the

blockchain and it's similar to how in

remix we would call these blue buttons

and nothing on the blockchain would

actually change we can actually also

call these orange buttons or these

non-view functions and just not actually

make a state change remix defaults these

blue buttons to be calls and these

orange buttons to be transacts in python

we can actually pick which one we want

to do a transact a transact call is when

we actually

make a state change

and this is when we actually have to

build a transaction and send a

transaction you can always just call a

function no matter what that function is

but just keep in mind you won't make a

state change you can also always

transact on a function even if it's just

a view and this will attempt to make a

state change

something like retrieve even if we

transact on it it won't make a state

change so for something like retrieve

where we don't actually want to make a

state change

we just use the call function so we'll

just do dot call

now

if we try to run this

you'll see we do get the zero because

now we're actually calling this

transaction awesome so now we have our

initial value for our retrieve function

let's keep going let's try to update

this favorite number using this store

function this we'll just keep in mind is

our initial

value of

favorite number we know that this store

function is orange and we'll actually

make a transaction

but if we wanted to we can even just use

call on it

we'll do simple storage

dot functions

that's store

we'll put that 15 in here

call

let's see what happens when we send this

you can see it returned a blank that's

because this store

function has no return type if we give

this returns

unit 256

and then we say return

favorite number

and now we go back here

and we run this again

you'll see now that we get a 15 back if

we go to ganache you'll see that we keep

making a whole bunch of different

contracts but none of these are contract

interactions that's because when we call

a function we just simulate working with

it if we call retrieve again right

afterwards you'll see that it's still

zero

it's because calling is just a

simulation now let's delete all that so

let's actually build a new transaction

to actually store some value

into this contract since we want to make

a transaction we got to go through the

same process as when we deployed this

contract

let's first create a transaction

called store transaction

equals

simple storage

dot

functions

about store

and we'll give it some number in this

case 15

and then we have to do dot

build transaction

and we'll put those same pieces in here

from before we're going to have

chain id

be the chain id

we're going to need from

give me my address

nunce

is going to be the nuns

plus 1.

we're going to need to do nuns plus 1

because we actually use this nuns

already

when we create our initial transaction

remember a nuns can only be used once

for each transaction

so this transaction is going to have to

have a different nuance than the nuns we

use to deploy the contract now that we

have the transaction let's go ahead and

sign it

we'll do signed

store

tx

and

we'll do web3

that eath

dot account

dot sign transaction

store transaction

and then private key equals

private key and we'll go ahead and save

then of course we need to send it so

we'll do

transaction hash

equals w3.eth

dot send raw transaction

signed

store transaction

dot raw

transaction

and let's grab that transaction receipt

again

by doing transaction receipt

equals w3

dot eth

dot wait for transaction receipt and

actually let's call this

send

store

tx

that way for receipt

send store tx awesome it looks like

we're following the same steps here as

we did above

we created the transaction

we signed the transaction

and then we send the transaction

down here

we create a transaction

we sign the transaction we sent the

transaction and then we waited for the

transaction to finish

so let's run this

all right great we still have this print

function printing out the current value

of retrieve let's go over to ganache and

see if there's anything different here

there is instead of all these contract

creations here we now have a contract

call

we can see there's some transaction data

that was sent

a different amount of gas same gas

prices

however

this

actually updated and sent the

transaction to our blockchain

now if we call this retrieve function

again

this should print out our newly updated

value which in this case was 15.

let's go ahead and run

python deployed up high

and we can see it started at zero

and then it turned to 15. awesome we've

made our first state change to a

contract that we've deployed on our

local blockchain great work sometimes

it's nice to put some lines in here to

tell you what's going on to make it a

little bit more clear so i'll put

something like

deploying

contract dot dot

right before we deploy our contract

after we do it i might do

deployed

then

right before we update our contract

we'll print out something

like updating contract

and then right after it's done

maybe something like

updated

now if we run this now

you'll see as this goes along we'll get

these things printed out saying

deploying contract contract deployed

updating contract updated this will make

those moments when waiting for these

contracts to actually finish a lot

easier you're doing fantastic so ganache

user interface is really nice because we

can see a lot of things that are going

on here however it's a little tricky to

do a lot of programmatic stuff

oftentimes engineer will use what's

called a command line interface of

ganache instead of the ui so we're going

to go ahead and close this out and we're

going to use the ganache cli instead of

that user interface that we just saw and

this is what and this is what brown is

going to use on the back end when we

move to brownie let's learn how to

actually do that so in order to use the

ganache cli or command line interface

the first thing that we need to do is

download node.js yes i know this is a

python video however we do need to

install node.js to work with the ganache

cli you can come to this download page

and choose your operating system and

download it accordingly we will link to

a video showing you how to do this in

the github you'll know you've done it

right if you can run node

dash version in your command line and

you get a version it might be 12 might

be 14 might be something else depending

on what version you downloaded next

we're actually going to install yarn

yarn is a package manager similar to pip

and will allow us to actually download

pieces and packages like the ganache cli

from the package repository we can

install it with npm install dash dash

global yarn and you'll know you've done

it right

if you can run yarn

dash dash version in your command line

and you get the version outputted here

then we want to install the actual

ganache cli we're gonna be installing it

with yarn so to install this we're gonna

yarn global

add

ganache cli

this will install our ganache cli as a

global command in our terminal we can

test to see if we've done it right if we

can run

ganache

cli

dash dash version perfect we now have

the ganache cli let's spin up a ganache

chain with the cli

if you have your ganache ui open right

now please close it otherwise it'll

conflict so to run a local blockchain

from the command line all you need to do

is run

ganache

cli

and the node will start running directly

in your terminal

if you scroll up you can see a lot of

familiar pieces

we see the available accounts just like

on the ui

these are the different addresses

and then we see a whole bunch of

different private keys this ganache

spins up with a bunch of random

addresses and random private keys if we

wanted to always spin up with the exact

same private keys so we don't have to

update our private key every time

we can do ganache

cli

dash dash

deterministic

this way we'll always get the exact same

private keys

and the exact same addresses you can

check out the documentation to see a

bunch of other flags that you can use to

run this and you can see it's listening

on 127.2

127.0.0.1 is also known as the loopback

address or localhost now to work with

ganache in the command line

all we need to do now is update our

private keys and our addresses let's

also update the http provider since now

we're going to be looking at the

loopback address for my address

we'll scroll up

to this top address here

and we'll place it in

for our private key

we're going to copy this

and put it into our dot emv file

it already has the ox at the top here

great now let's open up a new terminal

you can open up a new terminal by

hitting this plus button here

and you can flip back and forth by

hitting this drop down and flipping back

to the ganache terminal now let's go

ahead and run

python

deploy.pi

we can see

the exact same output as we got when

working with the ui and if we flip over

to the command line we can see we've

made a whole bunch of different calls to

our blockchain each one of these calls

is a specific json rpc call to our

blockchain that we're making to interact

with it we can see information about the

transactions that we send this one

creates our simple storage contract

this one updates our simple storage

contract and great you now know how to

work with the ganache cli and the

ganache ui fantastic so how do we

actually deploy this to a test net or a

real network we were working with remix

all we had to do was switch to injected

web 3 and we used our meta mask as our

blockchain connection well in our script

here we don't have metamask natively

with our script so we need some way to

connect to the blockchain we can see

that when we're connecting to our own

local blockchain we just use an rpc url

that connects to our local blockchain to

connect to a test net or to a mainnet we

can actually do the exact same thing all

we have to do is swap this out with the

url that connects us to a mainnet or a

test app we can also run our own

blockchain node similar to how we're

running our own local blockchain node we

can run a node that actually connects to

a real blockchain however it's not

always practical or really easy to do

this so sometimes we want to use an

external or a third-party client that

actually will run a blockchain for us

let's learn a little about inferior

inferior.io is an application that will

give you a blockchain url for you to

connect with for you to run whatever you

want to run and you can get started for

free let's go ahead and register

then we just check our email

confirm email address and awesome now

we're inside of infira there's a couple

other services out there that you can

also check out like alchemy which is

another fantastic blockchain as a

service platform fura is a freemium

service it starts out as free if you

make too many api calls or too many

calls to the url they'll start charging

you

but we can create a project for free for

now let's go ahead

hit the ethereum tab

hit create project we'll call

this free code camp

brownie

hit create now we'll have a whole bunch

of project keys and project secrets we

also have this endpoint section as well

this is how we're going to be deploying

to the different networks we can see we

have an ethereum mainnet connection as

well as robson coven rink b and gorilla

testnets there's also polygon in here as

well since we want to test and deploy to

a ring b chain we can go ahead and move

to ring b and then

we can copy this url back in our

application all we have to do is swap

this out

for the new url we also have to change

the chain id

our address and the private key if you

ever are confused as to what is the

chain id of the chain that you're

working on you can always check this

chain id dot network or you can usually

ask somebody let's look up ring b we see

the chain id is four so we'll grab four

and we'll place that in our script now

this address and the private key that we

gave it now this address and the private

key that we gave it aren't going to have

any testnet ring be in them so we need

to go in our metamask and grab the

address place it in for address and then

account details

export private key

type in our password

and grab the private key go into our dot

emb file

leave the 0x and replace the rest with

our private key since i have my private

key stored as an environment variable i

need to then run source.env so that my

private key is now updated the reason

we're using this is because again since

we're making transactions to a testnet

we need some test and eth alright so now

we have everything updated for deploying

to rinkeby let's go ahead and run this

now

as you can see it's going a lot slower

this is because we actually have to wait

for the contracts to get mined and for

everything to happen

on the test net deploying to a tesla

will result in nearly the exact same

experience that you'll get when

deploying to an actual main net so it'll

take a lot longer but you can see we got

the exact same responses here now if we

take this address

and we go to the rink be ether scan

we can verify what just happened

we can see that 38 seconds ago

we made this transaction

and then 23 seconds ago we made this

transaction

we can look at all the different details

of this transaction that we just made

from our python script

we can see it even tells us we created a

smart contract

and then

we made this call

which called this store function on this

contract

we've learned a lot so far this is

fantastic now is a perfect time to take

a break and take a quick breather and

reflect back on what we've just learned

we've learned a lot about python

deploying to our own local blockchain

deploying to a test net and deploying to

a mainnet working more with private keys

creating transactions

signing transactions and then sending

transactions

now as you can see there's going to be a

lot to actually managing all the

contracts that we work with having to

write our own compile code our own

storage code is going to take a lot of

work and what if we wanted to interact

with one of the contracts that we

deployed in the past well we'd have to

keep track of all those addresses and

manually update our address features

here with an address maybe we didn't

want to deploy a new contract every

single time maybe we want to work with a

contract that we've already deployed

what if we want to work with a whole

bunch of different chains what if we

want to work with rink b and mainnet and

our own local network there seems to be

a lot to manage here and we still

haven't even talked about writing tests

this is where brownie is going to come

into play brownie is currently the most

popular smart contract development

platform built based on python it's used

by d5 giants like yearn.finance

curve.phi and out each having billions

of dollars currently locked in value and

the reason that we learned a little bit

about web3.pi first is because brownie

heavily relies on web3.pi so let's do

all this again but in brownie and we'll

see how much easier it is to actually

interact with in our shell

let's go back one directory and let's

make a new one we'll call it

brownie

simple

storage

now another really cool trick that vs

code has is instead of us having to go

to file and open up this folder in this

explorer here

what we can do is we can type code

and then type the directory that we want

to work with in our case

this directory so we can just type code

dot

and we'll get a new vs code pop-up

inside of this brownie simple storage

folder let's get learning about brownie

and this is where you're going to spend

the majority of your time move forward

brownie is incredibly powerful and makes

our lives fantastically easier so get

ready to learn one of the most powerful

tools in the smart contract developing

ecosystem let's go ahead and open up our

terminal and let's get started

installing brownie it's recommended to

install brownie via pipex pepex installs

brownie into a virtual environment and

makes it available directly from the

command line once installed you'll never

have to activate a virtual environment

prior to using browning which is really

good to install it with pipex we can go

ahead and run python dash m

pip install dash dash user pipex

once we've run that we can then run

python3-m pick at pipex in surepath

then we'll want to close the terminal by

hitting the little trashcan and then

reopen it and then we just need to run

pipex install f brownie i've already got

it installed so that's why we see this

here and then just one more time we're

going to close and reopen the terminal

you can tell you have brownie installed

correctly if you run brownie dash dash

version

and you get some output that looks

something like this

or you just run straight up brownie

and it'll output a bunch of commands

that we can run let's create our first

brownie project

we're going to be using the exact same

simple storage code that we just went

through except for we're going to use it

in brownie this is going to make our

lives a lot easier when working with

simple storage to create a sample folder

with everything we need with brownie we

can just run brownie

init

and we will get a new brownie project

initialized in the directory that we're

currently in

if you type ls you'll be able to see all

the folders that are created or you can

just see them on your side panel in vs

code let's talk really quickly about

what each of these folders is going to

do the build folder tracks a lot of

really important low-level information

it's going to track any interfaces that

we're working with or deploying it's

going to keep track of all of our

deployments across all of the different

chains so we no longer have to manage

that ourselves

and it's going to store all the compiled

code remember how in our simple storage

code we actually saved everything to

this compile code.json well brownie is

actually going to do all of that for us

into this contracts directory so we can

always reference it later this contracts

directory outside the build folder is

where we're going to put all of our

contracts brownie knows to look inside

of this folder when looking for new

contracts to compile deploy or anything

else interfaces is where we can save and

store different interfaces remember how

when we were working with chain link

working with interfaces makes it really

easy to interact with a blockchain

application reports are to save any type

of report you run scripts or we can

automate tasks like deploying calling

different functions or really anything

we want and then we have a test folder

which is incredibly powerful and we're

going to be using a lot we also have git

attributes and get ignore which are

helpful when working with version

control like git so let's go ahead and

start working with brownie and really

understand what's going on here so let's

go ahead and add our simple storage

contracts to the contracts folder so in

here we're just going to make a new file

we'll call it simple

storage.soul and i'm just going to copy

and paste the code i have

from the simple storage that we've been

using this whole time let's go ahead and

save that with command s okay great now

that we have our contract in here we can

already start working with brownie and

even compile this code without even

having to write or work with our own

compiler all we need to do

is run brownie

compile

brownie will automatically read the

version of solidity and then store all

of the compile information in this build

folder so if we go to contracts we can

see we have a simple storage.json and

there's a lot of familiar pieces in here

for example we see the abi opcodes

section which is the low level language

we'll see a pc map and we'll see a lot

of useful information and great

obviously deployments and interfaces are

still empty so great we've already

compiled our smart contract so why don't

we actually deploy this to a blockchain

to do this we do have to write a script

which will allow us to do whatever we

want so we're going to create a new file

and we're just going to call this

similar to last time deploy dot pi this

is where we're going to define working

with and deploying our code brownie can

run scripts by running brownie run in

fact if you want to take a quick minute

to familiarize yourself with all the

different commands that brownie has just

run brownie and you'll see we can do a

lot of different things we do brownie

init which will create a new brownie

project we will do brownie bake which

allows us to pull from the brownie mix

which we'll talk about later we can

compile we can go into a console test

run we do a lot of wonderful things in

here if we do brownie run it'll run a

script for us and we can define that we

want to run this deploy all we have to

do is add a def

main

so def in python is the way to define a

function we're going to call this

function main and for now let's just say

print

hello

and we can run

brownie

run

scripts deploy

and as you can see it automatically does

this launching thing

so brownie defaults to always working

with a local ganache cli blockchain it's

running the exact same command that we

ran earlier and it has a bunch of

different flags like accounts 10 a

certain hard fork a certain gas limit

etc so at the beginning of all of our

scripts if we don't give brownie a

network to use it'll spin up a local

ganache and at the end of the script

it'll tear it back down typically what i

like to do is actually put all the logic

of our deployment in its own function

def

deploy

simple storage

and we'll do pass for now and then our

main function we can just call

deploy symbol storage now in order to

deploy our contract let's look back at

our web 3 pi version of deploying this

and see what we did so first we compiled

it great brownie does that automatically

then we jumped into a file great brian

does that automatically

we got a byte code and an abi

great brand does that automatically we

added a local blockchain to use great

brownie automatically spins up a local

ganache we'll learn how to do test nets

in a little bit aha we do need an

address though and a private key so how

do we actually get our private key get

our account into brownie brownie has an

account package that actually natively

understands how to work with accounts

and we can import it into our script

here so we can do from

brownie import accounts

and with this accounts keyword

we can add an account a number of

different ways if we're going to work

with our local chain as you see here the

ganache cli will spin up 10 fake

accounts for us and brownie

automatically knows that we can work

with that account so we can do something

like account equals account zero and

then just do something like print

account so we're going to take the

account that's spun up at the zerowith

index because this accounts object is

just an array so if we run this now

brownie

runs scripts

deploy

it's going to spin up us an address and

a private key that we can just work with

without having to define a private key

or do anything it does all of that for

us which is fantastic we do of course

still want to know how to add our own

private keys so that we can work with

the test net so this is great and works

when we're working with a development

network or working with brownie's

automatic ganache cli if we want to work

with a test net though we have to do

something else another way to add your

accounts in brownie is to use the

command line and actually add them

natively into brownie we can do brownie

accounts

new and we'll give it a name free code

camp account

this will then prompt us and say enter

the private key that you wish to add

let's go ahead and grab our private key

from metamask account details export

private key

put your password in

grab the private key and then we just

add ox and paste it in

brownie will actually password encrypt

your private key in this way

so we'll give it a password and now we

have a new account natively integrated

into brownie to see it we can do brownie

accounts list and you'll see that we

have a free code camp account with this

address and also a testing account i

made this a little bit earlier we can

get rid of it

by running brownie

accounts delete

testing helpful terminal tip time so if

you hit up or down on your keyboard you

can actually toggle through the history

of the commands that you've written so

if you hit up it'll actually bring you

to the most recently run command which

can allow you to run previous commands a

little bit faster and if we run browning

accounts list again

we'll see it's now just free code camp

if we want to work with this free

codecamp account that we've added to

brownie via the command line

we can get it with account

equals accounts dot load

free code camp account

and then we can do print account let's

run this script again

this time when we on the script it's

going to ask us for the password we need

to enter the password to decrypt the

account because right now it's password

encrypted so we're going to type in the

password and it's going to go ahead and

execute with our unlocked private key we

can see the address it printed out was

right here

and if we copy the address and we go

back we can see that that is correct

now if we're going to talk about safety

and you want to safely secure your keys

this is one of the safer ways to do it

because it's not going to store it in

git

you're not going to accidentally push it

up to github or show it to anybody and

it's going to be password encrypted this

is going to be one of the ways that i

highly recommend you store your keys

oftentimes you're going to want to do a

mix of working with the local ganache

ones and your own keys and we'll learn

how to flip back and forth between them

in a little bit now the third way that i

like to use is still again using an

environment variable script oftentimes

it's really easy just to have your

private key be an environment variable

this way you won't have to keep putting

the password in every single time you

run a script so it's a little bit less

secure and just another tip for myself i

never put my private keys associated

with wallets that have real money in

them as environment variables or in a

env file just in case i accidentally do

something really stupid i don't trust

myself enough so i'm gonna highly

recommend that whatever private key that

you use and you store it as an

environment variable here always have it

be just kind of a test account that

you're gonna use to test things and then

for some of your more serious accounts

that's what you'll use the encryption

for so let's go ahead and create an

environment variable file

so we'll do a new file call it env

and we'll do export

private key

ox this

now we have a private key set as an

environment barrel so brownie has an

additional feature that allows us to

easily work with environment variables

in an environment variable folder we can

tell brownie to always pull from our env

file in a brownie config

yaml

this is a special file that brownie

always looks for to grab information

about where you're going to build where

you're going to deploy and where you're

going to grab things in this config all

we need to do is add env

and set dot env this is telling brownie

hey when you run scripts grab the

environment variables from the dot env

file and what we can do is after we

import os we'll do account equals

accounts dot add os dot get env this is

how we get that environment variable a

private key then let's just print out

that account see if we did it right

brownie run

scripts deploy.pi

and great

all right great so this seems to work

perfectly but i like to make this method

even more explicit so we're going to

take this version that we just learned

and improve it in our brownie config we

can actually add more information about

what wallets we want to use and when we

want to use them

what we can do

is we can add a wallets section

and add in here a from

key section

and then add that environment variable

private key in your yaml file if you

surround a string with dollar sign and

some curly brackets it will

automatically get transformed into the

environment variable so if we go back to

deploy we can actually change this we

can grab right from our config file so

we'll do from brownie import accounts

config

instead of using os

we can do accounts

dot add

config

and then we'll do wallets

since that's what we're defining right

here

and then from key

wallets

from

key

and this will do the exact same thing as

our os dot get emv

the reason that this is better is

because now we have one canonical place

where we're always going to pull our

private key from instead of having to go

through all of our scripts and update it

based on whatever we change an

environment variable now let's try this

out

brownie run

scripts deploy

and great we see our address printed

here

for now let's just stick with using

accounts zero since we want to just use

the account that brownie makes for us

with ganache now brownie is really

intelligent and we can actually go ahead

and import

a contract directly into our script and

a web3.pi version we opened a contract

and read from it and that's how we were

able to interact with it after we

deployed it in brownie what we can do is

from brownie

import

and then just the name

of the contract simple storage then

we can do simple storage

dot deploy and this is how we're going

to deploy it to a chain anytime you

deploy to a chain or you make a

transaction you always need to do a from

and then say who you're going to be

deploying from what's the account that's

going to be deploying this as you can

see

this step of just deploying is

much quicker

than what we did in web3.pi in web3.pi

we had to

get the byte code and the abi then we

had to get the nuns

we had to create the contract we had to

create the transaction

sign the transaction and then send the

transaction remember how i said before

you could either make a transaction

or a call brownie is smart enough to

know whether or not what you're doing is

going to be a transaction or a call

in this case since we're deploying a

smart contract brownie's smart enough to

know that ah we want to make a state

change so let's make a state change

it'll return a contract object

so we can just add print

simple storage and we'll see what prints

so let's run this brownie run scripts

deploy.pi

awesome so what happened was brownie

again per usual it launched a local

ganache chain

and then it sent a transaction to deploy

simple storage

and it says simple storage deployed at

and then the address it was deployed at

and we can see how much quicker this is

to actually deploy now let's go ahead

and do exactly what we did with web3.pi

let's call this initial retrieve

function and then we'll update it with a

new value of 15. but we'll do it in

brownie now

remember here's how we did it back in

web3.pie in brownie what we're going to

do is first we're going to do

stored value

equals

simple storage

dot retrieve now since this is a view

function we don't have to add from

account in here again brownie is

intelligent enough to know if this is a

call or transaction and we know that

retrieve is

a view function so we know we don't

actually have to make a transaction here

then we can print out the value of

stored value

print

stored value

let's go ahead and try this

great we get 0 right here perfect

now let's try updating this so we can do

transaction

equals

simple storage

dot store

and in here we'd want to do 15. but

remember since we're doing a transaction

in brownie we always have to add who

we're going to transact from

in this case we're going to do from

account similar to web3.pi we can do

transaction.wait

for how many blocks we want to wait and

then let's call that retrieve function

again to see if it's been updated

so we can do updated

stored value equals

symbol storage dot retrieve and then we

can print

the updated stored value

and if we run this

we now see we have two transactions here

one that deployed our original simple

storage contract and we called the

retrieve function and we returned zero

here

then we updated with our store function

and then we called retrieve again and we

see we did indeed update it to 15. you

see how much smaller and easier and more

intuitive this is in brownie and how

much our lives are going to be much

better awesome now you've learned how to

deploy to a local chain now running

these scripts is fantastic but we need a

way to actually automate that our

contracts are doing what we want them to

do we don't want to always have to

manually check that all of our stuff is

doing what we want to do right we don't

want to have to manually check that 15

is actually updating appropriately this

is why running tests are so important

and automating your tests is going to be

crucial to becoming a successful smart

contract developer now i do want to

point out that you actually can write

tests directly in solidity and this is a

great way to actually test your smart

contracts is to learn how to do it right

in solidity however a lot of the

professional developers code their tests

in the smart contract development

framework language like python or

javascript doing it in this way allows

you to get a lot more flexibility and

customization with what you're doing

with your smart contracts and not being

confined to whatever only solidity has

so let's go ahead and learn how to

actually write our smart contract tests

in python this is what this test folder

is for so we're going to create a new

file called test

simple storage

dot pi

make sure you do add tests to the front

of these because this is the syntax that

pi test is going to be looking for and

then in our test we can actually set it

up the exact same way we set up our

deploy function we can do from

browning

import

simple storage

and accounts

then we can start defining our tests we

want to test to see that when we deploy

our smart contract that it gets started

off with zero in that retrieve function

so we'll create our first test we'll do

def

test

deploy and typically

testing in smart contracts or testing

really in anything is going to be

separated into three categories

arranging

acting

and asserting we're going to bounce

around and be a little bit loose with

this definition for the duration of our

tutorials here however keep in mind that

typically this is the setup that you

want to use later on in one of our later

smart contract examples we're going to

go through a much better testing setup

so in our arrange stage we're going to

set up all the pieces that we need to

get set up

so first

we're going to grab an account

we're going to say accounts equals

account zero and this is really all we

need to do to start getting set up now

for our acting stage we're going to

deploy

a simple storage contract

exactly as we did with deploy

so we do simple storage

equals simple storage dot deploy

from

account then we're going to get our

starting value

starting value

is going to be equal to

simple storage dot

retrieve and we're expecting

[Music]

this to be zero

so then all we have to do in our search

sage is we have to run assert

starting value

equals

expected so let's recap this in our

arrange stage we're just getting our

account so that we can actually make

contracts then in our x stage we're

going to deploy this simple storage

smart contract we're going to call the

retrieve function to see what its

starting value is and we're going to

compare to see if that starting value is

what we expect and we expect it to be

zero we can then test this with brownie

test

and per usual brownie is going to kick

off a ganache lie

and then it's going to test this

for every test you have you're going to

get a little green dot and we're going

to say one pass in 1.86 seconds which is

perfect if we had expected to be 15 and

we ran brownie test we should get a fail

here

awesome and that's exactly what we got

now let's go ahead and test updating

this with 15 and see if it works as we

want it to so we can do a new test in

here

we'll do def

test

update thing

storage

and we'll do those three phases

arrange

act

and assert in our range all we need to

do is get our account

from account zero and in this one

arranging is also going to be deploying

our smart contract

since this is really just part of the

setup and not the act that we're really

testing now in our act we're going to

add expected

to be equal to 15 and we're going to run

simple storage

dot store

expected

and then from account

you'll notice this is nearly exactly the

same as this deploy function here

now same as last time all we have to do

is assert

expected

equals equals

simple storage dot

retrieve we're saying we want to store

15 in our smart contract and then when

we call our retrieve function it is

stored correctly so let's go ahead and

run

brownie test

awesome we can see two dots here this

means two have actually passed correctly

that's great now i do want to quickly

show you a couple of useful tips that i

pretty much always do when i'm running

my tests if you want to test just one

function you can do dash k

brownie test k

test updating storage and we will only

test this test updating storage we can

run brownie test dash dash pdb

and add something wrong in here like

five equals simple storage dot retrieve

and what will happen is once this kicks

out and is wrong will actually get put

into a python shell and now we can check

to see some variables in here like if i

see what expected is expected is 15.

if i try to run

simple storage.retrieve expected is 15.

if i run simple storage

i'll see this is the simple storage

contract

pdb is a really useful way to mess

around and see okay well what did i

really go wrong why is my test failing

another important flag is going to be

dash s

so you'll notice that no print lines

actually get sent out when you're

working with these tests

if you do dash s

it'll be a little bit more robust and

telling you exactly what's going on and

if we had any print lines it would print

the lines out as well everything that

you can do with brownie test actually

comes directly from pi test so if

there's some flag you want to use or

some awesome debugger you want to use

you can use it with brownie just by

looking at the pi test documentation all

the tools are exactly the same all right

we're coming along fantastically we have

a script to deploy we have some tests we

have our contract this is great but now

we actually want to deploy to a test net

how are we going to do this let's look

at back how we did it with web3.pi back

in web3.pi to deploy this to a test net

we just needed to add our http web3

provider which was our infira account

and that was pretty much it and add our

address and our private key brownie our

lives are even easier brownie comes

pre-packaged with a list of networks

that it's already compatible with you

can see all the networks by running

brownie

networks

list

now mine has a couple more actually

because i've been playing around with

this for a long time but if you want to

see all the different networks you can

look at this list here something

important to note is that there's a

difference between the development

networks

and the ethereum networks whenever we

deploy to a network we default to this

development network any network that you

see under this development section is

going to be a network that is temporary

these are networks such as the temporary

ganache network that brownie

automatically spins up when we've run

any of the scripts we've written so far

so this is really important to know

remember anything in this development

section is going to get torn down

after it's deployed however the ethereum

ones are going to be our persistent

networks anything under this ethereum

tab brownie is actually going to keep

track of our deployments and keep track

of everything in there these networks

under here represent persistent networks

like mainnet rink b coven etc now in our

web3.pi we used an rpc url or an http

provider from infira to connect to a

testnet we're going to use that exact

same methodology here so how do we

actually get this rpc url this

blockchain url into our brownie smart

contract package well one of the easiest

ways is with an environment variable so

brownie actually already knows that

infuria is thing and can look natively

right away for inferior web 3

infuria

project id

and use our project id from infira if we

go to our project back in inferior

and we go to settings

you'll see the project id is a little

bit different than the whole url it's

just going to be this id right here

we can then copy this and paste this

right into our emv now that we have our

web3 inferior product id directly in our

project

if we do

brownie

networks list any network that infuria

has access to you'll see a little

inferior in colons here these are

networks that brownie will automatically

know about if we're working with

inferior so we can see here that ring b

is one of these inferior keys if we

wanted to deploy to ring b we could then

just run

brownie run

scripts deploy.pi

and then select the network with dash

network

rink b

now we're going to get an issue here

because remember account zero only works

when brownie works with a ganache cli we

have to use our actual private key here

and that's where some of those other

versions of working with private keys is

gonna come into play sometimes i'll even

add a get account function

so down here we'll do def

get account

and then in here i'll just natively

check if we're working on a development

chain we'll use account zero

and if not we'll use the method that

pulls from our config so we can check by

saying if

network

does show active

equals equals

development

then

return

accounts 0. network is another keyword

that brownie actually has

this network keyword allows us to

interact with different networks

now if it's not on the development

network we're going to pull directly

from our config

so we'll return

config

wallets

from key

and instead of doing account equals

account zero we can just do account

equals get account

now if we run brownie run scripts deploy

to pi network ringby it should pull

directly from our

config

file and great we can actually see

transactions being sent directly on the

rinkby chain

if we pull up ether scan

the ring be ether scan and we take this

transaction has and post it into the

bring to ether scan we can see this

transaction actually going through we've

deployed our simple storage contract and

it's initialized to zero

then we're going to go ahead and update

it and it gets updated to 15. now once

we've deployed to a blockchain

you'll see our build contract will

actually change

our deployments folder will have a new

deployment every time you deploy to a

blockchain brownie will actually save

that deployment so you can always go

back and say hmm where did i deploy that

or what happened with that deployment

you'll notice that it's separated by

chain id remember the chain id ring b is

four you'll also notice that none of our

development deployments are in here

again anything that's in this

development section isn't going to get

saved to the deployments area however

anything up here

and these ones will get saved and that's

going to be really powerful because we

can actually interact with contracts

we've already deployed onto a chain so

let's go ahead and even add

a new file in here

called

read value this function is going to

read directly from the ring blockchain

and it's going to read from a contract

that we've already deployed remember we

did something similar in web3.pi

by using the address

and the abi

we're going to do the exact same thing

but in brownie so in brownie again we're

going to do from brownie

import

simple storage

accounts

and config

we'll do def

read contract

and we'll just do pass for now

and then def main

is going to be read contract oops didn't

mean to do that down here and if we run

brownie run scripts

read value to pi

network rank v obviously right now

nothing's going to happen so how do we

actually interact with this simple

storage contract that we've already

deployed well this simple storage object

is actually just an array

if we were to print simple storage

let's see what we get

see we get this

brownie.network.contract.contractcontainer

object at here this object works the

same as an array we can access the

different indexes inside of it so what

if we do print simple storage at

position zero

you'll see we get this address here

and if we check on ether scan

we can see that this is indeed the

contract that we just deployed

ronnie knows that we just deployed it

because again

in our build section in the deployments

on the rink b chain which has the chain

id of four

we have this contract that we've

deployed now we can actually just

directly interact with this contract

we can do simple

storage

equals

simple storage of xero or if you're

always looking to get the most recent

deployment

minus one is a little bit easier if we

always do zero we're just going to get

the first deployment that we made and if

we make deployments later we're never

going to get past it

i want to always work with the most

recent deployment so i can just do minus

one remember how i said whenever we work

with a smart contract we need to know

its abi

and its address

well brownie already knows what the

address of this contract is it's got it

saved in this deployments folder

it also knows what the abi is because

when we compile it we get this big json

file and one of the first inputs that it

has is the abi so brownie automatically

knows what the abi is and what the

address is already

so then we can just go ahead and run

simple storage

dot retrieve

and print it out

and we should see 15 since we already

updated it

brownie run scripts

read value to pi dash dash network rink

b

and great we do indeed see 15. now that

we know how to write some scripts and

actually deploy things with brownie and

work with brownie i'm going to show you

one of the most powerful features to

also work with brownie typically we

write our scripts when we want something

to be reproducible and we want to do

something over and over again

deploying simple storage or reading of

value is something that we're probably

going to want to do over and over again

however maybe we want to work with some

of these contracts a little bit ad hoc

and get into a shell where we can

actually interact with these contracts

this is where the brownie console is

actually going to come into play and

make our lives a lot easier

so what we can do

is we're going to brownie

console

and what will happen

is brownie will actually kick us off

into a console it has all of our

contracts and everything already

imported

so if i run simple storage it gives me

back an array it's saying

great that's your simple storage

contract since we're working on a brand

new local test environment there are no

simple storage contracts deployed so

what i can do

is i can say account

equals

account zero

and we now

have

our account that we can work with

accounts is one of these keywords that's

automatically imported into our brownie

console

everything that is imported via brownie

in our script is automatically already

imported into this little shell here so

with that being said we can go ahead and

even deploy our simple storage contract

so we can literally take this line

copy it paste it in here

and you'll see exactly the same thing

that happens as if we ran our script we

get a little transaction hash here and

we get a simple storage

now

if i type simple storage the simple

storage variable now has a storage

contract here

if i type simple storage

you'll see i now have a contract in here

the length

a simple storage is now one because i've

deployed one simple storage contract

if i were to deploy it again

the length is now two

browning now knows i'm holding on to two

simple storage contracts and i've

deployed two simple storage contracts

i can then even do things like simple

storage

dot retrieve

and we can see

we start with zero i can go ahead and

even run

simplestorage.store

15

from

account

and we'll see we'll get a transaction

now if i rerun simplestorage.retrieve a

nice little hack here is in these shells

if you just hit the up key you'll

actually be able to go back in the

history of the shell so if i just hit up

twice here i can go back to this command

and i hit enter now we see the 15 is

here so the brownie console is a great

way to interact with these scripts in a

more ad hoc manner maybe we want to test

some weird functionality or maybe we

have some experiment that we want to try

it's a great way to really interact with

anything that we have in browning and

the other thing is we can do everything

that we normally do in python in here so

for example i could write print

hello

and it'll print out hello i could do

cat equals 1 plus 2

and i type cat and i get 3. so this

brownie shell is a python shell with all

of our smart contract features already

natively integrated and it's incredibly

powerful here

we go and quit it by doing quit so i

know we've learned a lot so far i'm sure

you're starting to see why working with

brownie is so much easier and makes our

lives as smart contract developers a lot

easier for testing them deploying them

and working with them

all right let's move on to our next

project is we're going to take the fund

me contract that we made recently in

remix and actually import that one into

brownie with this we're going to go over

a lot more of the advanced features that

brownie has to offer us and we're going

to get into some more sophisticated

testing and deployment mechanisms for

this so i'm going to make a new

directory

brownie

fund me

we're going to cd

into brownie fund me

and remember if you hit tab it will auto

complete i'm going to open this up in a

folder

again if code period doesn't work you

can always go up to file open folder and

do it like that we're in our brownie

fund me project and we're going to

initialize a new project

by running brownie

init

we're going to create a new contract

called

fundme.soul

this is going to be exactly what we had

before for our fund me contract so if

you have remix up great you can go ahead

and grab it or you can check the github

repository associated with this course

and just copy paste the code

now typically this is where in our last

project we just ran brownie compile

what happens if we run brown and compile

here brownie is going to give us this

error it's going to say hey this source

wasn't found so what's going on here

well remix understands that at chain

links slash contracts is an npm package

that it can import from however

brownie isn't aware of npm packages and

brownie can't actually download directly

from npm however brownie can download

directly from github so we have to tell

brownie where it should be downloading

these external these third-party

packages from so that we can use them in

our contracts here and while i'm in here

i might as well change the global

compiler version to 0.6.6

and we'll just change the compiler

version to carrot 0.6.6 so that our

linter is happy so we need to tell

brownie where to import these contracts

from from github instead of from npm

luckily there is a package out there

specifically created for downloading

chain link contracts the way that we can

tell brownie where to get these from

is in our browning config

so let's create our browning config

in here we're going to create a the pen

then sees section and this is where we

tell brownie the organization

slash repo name

at

version

that we want to download from

so so to get these chain link contracts

we can look up

chain link

brownie contracts

and we can use this repository to get it

so instead of downloading from npm we're

just going to download directly from

this github repo so we need to tell

brownie the organization which is going

to be smart contract kit

the repository name which is going to be

chain link brownie contracts

and then the version you don't always

have to use the latest version here in

fact we can go to the past nine versions

by clicking on the version history we're

actually going to be using 1.1.1

and yes it does look like the latest

version went backwards but as of a

recent release as a 1.2.0 version of

this package all the releases of

chainley brownie contracts is going to

match exactly the at chainlink contracts

npm tag so that's why it looks like this

is an earlier version so we'll say 1.1.1

so great so now brownie knows to

download this repository from github

once we do that everything everything in

this contract section will be available

for our solidity code to import and use

however that's not the final story here

we also need to tell brownie

what this at chain link thing means

because we're downloading from smart

contract kit slash chain link brownie

contracts ronnie's going okay cool well

what's the sat chain link thing so we

need to tell brownie whenever we're

using at chain link we're actually

referring to this import so we need to

tell the compiler this

so let's add a new section we'll say

compiler

when it compiles sulk

we need to remap

at chain link

say whenever you see at chain link here

it means

we're referring to this package

so compiler soccer mappings at chain

link

is equal to this package up here now

let's go ahead and try to compile

perfect we see here that it compiles

successfully and if we look at our build

folder

in the contract section we now have this

new folder called dependencies

and if we even expand this a little bit

we can see

it says dependencies smart contra kit

chain link browning contracts at 1.1.1

and this is what it downloaded from that

github repository it downloaded

aggregator v3 interface and smart math

chain link because we're using both of

those files in our solidity code all

right great so let's write our first

script to deploy this to a development

ganache chain to brownie's built-in

chain

let's do this

so in scripts let's go ahead we'll

create a new file let's go ahead and

build a simple deploy script to work

with rink b and then we'll actually

learn how to deploy this to our own

local ganache development chain so let's

build our deploy script so in scripts

we'll do new file

deploy.pi and we'll start by doing def

deploy

fund me

then we'll do pass for now

and then we'll do our entry point of

deaf main and then we'll call

deploy fund me in this file of course

we're going to do from

brownie

import

fund me

so we can actually use this and let's go

ahead and build this deploy fund me

function so first we're going to need to

get an account

and same as last time we used a function

called get account which would know to

switch back and forth between if we were

on development or if we were with an

actual testnet that we could pull from

our config we can actually once again

copy that function

and use that and use that in our script

here so once again we can use that get

account function that we had before what

i like to do with this get account is

add it into its own file called helpful

scripts

so what i'll do is create a new file

called helpful

scripts.pi

and in here i'll add that getaccount

function right so literally just pasted

it from our last project and just a

quick recap on what this is doing

is we're saying if the network is in

development we're going to use the

accounts 0 syntax otherwise we're going

to pull from our config

and of course we're going to have to

from brownie

import network

config

and accounts

and then of course in our browning

config we're going to have to add

wallets and from key so let's go to our

config

we'll do wallets

from key

and we'll add

our private key environment variable

setup

which of course means that we're going

to have to set dot env

to dot e and v and we're going to create

new file dot amv

and we'll paste

the exact same values from our last dot

emv so it's going to be our private key

and our project id kind of just a lot of

the basics of the setup here

but now that we've added this get

account to its own script how do we

actually use that in our deploy script

depending on the version of python that

you're in you might actually have to

create a new file first named underscore

underscore init underscore underscore

dot pi

you might not but just in case let's

make it here because it doesn't hurt and

with this now python knows that it can

import from other scripts and other

packages

in this project so now we can do from

scripts

dot helpful scripts

import get account so we're importing

that get account function

from our helpful script here and we're

gonna make this get account function a

little bit more robust a little bit

later but for now it'll work perfectly

for what we're looking to do now we can

just run our typical deploy function

funny we'll do the fundme contract

equals fund me

dot deploy

and of course we'll do from

account

because again since this deploy is going

to make a state change to the blockchain

we always need to do a from account

section here then we can even do a

little print

we'll do a print f here

so we'll say

contract

deployed to

fund me

dot address

this is how we'll get the address of our

fund me and great we can even go ahead

and try this out right now remember

you'll need some testing

ethereum in your metamask

brownie run scripts deploy.pi

dash dash network

rank b

and

perfect contract deployed here it is

we can even go to

bring the ether

scan again

and we'd see the contract right here now

this is great and all but if we look at

our contract

it's kind of this blank jarble of

bytes here right nobody can actually see

this contract and and easily interact

with it and we want to make our

contracts easy to interact with what we

can do on etherscan is verify and

publish our smart contracts to verify

our smart contract all we have to do is

hit that verify button

we'll choose our solidity compiler type

which we know is going to be

0.6.6

and we know we're working with the mit

license here

now to continue we would then have to

add in all of the

rest of these pieces we'd have to do

optimization which is going to be yes

we'd enter our solidity contract code

below which importing fund me like this

wouldn't actually work

because etherscan doesn't know what at

chainlink contracts is

so we would have to

copy paste the code

from these imports to the top of our

contract here removing these imports and

copy pasting the code associated with

those files is known as flattening and

this is an important concept for

verifying our smart contracts on

platforms like etherscan

however brownie has a really nice way to

get around this actually what you can do

is go to their main site etherscan.io

you can sign in and sign up and get an

api key i've already signed up so i'm

going to go ahead and sign in here

log in and what we can do is we can go

to my profile

and scroll down to api keys

and this is where we can create an api

key for us to interact with and

programmatically verify our smart

contracts on etherscan i've already got

one here but all we need to do is hit

add

we'll give it a name i'll call it verify

browning continue and we've created this

new api token that will allow us to

verify our smart contracts what we'll do

to use this in brownie

is we'll copy this api key

and we'll move back to our scripts here

we'll set this api key as an environment

variable so we'll do export

the name of this is etherscan

token

and we'll set it equal to that key that

we just got now to verify this all we

have to do then is once we deploy this

contract we'll tell brownie whether or

not we want to verify the contract

so after

our dictionary here

we'll do comma

publish

source equals

true we're saying yes we would like to

publish our source code

now if we rerun this script

let's see what happens again remember

we'll do browning

run

scripts

deployed up high dash dash

network space

rinkaby

and says fund me has been deployed to

here

now we're going to say waiting

for api

rink b dot etherscan.io to process

contract

and we're submitting our code for

verification here and it'll say

verification pending verification

complete pass verified it'll say where

the contract has been deployed and

what's been done with it

now if we go back to ether scan again

we're going to have to go back to rink

be ether scan because we deployed this

to rank b and we paste this in

we now have this little check mark

associated with our contract

and if we click contract we can see all

of the code in here

for our contract

we have contract fund me

payable you need to get more everything

that we defined in here and if we scroll

up we can see that they did indeed

flatten this contract right they

pasted that aggregator v3 interface

import

and they also pasted that library safe

math chain link now that's verified we

can even read the contract see the

different public variables in here such

as the owner get version get price and

all the exact same buttons that we saw

in remix this read contract section is

for all these view functions right the

ones that aren't going to be making a

state change

right contract

is going to be for when we want to call

something like fund or withdraw and we

could even go ahead and interact with

this so for example we could connect to

web3

metamask

okay and it would automatically get

connected to our metamask here then we

could call fund and withdraw just like

we did in remix if you want to give it a

shot go for it all right we're back in

our code editor after successfully

verifying one of our smart contracts on

etherscan now just a quick note

sometimes the verification process can

be a little bit touchy and for version

of solidity 0.8.4 there's currently a

bug that makes it verifying a little bit

tricky but it's being worked on so don't

be discouraged if it gets a little bit

funky so this is great that we've

written a deploy script for deploying

directly to ring b however as you know

we're always going to want to be able to

deploy to our own local blockchains or

or brownies built-in development chain

so we can test a lot quicker and that

yes so that we can write some tests but

we have a little bit of an issue here

the first issue being that our fundme

contract currently has an address

hard-coded to work with the rink be

chain so in fact the way it's written

right now it's going to be hard to work

with any other chain other than ring b

the second bit is that these price feed

contracts don't exist on a local ganache

chain or a gnost chain that brownie

spins up there's two ways we can get

around this we can do what's called

forking and work on a forked simulated

chain

or we can deploy a mock or deploy a fake

price feed contract on our ganache local

development chain deploying mocks is a

common design pattern used

across all software engineering

industries and what it applies doing is

deploying a fake version of something

and interacting with it as if it's real

so again right now if i run brownie

run

scripts deploy.pi and i don't set this

network flag we're going to actually

have a default spinning up a ganache

chain it's even going to try to verify

which it's going to run into an issue

because we can't verify on a ganache

chain so we have a couple issues that we

need to address here in order for us to

get this to work on a ganache chain

similar to how in this get account

function in our helpful scripts

we do a little bit checking we say hey

if we're on a development network

use this development accounts version

otherwise

pull from our config

we can do that exact same mentality but

with working with these marks so the

first thing that we need to do is we

need to parameterize our fund me

solidity smart contract

so that we don't have this hard-coded in

here anymore so what we can do

is right when we deploy this contract

we'll tell it what price feed address it

should use right when we call our deploy

function here instead of having it hard

coded

and we can add this parameter to our

constructor we'll say

address

price feed

as an input parameter and whatever input

parameter we use here is going to be our

global price feed address so instead of

us creating

these aggregator v3 interface contracts

right in the functions here we're just

going to create a global one so we'll

say

aggregator

v3 interface public

price feed

and right in our constructor

right when we create this we'll set

price feed

equals

aggregator v3 interface

price feed

and now what we can do is we can just

delete this part because as you can see

this is doing the exact same thing

is up here this is doing aggregator v3

interface price feed equals aggregator

v3 interface and then the address here

and we're going to do the exact same

thing but in our constructor meaning

right when we deploy this contract so we

can delete this

and we can delete it here as well in our

get price function we can even verify

this with brownie

compile

great looks like it's compiling

perfectly

now

our deploy function is going to need to

look a little bit different we're going

to need to pass

the price feed address

to our fund me contract to do this all

we'd have to do is paste

that address before we have our from

account variable here

so this is how you can actually pass

variables to constructors anything

inside this constructor function you can

pass through brownie in our deploy

script here so great so we could 100

always just pass this rink b address

here but that's not really going to

solve our problem obviously right the

problem is that the problem right now is

that we always have this ring b address

when we say if we are on

a persistent network like rink b

use the associated

address

otherwise

deploy mocks and i know we've been

talking about mocks we'll get into them

in a second but let's first set this one

up here so we can check what network

that we're on again by importing from

browning this network bit and we can say

if

network dot show

active

does not equal

development then

we'll say price feed

address

equals

this address here and we'll just pass

this price feed address now this still

doesn't solve our issue because we're

just always passing this the rink be

hard-coded piece here so what we want to

do is parameterize where we get these

addresses from so instead what we can do

is in our browning config we can add

different addresses for different

networks so right underneath our dnv

we'll add a new section called networks

and we'll do one called rink b and we'll

say the fusd

price feed

address is going to be

this price feed address now what we can

do in our deploy script

is we can say

if we're not on a development network

let's grab the address from our networks

section this way we can define

different addresses for this price feed

across different networks so we can add

we could add a coven section

we could add a mainnet section any other

networks that we want to work with all

we need to do is add add these flags for

those contracts so back in our deploy

now we can see the price feed address is

going to get pulled from the config

instead so we'll say config and

this means we're going to import config

or brownie

say config of networks

based off of the network dot show

active

and then we'll use the fusd price feed

flag here

perfect

so this little if statement is going to

say hey if we're not on a development

network

pull the address right from the config

and this will make it so that we can

deploy to really anywhere that we want

to deploy to but what if we are on a

development chain well what do we do

then we can say else if we're not on a

development chain we're going to have to

deploy a mock so right now

on all these live networks that we're

working with there is a version of this

price feed contract this price feed

address our development chain obviously

there won't be one because it's going to

start off as blank so what we can do is

we can deploy our own version of the

price food contract this is known as

mocking and we can interact with it

accordingly in order for us to deploy a

price feed contract ourselves we're

obviously going to need to have the

solidity code associated with it so what

we can do

is in our contract section we'll create

a new folder called test

when you create a test folder in your

contracts folder this is typically where

mock contracts are going to go and we'll

create a new file

called mock

v3

aggregateor dot sol

and this is where we'll add the code for

us to deploy our own price feed now i'm

going to show you another repository

pretty soon called the chain link mix

that we're going to work with

for now if you're looking for one of

these mocks i highly recommend just

pulling it from this chain link mix

repository so we can grab it by going to

contracts

test

and grabbing my aggregator dot soul we

can just copy this whole code

and paste it into our mockv3

aggregator.sol this has all the same

exact functions as a real price feed

contract such as decimals and latest

answer which are going to be two of the

ones we use the most we can also see its

constructor here

these are the variables that it takes

whenever this contract is deployed

it takes a decimals and an initial

answer decimals is of course going to be

how many decimals that this contract

should have an initial answer is going

to be its starting value like 2000 for

example once we have this contract in

our test section we can of course run

brownie compile and brownie will go

ahead and compile this mock v3

aggregator as well because remember

brownie compiles any contract in this

contracts folder let's go back to our

deploy script now that we have this mock

v3 aggregator in here now we can do is

we can do a little else here

saying okay well if we are on a

development chain let's do something

let's deploy these mocks so let's do a

little print statement here a little

printf saying

the active network

is

we'll do network

dot show active

another print statement print f saying

deploying

mocks dot dot dot oops i need a little

closing there

and this doesn't need to be print f

it can just be a regular print and then

now the same way we import fund me we

can import mach v3 aggregateor

we can just deploy this contract the

same way we deploy all of our other

contracts so we'll do mach v3 aggregator

dot deploy and as we just learned we

have to add the parameters the

constructor takes which is going to be

decimals and initial answer

so maybe we'll set decimals to 18 and

then maybe we want to set the initial to

answer to 2000 so two one two three one

two three four five six seven eight nine

ten one two three four five six seven

eight comma and of course since we're

deploying we've got to do a from

and we'll use our account here

we'll do another print

saying

mox

deployed and of course we're going to

need to get this mock v3 aggregator's

address so we'll do

mock aggregator

equals this and we'll set

price

feed address

to equal

our mock aggregator dot address

and now we're development or live

network agnostic if we deploy this on a

live network we'll use the address from

our config otherwise we'll use a fake

aggregator contract that we've deployed

let's go ahead and even try this on a

development network

so we can do brownie

run scripts deploy.pi we don't need a

network flag here we'll hit enter it'll

spin up the ganache

and we even will deploy a mock

aggregator contract first

and then we'll do our fund me part of

course we are running to an issue

because we're trying to verify a

contract on a chain that doesn't exist

etherscan doesn't know about our local

gnost chain so to fix this

instead of doing publish source equals

true we can have this published source

be again based on what chain that we're

on so we'll go back to our browning

config and for rank b

we'll say verify

will be true but for development

we'll say verify will be false and back

in our deploy script we now say publish

source

is going to be pulled from our config so

again we'll do config

networks

network dot show active

and then we'll do dot get

verify

this dot get verify

will make our lives a little bit easier

if we forget to add verify in here you

could still do like this

like verify but you run into some index

errors if you forget to actually put the

verify so sometimes i get lazy and uh

it's just a little bit nicer like this

now if we run this again

deploy.pi

we'll spin up our local ganache we'll

deploy a mock price feed contract

and then we'll deploy our fund me

contract

and it completes successfully so this is

awesome we have a way

our fund me contract that uses a price

feed contract to our own local

development environment with a mock aka

a fake price feed contract this is

awesome now this is great but our deploy

script is starting to look a little big

and a little clunky so let's actually

clean this up to make it look a lot

nicer the first thing that we want to do

is we want to fix this this big 2000

number just looking at right away i'm

not exactly sure how many zeros it has

so to make this look a little bit nicer

and more readable we can once again call

on our friend web3.pi from

web3

import

web3

and down here we'll do web3.2

way

2000

comma

ether this two-way function will just

add 18 decimals to this 2000 so now this

is much more readable that the initial

value for this is going to be 2 000. the

next bit is that we're always deploying

this mock v3 aggregator here and if we

already have a mock deployed to whatever

network that we're working on we don't

need two marks here so what we can do

then is right before

we deploy this mock is we can do a

little if statement

we can say if

the length

of our

mock v3

aggregator

is less than or equal to zero

only then will we deploy

this mock v3 aggregator remember we can

check the length of our v3 aggregator

because this v3 aggregator is just going

to be a list of all the different v3

aggregators that we've deployed now

instead of using mock

aggregator.address we can just

use mach v3 aggregator

minus one dot address so we're just

saying okay great just use the most

recently deployed mock v3 aggregator

and then of course we don't we no longer

need to set this as a variable and that

looks a little bit cleaner and we'll

make this a little bit more efficient so

this deploying mox bit though is going

to be something that so this deploying

mox bit though is going to be something

that we're actually going to do

relatively frequently let's even move

this print statement up here so instead

what i like to do is put this whole mock

deploying bit in its own function in our

helpful scripts so let's open back up

our helpful scripts we'll do a new

function called def

deploy mocks

and we'll just paste that code in here

of course this means that in our helpful

scripts we're gonna have to import

mock v3 aggregator we'll also have to do

from web3

import

web3 instead of account we'll just use

this get account function now back in

our deploy script

we just delete this whole part

replace with

deploymox

and then import deploymox from our

helpful scripts

and then we can also delete this import

now let's remove some of these comments

if you'd like this is starting to look a

lot more sophisticated and this is great

because now we have a way to deploy base

off if we're on a live chain or a

development chain and then one more

thing i like to

do so that everything is parameterized

i like to set these as static variables

in the top of our helpful scripts

so i'll set decimals

equals 18

and then i'll set starting

price

equals 2000 and then i'll have

mock v3 aggregator to deploy to decimals

web 3.2 way

to

starting price here

so no so let's say now that i wanted to

deploy this to my own ganache instance

well what we could do is we can open up

our ganache here we'll do quick start

and we'll just quickly create our own

ganache blockchain in our script let's

go ahead and just run this deploy script

again

let's see what happens instead of

brownie spinning up its own ganache here

it says attached to local rpc client

listening ad and then this address here

brownie is smart enough to detect if

you're running your own ganache instance

here and will automatically

attach itself to it knowing that that is

going to be a development environment if

we go to our ganache we'll see

we have two transactions which are going

to be

contract creations we're going to create

a price feed contract and then also our

fund b contract so this is great this is

great for testing quickly and locally

but there is an issue with this for

development networks again brownie

doesn't keep track of those so in our

build folders if we go to deployments we

only are saving stuff from the rink b

chain here so we would need to tell

brownie hey there's another network that

we want you to work with and we want you

to remember the deployments to that

chain so what we can do is we can add a

new network to our browning networks

list remember

in brownie

networks list we have all these

different pieces in here these are the

ones that brownie is going to not

remember and these are going to be the

ones that brownie remembers so let's say

we want to deploy to a grenache chain

and we want brownie to remember those

deployments well we can add a network

here and this is going to be how we add

any blockchain that we want any evm

blockchain like avalanche like polygon

etc to add a new network to the brown

networks is we'll run

brownie

networks add

we'll choose development or ethereum

we're going to choose ethereum because

we want this to be a persistent network

we'll do ethereum

we'll give it a name i'm going to call

this ganache

local

we need to give it a host

aka an http address which

we know

is right here

and then i'm just gonna

make this lower case

and then a chain id

which for this we know is one three

three seven

hit enter

now if i do brownie networks list i see

a new blockchain called ganache local

and this is going to reach out to our

ganache ui or our ganache command line

depending on what we're running now just

a note we are going to be deploying to

this ganache ui or ganache cli

a lot for the rest of this lesson so

please keep your ganache instance

running now what i can do

is i can run brownie

run scripts deploy.pi

network

ganache

local let's see what happens of course

we run into our first issue ganache

local isn't development so it's going to

go ahead and try to pull from our config

file we don't want this we want to

actually deploy mock for our local

ganache if a mock hasn't been deployed

so what we can do

is we can extend our definition of what

a development environment is in our

helpful scripts we can add a flag in

here we'll say local

blockchain and vi romance

equals and this will be a list we'll say

development

of course will be one but we can also

say

ganache

local

will be another and now we can import

this local blockchain environments into

our deploy so from at the top from

scripts.helpful scripts

do a comma here

paste that and save

mine gets reformatted which is really

nice and instead we'll say if

network.showactive

not in

local blockchain environments

then go ahead and pull from the config

what this is saying is it's saying if

whatever network that we're on if it

isn't development

or ganache local

then go ahead and use a config

if it is one of these two

we're gonna go ahead and deploy a mock

here now that we have that let's try

this again ronnie run scripts

deploy.pi dash dash network

ganache

local and we run into a different issue

we're saying hey you don't actually have

enough gas well

why is this let's look at our get

account function aha this one is also

looking directly for this development

chain this one will say if

network.showactive

is in

local blockchain environments then

return accounts zero so we're saying if

the network we're working on is

development

or our ganache local then just return

accounts zero so let's try this okay

we're getting closer now we're running

to this key error of ganache local

well we do know how to fix that as well

in our config we'll add this new network

we'll say ganache local

and we'll set verify

to false so let's try this one more time

perfect now mocks have been deployed and

our fundme has been deployed

and if we look in our build folder in

deployments we now have a new chain id

for one three three seven for saving

these deployments and it looks like in

our ganache chain we have these actually

saved in here which is great now an

important thing to note if you were to

close this or delete this ganache chain

all of your contracts will be lost so

you won't be able to interact with them

again to account for this you can always

delete 1337 and delete the entries in

one three three seven from your map.json

or if you're fine deleting the whole

build folder you can delete the whole

build folder so now that we've deployed

this let's actually write a script to

interact with this so let's create a new

file we'll call it fund and

withdraw

dot pi

and this will be the script we use to

fund and withdraw so let's create a

function called

fund we can say fund me

equals

the most recently deployed

fund me we have to do from

brownie

import fund me we're gonna have to get

an account since we are gonna be making

some state changes and we just have this

equal to get account

and we can do from

scripts dot helpful scripts

import

get account

let's get the entrance fee so we can

figure out how much we want to fund

actually sorry since this is going to

resemble that fusd price feed it

actually only has eight decimals two one

two three four two thousand and one two

three four five six seven eight

the reason we want to do it like this

too

is because

in our get price function we know that

it only has eight decimal places so

we're multiplying it by an additional 10

here

we want to resemble that as well so

we'll do eight decimals starting price

of 2000 with eight decimals here and for

our mock v3 aggregator we're just going

to use those exact values and we're not

going to do the web 3 converting we're

just going to make it exactly those

hard-coded values now we're going to

want to get the entrance fee so i've

gone ahead and actually added a function

called get entrance fee to our contract

to make our lives a little bit easier

here i'm going to recommend that you

take a look at this and then

type it in yourself or you just copy

paste it from the github repository so

that we can use this get entrance fee

because it's just a whole bunch of math

here so back in our fund and withdraw

what we can do then is we can do

entrance fee

equals

fund me dot get

entrance fee

excuse me get interested

and we can even print out this entrance

fee just to see if we're doing it right

but first we're going to want to run

brownie

run scripts

deploy

network ganache local because we changed

our fundry.soul

all right great

and now we can run brownie

run scripts

find and withdraw

network

local

and whoops i need a main function so

we'll do def main

fund in here

and let's rerun this

and great we can see this is the

entrance fee do a little print statement

here printf saying the current

entry fee

is

entrance fee

we'll do a little print saying

funding

and then we'll call fundme.fund

and of course we're going to do a from

account

and we're also going to send a value

of

entrance fee

any low level transaction data that we

want to send with our transactions and

function calls we'll add in this little

bracket piece here let's set up let's do

brownie run scripts funder withdraw

again

and great it looks like it's going

through perfectly

awesome let's also do a withdraw

function for the owner to withdraw

we'll say fund me equals fund me

minus one

do account

equals get account

and then we'll just call fund me

dot withdraw

from

account

and then right after fund is called

we'll have withdraw be called and our

main function here

let's go ahead and try this

brownie run scripts

find and withdraw

network

ganache local

this is our funding script

our funding transaction going through

and then our withdrawal transaction

going through perfect so it looks like

our approximate functionality here works

great and this is a script that we can

run on a main network if we'd like

now again it's still much better for us

to run so now we're going to move into

actually

writing those tests and for these tests

we're going to want to quit our ganache

ui let's go ahead and write some of

these tests create a new file

called test

fund me

dot pi we'll quickly speed through this

test because we're not going to learn

too much new here keep in mind when

we're on this test we're going to want

it to be able to work independent of the

network that we're working on so let's

just keep that in mind let's do a test

just to see if we can fund a withdrawal

so we'll do def test

can fund

and

withdraw

and we'll do basically exactly what

we've done before

do account equals get account

of course

we'll do from scripts

that helpful scripts

import get account then we'll want to

deploy fund me and we can even just use

our deploy fund me script in our

deploy.pi so we can do from

scripts

dot deploy

import

deploy

fund me in our deploy fund me at the

bottom we'll just say return

fund me so that our test can now have

this fundme contract for it to work with

so now we'll say fund me

equals

deploy

fund me

grab the entrance fee

which will be equal to

fund me dot get

entrance fee

and then let's go ahead and fund it so

do transaction equals fund me

dot fund

and we'll call from

account

we'll do value

entrance fee

we'll do tx.weight one

we'll do an assert here we'll do assert

fund me dot address

to amount

funded

it's going to be account dot address

it's going to be equal to the entrance

fee

so we want to check

that our address

and the amount that we funded is being

adequately recorded and then we'll do

transaction two will be fund me

dot withdraw

from

account

tx2.weight

one

and then we'll assert

fund me dot address

to amount funded

account dot address

equals zero

and let's go ahead and run this test so

we'll do brownie

test

and perfect looks like it's doing well

now you may be wondering why sometimes

we use the dash dash network flag and

sometimes we don't in our network

section brownie automatically picks a

default network to use and the default

is always set

to development

however we could set this to be anything

that we wanted we could set the default

to be ganache

local we could set it to be rink b

whatever we want it here whatever you

set for the default in your brownie

config is what the network will be

defaulted to so right now when we run

brownie test this is equivalent to

running brand test dash dash

network

development we can even go ahead and run

that too now we could also run this test

on rink b and we will in a second but

oftentimes we don't want to test all of

our functionality on rink beat and on

live networks because it's going to take

a long time for them to run so sometimes

we only want to run tests

on our local chains well how do we do

that we can use pi tests skip

functionality to do so to work with pi

test we're going to first need to

install it so go ahead and run pip

install pi test to demonstrate this

let's create a test that makes sure only

the owner can withdraw and nobody else

can so we'll call this def test only

owner

can

withdraw

to skip this test if we're not on a

local network we'll first check the

network we'll say if

network.showactive is not in

and yep probably would have guessed it

we're going to pull this local

blockchain environments in from our

helpful scripts so we'll do comma local

blockchain environments

and we're going to say if the network

dot showactive

is not in this list of local blockchain

environments we're going to do pi

test.skip

and say only for local testing

of course we're going to import network

and we're also going to import pi test

now if i try to run

this test here

with brownie

test

dash k

dash dash network rinkeby it should skip

perfect and we do see with this s here

meaning that it's skipped this function

if we run this

with dash network

development

it should go ahead and run this and it

will pass because nothing happens in

this function and it does perfect let's

keep going so now we'll say account

equals get account

we'll say fund me

equals

deploy

fund me

and now let's get a different account

to try to call the withdraw function

so we'll say bad actor

equal and this will just give us a blank

random account

but we do have to import accounts

from about here

now we want to test to see that them

calling this withdraw function actually

reverts them and causes an exception

because if i try to do

fund me

dot withdraw

from

[Music]

bad actor right now

what do you think will happen well that

well we know in our fundme.soul our

withdrawal function has the only owner

modifier so technically only the owner

should be able to call this function

so what happens actually we don't even

need this account get account bit let's

just go ahead delete that so what

happens if somebody else tries to call

this withdraw function well let's go

ahead and test this we'll do browning

test

dash k

test only owner can withdraw

hmm and you can see we're getting this

error here writing

browning.exceptions.virtualmachineerror

revert from this fundme.withdraw well we

want this to happen we were expecting

this to happen so how do we test that we

want this to happen well we just need to

tell our test that we want this to

happen

so first we're going to import from

brownie this exceptions

package this way we can tell our test

exactly what exception we're expecting

to see then we'll say with

pi test

dot

raises

exceptions dot

virtual machine error

fund me

dot withdraw

and then we'll just actually we'll just

copy this line down here

now what this is telling our test is

that if this reverts with this virtual

machine error that's good we're saying

we want you to revert when you try to

call this line so if we delete this line

and hit up and try to run this again

we can see that it now passes and this

is exactly what we're expecting so this

is awesome all right we've learned a lot

of fantastic tools for working with

brownie here now the last version of

testing that i want to show you how to

use is mainnet forking maintenance

forking is incredibly powerful when

we're working with smart contracts on

mainnet that we want to test locally so

let's talk about forking for a minute so

on the left here i have a blockchain

right an example of a blockchain this is

going to be like a test net

like rinkaby

or something like mainnet right this is

going to be a blockchain that we

actually deploy to

now there are a whole bunch of blocks in

here right and there's a huge chain that

we can actually work with all this

information is public information right

this block is going to have like

transaction

transaction

transaction

it's going to have you know each one of

these blocks is going to have a whole

bunch of transactions and all this

information is here in addition to all

these transactions it's going to have

price feed contracts

ave contracts

you know et cetera it's going to have

all these different contracts in it so

hypothetically if it's already there we

should be able to basically copy this

all this whole blockchain and do some

simulations ourselves

and that's exactly what forking does

a forked blockchain literally takes a

copy of an existing blockchain on the

left here and brings it into our local

computer for us to work with we actually

have control of this blockchain since

it's going to run on our local computer

similar to ganache now all the

interactions that we do on this local

blockchain are not going to affect the

real blockchain because it's our local

chain right it's a simulated blockchain

but because it's simulated we can go

ahead and interact with price feeds we

can interact with avid we can interact

with all these different contracts that

are already going to be on chain

maintenance fork is a built-in part of

brownie and also pulls from inferior the

same way it works with rink b and coven

and everything else we can start to

interact with the mainnet fork contracts

the exact same way therefore so we can

take this whole ring big section

copy it

paste it

and we'll just change this fusd price

feed address

to its mainnet address so we'll go to

docs.chain.link

ethereum price feeds

get fusd here

copy that

and we'll paste it into here and we'll

change this to mainnet fork and since

this is going to be a fork of course for

verify we're going to do false

now if we try to run one of our scripts

like brownie run scripts deploy.pi

network

mainnet fork

you'll see we'll actually run into an

issue here it's saying insufficient

funds for transfer in our deploy script

when we do our get account and our

helpful scripts

right now we're using accounts.ag config

while it's from key yes it's going to be

our account which right now has zero

money in it on mainnet so brownies right

away gonna say hey you don't have any

money on mainnet what's the deal so we

need to tell brownie that when we're

working with mainnet fork it should

create us a fake account with a hundred

ethernet however

we don't want it to deploy a mock

because the price feed contracts already

exist so we don't want it to deploy a

mock but we do want it to get us an

account here so typically what i like to

do

is i'll add another variable here and

i'll call it

forked

local environments

and i'll add

maintenant fork in here and i'll use

this now as part of my if statements

so i'll say if network does show active

in local blockchain environments or

network dot show active

in forked local environments then we're

going to go ahead and return account 0.

however

in our deploy.pi mainnet fork is not

going to be in this local blockchain

environment so we will just get our

price feed from our config so now if i

run this maintenance fork again now if

we run this you'll see we'll still get

an error we'll get list index out of

range so brownie's built-in forking

mechanism doesn't actually come with its

own accounts here however it has these

issues so what normally i like to do is

i like to create my own custom

maintenance fork right in browning the

way we can create our own development

custom network is by using the brownie

network's add key so

we do brownie

networks

add

we'll make this a development network

instead of a persistent network

and we'll call this

mainnet fork

dev

to set this up we'll do a ganache cli

so we'll say the command to run this

fork is going to be ganache cli

the host is going to be the same as

always http

dot

colon slash 127.0.0.1

fork is going to be equal to and this is

where we just put https

mainnet

dot infira dot io

v3

slash

web 3

infira

project

id

now don't hit enter quite yet i'm going

to explain a couple things

so this single quote means

run this as is if we run this without

the single quote our environment

variable would get actualized here and

we'd always have to use whatever our

current environment variable is so we

want to have this little semicolon here

then we would do accounts equal 10

this tells brownie for us to set up 10

fake accounts for us we'll give it a

mnemonic

of brownie so we'll say great make those

accounts just have a new monica brownie

and we'll do a port equals eight five

four five now once again don't hit enter

quite yet i do wanna explain one other

thing so this is great for working with

inferior and forking from inferior

however i have to note that performance

wise forking forming fura has pretty

much always given me an issue

so i prefer actually to fork from this

application called alchemy and in fact

if you'd like you could set up all of

your networks to work with alchemy by

modifying them i'm going to go ahead and

sign in here and we're going to give it

an alchemy url instead of an inferior

url so i'm going to go ahead and create

an app

i'm going to call this fund me

demo

description will also be a fund me demo

via development environment on the

ethereum mainnet let's create this we

can now view the details of this we'll

go to view key and we'll copy

this http address

and we'll move back over here and for

forking

we can just

delete

everything next to this fork

and we'll just paste that in here

instead and let's go ahead and hit enter

you'll know you've done this right if

you can see something like this mainnet

fork dev has been added oftentimes in my

example i will actually just delete

maintenance fork

and have mainnet fork dev be my default

for maintenance for but for us we're

going to go ahead and do mainnet fork

dev

so in our config

we're going to change mainnet fork to

mainnet fork dev

so since we're giving this a different

name

that means in our helpful scripts

we're gonna have to have do a comma here

and say mainnet fork

dev all right great now our get account

should return accounts 0 for maintenance

fork dev and it should actually work so

let's run our script again brownie run

scripts

deploy dash dash

network

mainnet

fork dev

and perfect we're running our

maintenance fork dev

and it is running successfully

now we should also be able to test

exactly the same way let's look at our

test real quick

test fund me and see okay cool we're

going to be skipping this one since main

at fork forkdev isn't in the local

blockchain networks but this should work

perfectly and then oftentimes in my

tests here i'll actually do like a

little plus

100 or something for entrance fee just

in case i need like a little bit more

money for whatever reason so now if we

run founding test dash dash network

mainnet fork dev

we'll see that this does indeed pass and

this is awesome so this is fantastic

incredibly powerful project here now

we're going to teach you how to actually

share your code and enter the world of

open source and decentralized code the

way the world works when sharing code

and sharing ideas and collaborating

together is they use what's called open

source git repositories github is an

example of one of these git repositories

that we can use to share our code and

it's one of the dominant ways that smart

contract engineers share ideas and share

code we are now going to learn how to

add our code to github and then we can

even share the code and show the world

what we've built and what we've done

this isn't going to be a full end-to-end

git course however there are some links

in the course repository that will show

you how to work with git work with

github and work with version control so

the first thing that we're going to do

is we're going to come to github and

we're going to sign up for

a service

add our email

create a password

enter your username no now we'll go to

our email to verify it

continue we're going to be working with

some collaborative coding we're going to

choose the free edition and perfect we

are now in github now that we're in

github we're going to create our own

first open sourced repository so we're

either going to hit this plus button

here or create repository let's choose a

repository name for this we'll give it

the same name as our main folder so call

this brownie fund me give it a

description maybe smart contract

application

and we'll hit create repository this is

where we're going to upload our code to

share with the world back in our vs code

now we're going to send this folder to

that repository first thing we need to

do is installing git there are a couple

different ways to install git depending

on the version that you're on we'll put

this link in the description to our

course to actually install git once you

have it installed you should be able to

run git dash dash version

and see a git version here now we're

going to initialize our repository in

here by doing git init

we're going to choose a branch name

we're going to call it main

we'll go ahead and add our username and

email to our git config user dot

name

quotes

free

code camp

video

git config

user dot email

free code

camp

video gmail.com

now we're going to do a couple things to

push all of our code to github here

however remember we do not want to push

our dot env pieces up here so we can do

a couple of things we can a we can go

ahead and delete this of course but we

can also add in our dot git ignore file

a dot env this will help us so that we

don't accidentally push our dot env file

to github we can choose what files we

want to push by doing git

add and then a period and if we do get

status

it will now show us all the different

files that we have staged to push to

github if we look in here we see we have

git attributes git ignore browning

config

fund me some contracts some scripts but

we do not have that dot emv file

if you were to remove dot emv from dot

git ignore and you ran git add dot again

and then we did get status

we now see the dot env in here

we do not want this in here so we can do

git

remove dash dash cached

dot e b

we'll add

dot env

back to our dot get ignore file

and then we'll run git status again and

then we'll run git add period

and then get status

and great we do not see that dot env in

here so that's very good now we'll

commit this by git

commit

minus m

first commit

and now we can add

this folder to our github back in our

github there's a little line here which

even tells us how to do it we're going

to copy this line right here

git remote add origin https free code

camp brownie fund me i'm going to copy

that

paste it in here

hit enter and now we can just do this

second line

git push dash u origin main we'll do git

push dash u

origin main we get an output like this

and if we go back we'll now see all of

our files and folders in here now i've

already added my email and password in

here but instead of this you'll probably

get github asking you for authorization

you can just go ahead and put your

github username in and your password in

there if your username and password

doesn't work you can come into github go

down to settings

scroll down to developer settings

personal access tokens and generate new

token we'll call this f

brownie and we'll want to give it at

least repo authorization here and we'll

hit generate token

and instead of using your password you

can go ahead and use this github token

amazing and you now have your first

github repository

we could even come in here add some

topics

like solidity

chain link

python

brownie

etc so that we know what our file is

about and this is incredibly exciting

now i'm gonna even encourage you

to pop onto twitter and share your

excitement

i just made

my first first

at

thanks to at free code camp

at

solidity

brownie s

at chain link if you want to tag me you

can also tag at patrick alpha c

and pop your repo in there go ahead and

hit tweet the community absolutely loves

hearing about all the fantastic things

people are doing in this ecosystem so be

sure to reach out have fun and engage i

know we've gone over a lot here but

let's talk a little bit about some

testing pieces here

now a big question you might have is

well okay so i learned a ton of stuff we

learned about maintenance forking i

could do stuff on ganache i can use

brownies ganache i can use brownies main

net fork there's

i can do a test there's all these places

to do stuff where do i need to run my

tests the default for every single one

of your contracts is as follows you

always 100

need to have tests that pass on a local

brownie spun up ganache instance that

should be priority number one to get all

your tests to pass on this this means

that you will need to deploy mocks after

that the other place you absolutely need

to have tests or do some type of

development is on a test knob these are

going to be what's known as your

integration test and we'll talk more

about those later so those are the two

places you always need to have tests

development and a test net

i think testing on main net fork and

your own local ganache are optional

testing on mainnet fork can be done and

probably should be done whenever all of

your contracts and all of your

interactions are going to be on chain on

one chain without any external off-chain

components testing on your own local

ganache is really more meant for

tinkering and kind of exploring and

seeing things yourself so that's going

to be the setup here so great now let's

move into our most challenging example

once you pass and once you complete this

example you basically will have all the

tools to be an incredibly powerful smart

contract developer then after that we're

going to show you the chain link mix

package and how to do what's called a

brownie bake to automatically open up

this package with all these scripts and

all these contracts pre-built in this is

going to make our lives substantially

easier and faster for deploying our

smart contracts however let's go through

the process of understanding all the

pieces that are going to be inside of

this brownie mix

are you ready you should be let's get

excited and jump in

okay so let's get into our most advanced

smart contract project that we've made

so far this is going to be the best

example of a full scale application and

by full scale i really mean end-to-end

full suite of our brownie all of our

smart contracts are really solid here

what we're going to want to do is create

a lottery application where anybody can

enter the lottery and a random winner is

selected so let's get to it and let's

get started so first of course

we're going to make new directory

we'll call it smart contract lottery

cd and a smart contract lottery and then

open that folder

great we are now in our lottery

application

so let's go ahead and start a new

project

brownie init we've got our project here

now let's create a quick readme.md

to explain what we're going to be trying

to do here so number one we're gonna say

users can enter the lottery with f

based on a usd fee

so for example let's set the price to be

like fifty dollars and the users

actually pay with ethereum so we're

gonna have to get that conversion rate

number two an admin

will choose

when the lottery is over and then three

lottery will select

a random winner now something important

to note here

is since we have an admin here this

means that our application isn't

necessarily going to be truly

decentralized because we have a single

person chooses when the lottery is over

we could scale this out to have maybe a

dow being the admin or something like

that

or we could have the lottery

automatically open and close based off

some time parameters but for the moment

this is the setup that we're going to

have keep in mind even though this is

much less decentralized it's still going

to be a great use of smart contract

technology so first thing that we're

going to get started with of course is

our lottery contract so create a new

file

called lottery

dot sol and let's begin with our initial

setup here so let's choose our version

pragma

solidity

carrot 0.6.6

and this will be the version that we

want to work with here

we'll do contract

lottery

bracket here now let's think for a

second on what some of the functions

that are going to be what our main

functions are going to be here we'll

probably have a function enter

that'll be public

we'll probably have a function

get

entrance fee

to get the entrance fee of the

lottery we'll probably have a function

start lottery that only the admin can

call this will be public as well which

means we'll also probably have an end

lottery function

and those are really going to be the

main functions

the user can enter

based off the entrance fee we can start

the lottery and then of course we can

end the lottery so let's get started

with this enter function just because

this is most likely going to be the

entry point as we know since we're going

to want them to pay

using this entry function in ethereum

we're going to need to make this

function payable

and in here we're going to need to keep

track of all the different players

everybody who signs up for this lottery

to keep track of all the players we're

going to make

an address

payable

array

we'll make it public call players

and anytime somebody enters we'll just

do player

dot push

message dot sender

however right now we're not checking to

see how much value that they're actually

sending we want to set the price of this

to be at least 50

so we'll say 50 minimum so here we're

gonna have to do a require statement

requiring them to do at least 50

in order to do that we're probably going

to need to have some function to get the

entrance fee to check whether or not how

much they're sending is actually 50

so let's go ahead and make that get

entrance fee function now since we're

just going to be returning a number for

get entrance fee we can probably go

ahead and make this a public view and

have this return

a u and 256.

to get this entrancy we're first going

to have to have stored somewhere what

the entrance fee is we're going to store

this 50 minimum somewhere this is

something we'd probably want to set

right when our contract is deployed so

where can we put stuff like that

well in our constructor we'll do

constructor

public

we'll create a new variable

outside here we'll call it un256

public usd entry fee

in our constructor we'll set usd entry

fee equals

50. now because i like to have units of

measure always in way we'll also do

times

10

raised to the 18th

now we have some usd entry fee let's go

ahead and get this entrance fee as we

know since we're going to try to get a

conversion rate here we're going to want

to use a chain link price feed

so

we can head on over to docs.chain.link

we'll scroll down to get the latest

price

and we can even just go ahead and copy

paste this again

but for the sake of robustness let's

just walk through again how to actually

set this up we're going to need to pull

from the price feed to convert fifty

dollars to fifty dollars in each

so let's go ahead and create an agra

gator v3 interface

internal

f usd

price feed

and in our constructor

we'll go ahead and set this we'll say

fusd price feed

equals

ag redgate tor v3 interface

and we're going to want to grab an

address

from our contract addresses but of

course as you know as we've learned from

last time we're going to want to

parameterize this so we're going to want

to pass the address of our price feed as

a constructor parameter

so we'll do address

price

feed

address

and we'll have our aggregator v3

interface

we passed that price feed address then

of course since we're using an

aggregator v3 interface we're gonna have

to import this

from chain link

so we can just go ahead and copy this

from the documentation

and paste it right at the top

or if you want to rewrite it out

yourself feel free to do so

and of course since we're doing this

import here

new file

browning config.

we're going to want to add this as a

dependency so we'll do d

pendancies

smart contract kit

chain link

browning contracts

and we'll do add 1.1.1 again

and then compiler

sulk

remappings

we'll say at chain link

equals

this right here

we'll pull up our terminal

and we'll try this out do brownie

compile see if we're doing everything

right we forgot an spdx license

identifier

which is just a warning but let's add it

in anyways

spdx

license

identifier

mit i should probably spell me

remappings right

mappings

and let's try to compile again

all right lovely so we at least know

that

we are compiling correctly here awesome

so now that we have a price feed let's

go ahead and set up this entrance fee so

we're of course going to need to get a

price from this price feed so we can

even check the documentation how to do

that

we can call this latest round data

function

so we could copy paste it i'm just going

to go ahead and rewrite it but again we

don't need round id started at timestamp

or answered in round we only need price

so we can go ahead and ignore these

variables on our call

so what we'll do is we'll do blank comma

into price

and then

comma comma comma

equals

fusd price feed dot latest

round data

and this means we're just going to get

the price here now we're going to want

to do a little bit of quick math

typically if we're setting the price at

50

and we have

a price feed of two thousand dollars per

eth

we would just wanna do

fifty divided by two thousand

but of course since solidity doesn't

work with decimals we can't actually

just do this

so we'll have to do

50

times

some big number divided by the 2000 so

we're going to go ahead and do it like

that but first let's go ahead and

convert this price from into 256 to uint

256.

so we'll say

you went 256

adjusted price

equals

you went 256.

you in 256 price

and then

since we know

we're going to be using an ethereum usd

price feed that has eight decimals

let's also just convert it to having 18

decimals as well

so we can also do times 10

raised to the 10th

so now we can have 18

decimals

now that we have this adjusted price

we'll do um 256

cost to enter

it's going to equal

usd

entry fee

times

again we're going to want to times it by

some big number here so we'll just times

it by 10 raised to the 18th

this way usd entry fee

has 18 decimals but it has an additional

18 decimals here that'll be canceled out

with our price feeds and the math will

work divided by price

and then we'll return

cost to enter

now of course since we're doing some

interesting math here it's recommended

to use safe math and use safe math

functions we're going to skip over the

safe map functions here again because in

the newer versions of solidity you don't

really have to use them but i think it's

important to note here that sending this

code this exact code to production would

be a bad idea for at least the reason of

the safe math functions but in any case

we have a function here we think our

math is pretty good but i know for a

fact that my math is usually not very

good so let's go ahead and do some

testing as we code just to make sure our

get entrancy function is working

properly so based off of our last lesson

let's talk about

how do we want to test

this

well we could do a main net fork here

because we're only working with some

on-chain contracts and some math we will

at some point have to do our develop

mint

with marks

and of course our test net

i kind of want to just do a quick and

dirty way so let's try our maintenance

fork just for now just to see if

if this is really making any sense if

the current price of ethereum is 2 500

or this much here

and we want the price of this to be

fifty dollars we do 50 divided by this

and we get

.019 so this should be approximately

what we get for our eat value so if we

were to write a test

test

lottery dot pi

if we were to test this function we

would expect to get 0.019

or in way it'll be 1 9

1 2 3 4 5 six seven eight nine ten one

two three four five six

we expect to get approximately this so

let's go ahead and create a function

that tests us so we'll do test get

entrance fee

and here we'll deploy lottery

and in here the first thing we need to

do is deploy this lottery function of

course so we'll do from

brownie

import

lottery

in order to deploy this we're going to

need to get an account

we are going to import our helpful

scripts from the last project to this

one too so we can get our get accounts

but for the time being

we can actually just use accounts 0 from

brownie so we'll say count zero

let's start with def then we'll do

lottery equals

lottery dot deploy

from

account

and ah of course we have a parameter

here of our price feed address

so we're gonna have to add

some type of parameter here for now

let's just hard code it from our config

and we'll go into our config and we'll

start our networks flag

we're going to be working like i said on

the maintenance fork for this quick and

dirty here

we'll call f

usd price feed

grab the fusd price feed

from mainnet since we're going to be

doing a main net fork here

pop that in here

now we can just say

from config

networks

network dot show active

usd

price feed

of course we're going to need to import

network here

and now we can do our kind of quick and

dirty test we can do lottery

dot

get entrance fee

am i spelling that right get entrance

fee

yes

assert

lottery.get entrance fee should be

greater than

let's just say let's just go down 18

or if we wanted to make sure we're

actually doing this right we'll do from

three import

web three

we'll do web3.2 way

0.019

comma ether

should be greater than

and then we'll

even do

0.018 just to make sure

and it should be less than

0.01

now these numbers are of course going to

be a little bit different for you

and if you want you can go ahead and

skip this part so that you don't have to

do the math but it is kind of nice to do

a quick sanity check saying okay like

based off what things are right now what

would this price end up to be now in our

last section we made a mainnet fork dev

network

i'm going to just go ahead and customize

our mainnet fork the way that we showed

you guys how to do maintenance fork dev

this way you can use accounts and we can

be a little bit more robust here

to do this we're first going to have to

delete brownie's internal built-in

mainnet fork

so we'll do brownie

networks

delete

mainnet fork

maintenance fork has been deleted

and now let's go ahead and add our own

maintenance fork using alchemy

as our ethereum connection

so you'll want to create a new app i've

already created one here called smart

contract lottery

we'll view the key

and this is the http endpoint that we'll

use

so to do this we'll do brownie

networks

add this will be a development chain

we'll call this

maintenant fork

it'll be a ganache cli

the host is going to be our local host

so 127.0.0.1

and the fork is going to be equal to

our alchemy http here

we'll do accounts equal 10 that way we

can use the accounts

do the new monarch

equals brownie

import is going to be eight five four

five

and great maintenance fork has been

added now that we have this here we can

go ahead and run our test

brownie

test dash dash network

mainnet fork

whoops looks like we got a little

compile error on our math here

oops it looks like we're divided by

price when we need to be divided by

adjusted price and we forgot the

parentheses on latest round data

let's try this again

and i put an extra comment in here

let's try this one more time

lovely and it looks like we're forking

correctly

and awesome it looks like our test

indeed passes here

of course we know that we're going to

want to change this because this isn't a

great way to actually test our contracts

here but it can be a nice sanity check

and we know we're going to have to

refactor this as well

for mocks and for accounts

but we'll get to that in a little bit

awesome sanity check complete let's get

back to our contract here

so we are getting the cost to enter

correctly perfect we're getting this

entrance fee what that means we can do

in our enter function we can do require

message.value

it's got to be greater than or equal to

our get entrance fee function

and if it's not

give them an error of not

enough

eath

we have a way for them to enter and we

have a way to get the entrance fee but

we want to make sure that we're not

ending the lottery before the lottery

even starts right or we're not entering

a lottery when a lottery hasn't even

begun so we're going to want a way to

iterate through the different phases of

this lottery and we can do that with

what's called an enum or an enum

according to the solidity documentation

enums are another way to create

user-defined types in solidity

we saw an earlier version of doing this

with a struct enums are a little bit

different in that they're explicitly

convertible to and from all integer

types so what does that actually mean

well

we can have an enum

like this action choices go left go

right go straight and sit still they're

just more readable ways to say

go left is going to be represented as

state 0 go right it's going to be state

1 go straight state 2 sit still state 3.

so for our lottery contract we're going

to want to create

this new type that represents the

lottery state so to do this we'll do

enum

lottery state open

closed

and calculating winner

this means that we have a new type

called lottery state with three

positions open closed and calculating

winner these different states are

actually represented by numbers so open

is actually a zero

closed is actually one and calculating

winner is actually a two now that we

have this new type we can create a

variable of type lottery state so we'll

say

lottery state

public

lottery state

and right when we initialize our

contract here we're going to want to set

our lottery state to being closed

so in our constructor we'll do lottery

state

equals

lottery state

dot closed

now since these are represented by

numbers as well we could also just do

lottery state equals

1

because 1 stands for closed however it's

much more readable to do

lotterystate.closed

now that we have a lottery state

in our enter function we can require

that the lottery state

is going to be

equal to

lottery state

dot open

so we can only enter if somebody's

started this lottery and that's exactly

what we're going to do in our start

lottery function

we're going to do a require in here

that the lottery state

is going to be equal to

lottery state dot closed

we can even add

a failure function here

saying

can't start

a new

lottery yet

and when we do start this lottery we'll

say lottery

state

equals

lottery state dot open

now when somebody starts the lottery

they'll be able to

enter of course this

start lottery bid here needs to be

called only by our admin so this is

where our

only owner modifier is once again going

to come into place we could write our

own only owner modifier or we can once

again use open zeppelin's access control

and open zeppelin's ownable function

instead which is what i'm going to use

here so we're going to go ahead and grab

this

copy this

paste it in

import at open zeppelin contracts slash

access ownable

and of course since we're doing this

we're gonna have to add this dependency

into our config

we're gonna be using

open

zeppelin

open

zeppelin

contracts at 3.4.0

we're going to remap

at

open

zeppelin equals

this

oops

and then we'll say our lottery is

ownable

perfect

now we'll try to compile this

awesome looks like brownie grabbed

everything correctly and we're good to

go great

now we can finally move into our end

lottery function

this is where we're actually going to

choose a random winner here

we only want the admin to be the one to

actually end the lottery so let's add

the only owner modifier here

and let's talk a little bit about

randomness because this is what we're

looking to do now we're looking to get a

random winner here now as you know the

blockchain is a deterministic system

right and this is super ambitious

because that allows us to do all these

smart contracts and have this system

that can actually reach consensus very

easily random numbers are much harder if

let's say you had a blockchain with a

whole bunch of different nodes and each

node responds and gives their own random

value well each node is never going to

be able to sync up and say hey you know

we all agree on a random number what you

could do is you could base the random

number on some other attributes in the

system

but then it's not really random it's

actually going to be pseudorandom so

getting truly random numbers in a

deterministic system is actually

impossible and if you know a lot about

computer science you actually know that

even when you call like math.random in

your javascript what your computer is

really doing is it's looking at some

place in memory grabbing some value and

saying hey this is probably random

enough here go ahead and use this now in

smart contracts especially when working

with any type of financial application

such as a lottery having an exploitable

randomness function means that your

lottery is at risk of being hacked or

destroyed and this isn't even a fairy

tale at the time of recording about two

weeks ago i did a rundown on an exploit

where a protocol used insecure

randomness and got hacked for seven

hundred thousand dollars so i am going

to show you this insecure way first and

the reason that i'm going to show you is

that it is a quick and dirty way to get

a pseudo random number but please do not

use this in any production use cases i'm

going to show you a method that's often

used to teach people how to get random

numbers and then we're going to explain

why it's so vulnerable and not a good

method of randomness and what some

insecure protocols will do is they'll

use a globally available variable and

hash it so in your smart contracts

there's actually a number of globally

available variables one of those as we

saw above

is going to be message.value right it's

going to be the value that's sent with

the transaction another globally

available variable is going to be

message.sender

you can actually see a whole list of

these different globally available

variables in the solidity documentation

here so since there are these globally

available variables a lot of times some

will see something like block.difficulty

which returns the current block

difficulty

now one of these globally available now

one of these globally available

variables is going to be block

difficulty or block dot difficulty it's

the current block difficulty remember

how i said that the time between

different block generation is called the

block time

well you can always keep that block time

as is by changing the block difficulty

over time the harder the problem or the

harder the proof of work algorithm

the longer it's going to take or the

more nodes you're going to need to solve

that problem there's this constantly

recalculating metric called ethereum

difficulty or block difficulty depending

on the chain that you're working on that

constantly changes

so you might think this would be a great

use of randomness right because it's a

somewhat hard to predict number so what

a lot of people do is they think that

hey those sound pretty random let's use

them as a unit of randomness and what

you'll see is you'll see like something

like uint

256 which is

again this hashing algorithm

let's do something like abi dot encode

pact

so i know there's a whole lot going into

this line and let's talk about it

so first as we can see

is that we're casting or we're

converting everything in here to being a

uni-256 the reason that we're doing this

of course is because we're going to want

to pick

a random winner based off of an index

right we're going to want to pick

somebody some random winner in our

players array or our players list

so we say okay whatever number that

we're going to use that's going to be

the index of the winner that we're going

to randomly pick

then they use cache 256 which is again

our hashing algorithm so they hash a

whole bunch of variables together

and they do this abi dot encode packed

api is another keyword

for some low-level work

and they'll add maybe a nunsen they'll

add the message on sender

block that difficulty and block the

timestamp basically what they're trying

to do here is take a bunch of seemingly

random numbers

mash them all together in a hashing

function and then say yeah this this is

pretty random but the issue here is that

the hashing function itself isn't random

the hashing function is always going to

be exactly the same could check 256 it's

always going to hash everything exactly

the same way so we're not actually

making it more random by hashing it all

these numbers inside are the pieces that

actually determine how random it is so

if the block to difficulty is random

then this will be a random method if the

blocked out difficulty isn't random then

this won't be a random method and the

blocked difficulty is not random

difficulty

can actually

be manipulated by the miners

in time stamp

timestamp is predictable

nuns is predictable

aka

transaction number because in this

regard they're using the nuns as some

transaction number

and message.sender

is predictable

when using a random number in this way

the hashing algorithm is always going to

be the same union 256 is always going to

be the same we have a predictable number

a predictable address

a predictable timestamp

and then a manipulatable value

so all this is really doing is giving

the miners the ability to win the

lottery or win whatever lottery that

you're working on

so this isn't going to be an effective

way to get a random number this is an

unacceptable way to get a random number

in our applications yes we do have this

only owner modifier here which means

that we are the ones who are going to

choose when to call this so it is still

centralized in that regard

but let's just teach you the best

practices for working with random

numbers right from the get-go so you

don't run into any issues

i'll explain what this part is doing in

a little bit in order to get a true

random number we are going to have to

look outside the blockchain the

blockchain itself like i said is a

deterministic system so we need a number

outside the blockchain but what we can't

do is we can't use just an api that

gives a random number right if that api

becomes corrupted if they're malicious

if they go down if something happens

etcetera what we need is a provable way

to get a random number and chain-link

vrf is actually that solution chain-link

vrf it stands for chain-link verifiably

randomized function and it's a way to

get a provably random number into your

smart contract it has an on-chain

contract that checks the response of a

chain-link node to make sure the number

is truly random using some cryptography

magic it's able to check a number of the

parameters that the chainlink vrf

started and ended with to make sure that

it's truly random it's already used for

protocols like avagochi

ethercards pool together and a whole

bunch of other protocols as well because

it is a secure reliable truly provable

way to get a random number which is

incredibly powerful in a decentralized

system so that's how we're actually

going to get our random number here so

let's work on getting that

what we can do is we can go ahead and

head right over to the chain link

documentation to actually learn how to

work with one of these let's go over the

chain link documentation just to make

sure that we get it right so if we go to

the get a random number here

we have all the documentation you could

ever want so if you ever get lost or

confused you can always come right back

here to work with it what we're going to

do is we're going to deploy their simple

version in remix version of working with

the chainleaf vrf and we're going to

walk through a minimalistic contract to

see how it actually works in a contract

so once again we hit this remix button

remix pops up and we immediately get

this random number consumer.soul

in our files that we can check out so

awesome so here is our files right here

we can see that this is actually using a

different chain than what we've been

using we've been mostly working with

rink b

but for this demo it's actually on coven

so we can do some work with kovin here

and remember if you do want to stay with

rink b you can always go to this

contract addresses section of the vrf

and grab these addresses to use so

what's going on in this contract how do

we actually use this well as you can see

the first thing that happens is we're

importing some code from the chain link

package and our contract is inheriting

the abilities of this vrf consumer base

contract so we're going to see what

functions we're actually going to use

that are inherited from this contract

and the first thing that we notice is we

can see that our constructor in here

does some weird stuff

it looks like it almost has two

constructors

so what's actually going on here well

let's look at this vrf consumer

base.cell contract in the chain link

github

so we can come to the chain link github

here

we'll go to evm contracts or depending

on when you're watching in this it's

migrating to contracts at some point

we go to evm contracts we'll go to src

so once we're using v0.6 we'll go there

and we'll look at this vrf

consumerbase.sol

as we can see this vrf consumer base

that we're importing has its own

constructor and it takes an address for

the vrf coordinator this is the on chain

contract that actually checks to make

sure our numbers are random and the

address of the chain link token which

we'll talk about erc20s in a little bit

what we're doing is we're also

inheriting the constructor into our

contract

so this is our constructor for our

random number consumer but we can also

use the constructor of the vrf consumer

base

and this is actually how we go ahead and

do that we grab the constructor of the

vrf consumer base and pop it in here

now it's taking two addresses it's

taking the vrf coordinator

and the link token like i said the vrf

coordinator is a contract that's been

deployed on chain that's going to verify

that the return of the chain link node

is truly random and we're going to use

the link token as a payment to the chain

link node for its services and then we

also have a key hash and a fee defined

inside of this constructor as well the

key hash uniquely identifies the chain

link node that we're going to use and

then the fee is how much link we're

actually going to pay to the chain link

node for delivering us this random

number now let's talk about a couple

things here

in ethereum whenever you make a

transaction you have to

pay some eath gas

right or transaction gas

this is to pay the smart contract

platform a little bit of eth for

performing our transaction with a smart

contract with a smart contract that

operates with an oracle we have to pay

some link gas or oracle gas

this is to pay the oracles a fee for

their services for providing data or

doing some type of external computation

for a smart contract the question that

might then follow up is oh okay well how

come i didn't have to pay

when we did this price feeds thing

well for price feeds

somebody had actually already paid

for the data to be returned and if we go

to data.chain.link and we scroll down we

can actually see a list of sponsors here

that are paying to get this data

delivered so they're already paying the

oracle gas to bring this data on chain

for us since no other protocol is

getting a random number for us we're

actually going to have to pay the oracle

gas here now in this contract we have a

function called get random number which

is going to return a bytes 32

and what it's going to do it's going to

call this request randomness function

which is inherited from this vrf

consumer base if we look in here

we look for request

request randomness we can see there's a

function right here

called request randomness this function

is going to send our oracle fee or the

link token

and it's going to call this

specific to the link token function

called transfer and call

this function is going to call a chain

link node now i'm not going to talk now

i'm not going to go into exactly how

it's doing that right now but we will

talk about it in a little bit so we call

this request randomness function

and we send the key hash and the fee

remember the key hash uniquely

identifies the chain link node

and the fee is going to be how much

oracle gas we're going to pay if you

ever get lost on how much to pay or what

the contract addresses are you can

always head over to this vrf contract

section and see where the most recently

deployed

vrfs are how much the fee is etcetera

now here's where it gets a little bit

interesting

getting a random number actually follows

what's called the request and receive

style of working with data let's go

ahead and just try this out and i'll

explain what this means once we see it

now we're going to save the answer to

this random result variable here and

let's just go ahead and try this and see

what happens

so we're going to switch to our injected

web 3 and since we're now swapping to a

new test network this means that we have

to get tested eth and test that link

again

we can always look for the link token

contracts page to find the most

up-to-date faucets so we'll scroll down

we'll find coven

looks like this is the at link faucet

and the test and eat faucet

so here's our kovin faucet we'll just

want to switch from rink b to coven

grab our address

paste it in

send me a hundred test link

here's our transaction

we can see we're transferring

some erc20

we'll take this contract address we'll

add it to our metamask by copying the

address

scrolling down to add token

pasting it in here i already have the

address in here so i'm just going to go

ahead and hit cancel for now

and we'll also want some testnet coven

ethereum which looks like this faucet

has it

so we'll paste the address in here

i'm not a robot and we'll do send me 0.1

test eth and perfect now that we have

some tests on ethereum

and some test that link we can proceed

we're going to make sure we're on the

coven test network

and we're going to deploy

our random number consumer gist here

let's go ahead and hit deploy

metamask pops up we're going to go ahead

and confirm

i didn't explain this fulfill randomness

function intentionally you'll see why in

a second

and great a random number consumer comes

up

let's check what our random result is

right now it's obviously zero because we

haven't got a random number so i'm going

to do something intentionally wrong

because there's a good chance that

you'll run into this at some point

if i hit get random number right now we

see this air gas estimation failed

we have plenty of eath why would this

fail the reason that it's failing is

because the contract doesn't have any

oracle gas so we got that gas estimation

failed because we need to fund this

contract address with some link to

actually get a random number so we're

going to hit this copy button and this

is going to copy the address

and we're going to come into our meta

mask here

and we're going to send

this address we're going to paste it

there

swap to link and we'll send it one link

this is probably overkill

because as you saw

the fee is only 0.1

but we're just going to be overkill for

now

and great now that this contract has

some test net link now we can call this

get random number button because we can

actually pay the chain link node to

actually return our random number so

we're going to go ahead and do confirm

and this is fantastic so we're paying a

little bit of transaction gas to make

this transaction to make this request

and then we're paying a little bit of

oracle gas to make this transaction now

so the transaction

now so the transaction confirmed but if

i hit random result now it's still going

to be zero

so why is that what's going on well

getting a random number like this

actually follows what's known as the

request and receive cycle of getting

data you can read more about it here in

this basic request model in the

documentation so in one transaction we

actually request some data or in this

case a random number and then in a

second transaction the chain link node

itself

will make a function call and return the

data back to the smart contract in this

case the function that we're calling is

fulfill randomness it calls this fulfill

randomness

with byte32 request id which is going to

be the request number of when we call

this

and it's going to return with this

random number called randomness

so after we wait a little bit

if we hit random result now we can see

indeed our random number is in here

again the reason that it's in here is

because we actually had two transaction

occur

one paid by us

when we called get random number and one

paid by the chain link node when it

called fulfill randomness now i lied to

you a little bit technically that vrf

coordinator contract calls this function

and then the chain link node calls the

vrf coordinator function but for

simplicity's sake you can kind of just

think of it as the chain link node

itself is calling this fulfill

randomness function so now that we know

how to do this from remix let's go ahead

and add this to our brownie project

so actually before we even do that we

need to require so before we even get a

random number let's change the state of

our lottery so now we'll do lottery

state

equals

lottery state

dot calculating winner

and while this is happening no other

functions can be called right this will

lock out

nobody can start a lottery and nobody

can enter a lottery while we're

calculating the winner

awesome so now that we know a little bit

more about random numbers and everything

that we're doing here let's go ahead and

try implementing this now

so in our chain link smart contract docs

of course we're going to scroll down

we're going to go to our get a random

number bit here

we can copy and paste all this code as

well

into our smart contracts so the first

thing that we're going to need to do of

course is

import the vrf consumer base code

let's move back over

scroll to the top and we'll just paste

this in at chain link slash contracts

src

v0.6 vrf consumer base and we'll inherit

this into our lottery contract so we'll

say the lottery is vrf

consumer base

and it's ownable let's take a look at

this vrf consumer base in the chainlink

github here

if we scroll down

to the constructor of our vrf consumer

base we can see it takes these two

parameters the address of the vrf

coordinator and the address of the chain

link token

we can use a constructor we can use a

constructor of a contract inherited in

our contract inside our constructor

so what we'll want to do is we want to

come down to our constructor and right

after this public keyword we can add any

additional constructors from inherited

smart contracts

so we'll say constructor and this is our

normal constructor and then we'll put

vrf

consumer base

and we'll add the vrf consumer base

addresses in here

we know that it's going to be a vrf

coordinator address and a link token

address

similar to the price feed these two

addresses are going to change based on

the blockchain that we're on

so it'll probably make sense for us to

parameterize them the same way we

parameterize the price feed address

so in our top level

constructor parameters we'll add

an address

for the vrf

coordinator

and we'll pass this to the constructor

of our vrf consumer base

then we'll also grab an address for the

link token so we'll do address

link

and we'll pass this

to the vrf consumer based constructor as

well

great what else do we need to make this

work well back in the documentation we

can see we need a fee

and a key hash the fee is associated

with the link token needed to pay for

this request

so we'll make a public variable

uint 256

public

fee since this might change blockchain

to blockchain we'll have this as an

input parameter as well

so we'll do uni-256

underscore fee

and in our constructor

we'll do fee

equals underscore fee

we'll set our global variable

to fee

and i need a comma here and no semicolon

here what else do we need

well we need a key hash

the key hash is a way to uniquely

identify the chain link vrf node

so create another one we'll do

bytes 32 public key hash

we'll add this as a parameter in here

bytes32

keyhash

and then we'll say

keyhash equals

underscore keyhash

perfect our contract is coming along

great here

now that we have the main pieces that we

need how do we then request this random

number

well if we scroll down in the

documentation

we can see we have this request

randomness function that we need to call

if we scroll back to our vrf

consumer-based contract this request

randomness function is a built-in

function from the vr of consumer base so

our contract can natively call this

request randomness function right in our

contract and you can see it takes a key

hash and a fee as its parameters

so right in our end lottery function

we can add this function and we can see

this also returns a bytes32 called

request id this return syntax is pretty

powerful

you can actually identify the name of

the variable you want to return right in

your write in your function declaration

so by saying bytes32 request id we're

saying we're going to return a bytes32

variable named request id so right in

our function here

we can do request

randomness

because again that's this function that

we're importing

passing it the key hash

and the fee

this will return

a bytes 32 called request id

so this is actually doing this

and having our function

having our function declaration tell us

that there's going to be a variable name

request id

is going to be exactly the same as if we

did bytes 32

request id equals request randomness now

this function call follows again what

we've talked about as the request and

receive mentality the request and

receive architecture

this means that in this first

transaction we're going to request the

data from the chain link oracle in a

second callback

transaction the chain link node is going

to return

the data to this contract

into another function called fulfill

randomness so again if we look back in

our vrf consumer base we can see it has

this function raw fulfill randomness we

can read some of the comments in here

saying raw fulfill randomness is called

by a vrf coordinator when it receives a

valid vrf proof raw fulfill randomness

will then call fulfill randomness so

there's a little bit of contract tag

going on but it's going to eventually

call this fulfill randomness function

which is going to be what we define in

here

and that's how our contract is going to

know what to do once it gets the random

number back so in our first transaction

we're going to end the lottery request a

random number

and then a second transaction later on

once the chain link node has created a

provably random number it's going to

call a second transaction itself

based off of what we define

we just have to call it

fulfill

randomness

and as you can see it takes a byte 32

request id and a random number so

in here we'll do fulfill randomness it

takes a byte 32

request id

and then a uin256

randomness

we don't want anyone else to be able to

call this function we only want our

chain link node to call this function so

we can return a truly random number

so we're going to make this an internal

function

it's internal because actually the

chain-link node is calling the vrf

coordinator

and then the vrf coordinator is calling

our fulfill randomness

so we'll make this internal so that only

the vrf coordinator can be the one to

call and return this function

and then we're going to give it a

keyword of override this override

keyword means that we're overriding the

original declaration of the fulfill

randomness function our vrf consumer

base has a function fulfill randomness

defined but it doesn't have any

parameters or anything about this

function actually laid out this function

is meant to be overridden by us and

that's exactly what we're doing right

here so in this fulfill randomness

function let's go ahead and define

what's going to happen once we get this

random number back so before we can

process this random number let's just

check to make sure we're even in the

right state so we'll do require

our lottery state is going to be equal

to

lottery state dot

calculating winner

and if we're not in that state

we'll just say

you

aren't there yet

my auto format is is on for this one so

it's uh it's jumping in then let's just

do another check to make sure we

actually get a response so we'll do

require

underscore randomness

is greater than

zero

and if it's not we'll just say random

not found

now we need to pick a random winner

well we need to pick a random winner

specifically

out of our list of players our list of

payable public players so our players

array is just a list of players so it's

like one player one player two player

three player four

and they're each at a different index

what we can do then to pick a random

winner is to do what's called a modulo

function in fact let's even open remix

to do an example of this remix let's pop

open a new contract we'll call it

mod.sol

do pragma

solidity

carrot 0.6.6

we'll do contract

mod

and in here we'll do a constructor

blank constructor

and we'll get a global variable you went

256

number and we'll set it equal to 5. and

we'll go down to 0.6.6

save compile

and you know let's even just get rid of

the constructor

let's now create a function

called do mod

we'll take a un256

mod value

make this a public function

public

view returns

ui 256

and we'll just return

5

modulo

mod value

now let's go to javascript vm we'll

deploy this

we'll go in here

so our number is right now five and

let's learn about how the modulo works

if we have this do mod function

what we're doing

is

the module divides

by

the number

and returns the remainder

for example if we did 5 mod 5 what do

you think we're going to get

so we're going to do 5 divided by 5 and

then return the remainder

well 5 divided by five is one and

there's no remainder there's no decimal

there so five mod five should be what

zero exactly well what's five mod four

then

well four can go into five evenly once

but there's one number left over so five

mod four is going to be

one

five mod three is going to be two five

mod one is going to be zero right since

one goes with everything this is how the

mod function works and it's this little

percent here we can use that mod

function

in our fulfill randomness

with the length of our players so we can

say uint 256

index of winner

is going gonna be equal to

the random number that we got

modded

by the players dot length so let's say

for example we had seven players

sign up and our random number was 22

well we want to get one of these random

seven players so

we would do 22

mod 7.

7 divides evenly into 22 three times

with one left over seven

times 3

equals

21.

difference between 21 and 22

is 1

7 times

4

is 28 so we know this is how we know

we've reached our upper limit so this is

how we can get a random number

based off of the index

now that we have this index what we can

do

is we can say the winner

equals

players

of the index of winner

and just to keep track let's make a new

variable called recent winner at the top

we'll do address

public

recent winner

we'll grab this recent winner instead of

winner we'll say recent winner equals

players and this index of winner here

now that we've got a winner wallet we

want to pay them all the money

gathered from our enters here

so what we can do

is we'll do

this recent winner

dot transfer

the entire balance of this address

so we'll say address of this

that balance

and perfect

we'll transfer them everything that we

have

then of course

we're going to want to reset the lottery

so that we can start from scratch we can

start blank again

so we'll do players

equals new

address payable

array of size 0.

so

we're just resetting players to just be

a brand new array then we're going to

change our lottery state

to being

lotterystate.closed

because the lottery is now complete and

i often also like to keep track of the

most recent random number

so at the top

i'll do a uint 256 public

randomness

variable

and in our fulfill randomness i'll say

randomness now equals

underscore randomness

and perfect we now have a contract here

of course we haven't actually tried it

out but we're assuming that it works

great so you know what this means it's

time to go into testing mode testing and

development mode but let's even just try

to do a brownie

compile first

looks like we have

an issue here

send and transfer are only available for

objects of type address payable

not address oops looks like we made our

recent winner just an address but it

needs to be an address

payable

so let's try browning compile again

and beautiful we at least know it's

compiling so that's a great sign let's

now move into our testing and

development phase as you are starting to

figure out we can ignore these file

import callback not supported bugs and

vs code for now i'm sure the solidity

linter will get better as time

progresses but great so now let's go

ahead and move into actually testing and

working with everything here

so let's go ahead into our scripts

and we'll make a little deploy script

first

let's do a new file

call it deploy lottery that pi

and let's go ahead and deploy our

lottery

so same as always we'll do def main

we'll come with a new function called

deploy

lottery

and then we'll do def

deploy

lottery

and then we'll just have a pass for now

and if we run this

brownie run scripts

deploy lottery.pi

our default network is not defined which

means the default is going to be

development

and we can even

verbose here develop

meant write that in our brownie config

run this

gnosh will get spun up

and nothing will happen because our

deploy lottery function doesn't do

anything right now

awesome the first thing we need always

to deploy a contract is we need an

account

so we'll do account

equals and we've been using this

getcount function for some time that

we've been adding in a helpful script

section so that can pull from a real

test net or from a local development

environment if we like so to do this of

course let's create our new

helpful scripts

dot

pi we'll create our underscore

underscore init underscore underscore

dot pi

so that python recognizes it as a

package

and in here we'll create a new function

f get

account

for now we'll just have it pass

we'll copy this

into our deploy lottery we'll do from

scripts.helpful

scripts

import get account

now this

now this

is what our get account looked like

in our last project

along with that we had

these forked local environments

we also had from

brownie imports accounts

and network and config

to make this look really nice right

let's flush this out just a little bit

more so it's even more robust

right now as we know

we have a way to use

brownies ganache accounts

and we have a way

to use

our environment variables

however there was a third method that we

learned that isn't identified here

accounts.load

and this is with our id

if you still have your account and you

still have all your brownies set up if

we do brownie

accounts

list

you'll see we have a couple accounts

here

we want our get account to be

even more liberal so that if we wanted

to use one of these as well we could so

let's modify our get account script here

a little bit let's first get rid of this

else

and rid of this indent

what this will do is this will be our

default

if nothing that we define prior to this

is defined we'll just default to grab

right from our config which since we are

doing that

let's create our dot env

we'll paste our different variables in

here our private key web 3 and fura and

etherscan token

and in our brownie config of course

we'll do wallets

from key

private key

and now let's flesh this out a little

bit let's add an index

and an id

index equals none

and id

this way if we pass an index to our get

account function we'll just use

an index from this accounts variable

if we pass an id

we'll have

trying to do this accounts.load here so

now let's change this up a little bit

we'll say if an index was passed

we'll just return

accounts

on that index

otherwise if we're doing a local

blockchain we'll just return account to

zero

but if there's an id

we'll return

accounts.load

id

whoops we need to actually move this up

a little bit

so that it's before

our local blockchain checking

so now in our deploy lottery

we could do something like get account

id equals

free code camp

oops and this is actually free code

account

precode camp account let's try one more

time

it's going to ask for our password here

now we have a much more liberal get

account function

so now that we have a count we can

actually deploy our lottery

so we'll say lottery

equals

lottery.deploy

and this is where we're going to import

from brownie

import our contract lottery

and we're gonna have to add in

all these different variables so if we

go back over to our lottery contract

we need to give it a price feed address

a vrf coordinator

a chain link token

a fee and a key hash

now the way we did that in fund me is

that we did it in a way where we checked

to see if we were on a local chain or

not if we weren't on a local chain then

we would just pull our addresses

directly from our config if we weren't

on a local chain though we'd deploy some

mocks and use the address of those mocks

we're going to want to do the same thing

here but let's make our lives a little

bit easier

we can take this whole process and put

it into its own function

so let's make this a little bit easier

mentally the first thing we're going to

need is this price feed address

if we're on a real test net of course we

would just go into our brownie config

and add the address which we will do

we'll add our rink b

network here in a little bit but for now

don't worry about that

but if we're not on a wrinky chain what

we're going to need to do is deploy our

mock

we're going to wrap

all of this mocking and checking into a

single function called

get contract

and we're going to add this function in

our helpful scripts

so let's create this function called get

contract

do def get contract

pass

let's talk a little bit about what we

want this function to do

let's add one two three

three double quotes here and three

double quotes here to start what's

called a doc string this will define

everything about this contract so we're

just going to say

this function

will

grab the contract addresses

from the brownie config

if defined

otherwise

it will deploy

a mock version

of that contract

and return

that mock contract

for the arguments of this chain

we're going to take a contract name

this is going to be a string

and it'll return

a contract

or in particular it's going to return a

brownie

dot network

dot contract dot project

contract

the most

deployed

version of this contract

so for example if we have a mock v3

aggregator contract

it'll do the most recently deployed

version of that with this -1 syntax

now this get contract function if this

is a little confusing to you

again we're going to go over this chain

link mix in a little bit and inside of

this it has a more robust

description of what's going on in this

get contract bit

so you can check that out if you want to

learn more but let's go ahead and

actually define this

so we obviously want a contract name

as an input parameter so let's go ahead

and add contract name in here

meaning that this getcontract function

we'll get something like f

usd

price feed

right

that's gonna be the same as what's

defined in our browning config and from

this name we're gonna get the type of

contract that it is

contract type

and to do that we're gonna have to

create some mapping that'll map the

contract names to their type

so right above we're gonna do contract

to mock

and we're to create a mapping in here

which will map everything out

so

an fusd price feed

is going to be of type

mock v3

aggregator

so

we have to import mock v3 aggregator

from rounding

so now we're saying anytime you see fusd

price feed you know that that's going to

be a mock v3 aggregator if we need to

deploy a mock

so we'll say contract type

is going to equal

contract to mock

of the contract name

now we need to check okay do we actually

even need to deploy a mock

so sure let's check if we're on a local

blockchain

so we'll say if

network.showactive

is in

our local blockchain environments

and we'll skip the forked local

environments because again

we don't need to deploy a mock price

feed address on a fourth local

environment

which say if network.showactive is in

the local blockchain environments

then we'll check

to see if one of these contracts has

already been deployed we'll say if the

length

of contract type

is less than or equal to zero

then we're going to go ahead and deploy

mox

so this is equivalent to doing

something like mach v3

aggregate or

length

we're checking how many mach v3

aggregators have actually been deployed

if none have been deployed we're going

to go ahead and deploy them so

we're gonna have to create this deploy

mox function so we'll do def deploy

mox

and this is gonna be the same as what we

did

in our brownie fund me right it's gonna

be the exact same

so we'll say

account equals

get account

i'm not going to put the prints in here

but you absolutely can we'll say mock

price feed

equals

mock v3 aggregator

[Music]

dot deploy

we'll need to give this some decimals

and an initial value so right above

we'll do

decimals

equals eight initial

value equals two thousand one

two thousand one two three four five six

seven eight

and in our deploy max we'll say decimals

equals

decimals

initial value equals initial value

to deploy decimals and

initial value

of course this is going to be from

account

and for now that's it i'll say print

deployed

all right great so now we have a way to

actually deploy the mock price feed here

so let's go back up to our get contract

function

so we have a way to deploy the mock

if one already isn't deployed

now what we're going to want to do is we

want to get that contract right we're

going to want to get that mock so we'll

say contract

equals

contract type

minus one

right so this is going to be equal to

doing

mock v3r gregator

minus one

this is saying hey let's grab the most

recent deployment of the mock v3

aggregator which is exactly what we want

perfect so this will work

perfectly

for our

development context however we're not

always going to just want to deploy to a

development network we're also going to

want to deploy to testnets

so then we'll say else and this is where

we'll just grab that contract from the

running config for example fusd price

feed so we'll say

contract address

equals config

networks

network.show active

and that contract name

for example again if it's fusd price

feed it'll be fused price feed here

and the way we're setting it up it's got

to be the same as what's in our contract

to mock dictionary here so up here the

way that we did it was we actually got

the contract because we had its contract

type

based off of browning for here we're

gonna have to interact with the contract

getting those two pieces that we always

need which are gonna be the address we

actually have the api from our mock v3

aggregator type right here and we just

got the address so we can create this

new contract type by saying contract

equals contract

dot from abi

and this contract package can be

imported right from brownie

and it has this function from abi

that allows us to

get a contract from its abi and its

address

so we'll just give it a name

we can say contract

type dot underscore name

we do the contract address

and then

the contract type dot abi

so these mock v3 aggregators and all

these contracts

have a dot avi

attribute that returns the api

they also have a dot underscore name

which returns their name so this is

perfect this is how we'll get the

contract otherwise and then at the end

of all this we'll just do return

contract awesome so this is an

incredibly powerful function for us

to get a contract based off of if it's

already deployed as a mock or it's a

real true contract i know there's kind

of a lot here but definitely check the

github repository if you're a little bit

confused on what's going on with this

function and let's

and let's also just deploy this to make

our linter happy why not

yeah vs code's happy now but now that we

have this function let's go back to our

deploy lottery

now we can do a comma get account

and now we have a get account function

so let's go through this again

this lottery.deploy getaccount is going

to get an fusd price feed

if we don't have a mock deployed it's

going to deploy a mock price feed for us

and we're going to return that mock

price feed

however if we're on a test net if we're

on a real network we're going to grab

its actual address and return

a mock contract of it our mock contract

here has all the same functions of a

regular contract so we can just use it

as the same this way we don't have to

adjust this function for whether or not

we're deploying to a test net or to an

actual address the only additional piece

we should put in here just for clarity

is we should add dot address here

because this is going to return the

actual contract and we really only want

the address this is going to make our

coding a lot more robust for

moving between development environments

and test environments and working with

scripts in a really effective manner so

now that we have this incredibly

powerful function let's go back to the

lottery and figure out what are the

different pieces we need in here okay

great we also need a vrf coordinator

so

to do this we're going to go back to our

docs.chain.link

we'll go to contract addresses

and we could do mainnet here but let's

also just set this up to work with rank

b so we'll do ctrl f for rink b

vrf coordinator is going to be this

address right here so we'll copy it

we'll go back

and we're going to have to do

in our config

is we're going to have to add a new

network here for rank b

we'll do vrf core data nato

will be that address right there

and then while we're doing this let's

also get the rink b address for our

price feed so ethereum price feeds

rink b

let's scroll down for fusd

fusd here we go

grab that

enter this will be f usd

price feed

face adder sit here perfect

so now we can do get contract

vrf coordinator dot address of course

we are gonna have to go back to our

helpful scripts

because there's currently no mapping

between what a vrf coordinator is and

what its mock needs to be so we'll add a

comma here

and we'll do vrf coordinator

and we need to get

a mock vrf coordinator well first of all

we don't even have our mach v3

aggregator so let's go grab that as well

so we can grab both of these again i'm

going to highly recommend going to the

chain link mix

going into the contracts here going to

the test folder for these different

mocks because these are already set up

to work with the chain link mix however

you can definitely go into the chain

link github as well

go to contracts

src

0.6

tests

and then look for the different mocks in

here so mock oracle vf coordinator mock

et cetera so we're just gonna i'm just

gonna grab it though from this chain

link mix so let's go to vrf coordinator

mock

and i'm just gonna grab this whole thing

here

so i'll do contracts new folder

test

new file vrf

core

core

[Music]

moc.sol

paste it in here

and then while we're in here we want to

do new file

mock v3 ah

greg

sol

we'll grab this as well

from our chain link mix

again it's got all the functions of a

price feed update answer

latest round etc

vrf coordinator walk has different

functions for actually working with the

vrf coordinator

one of the specific ones in particular

is this callback with randomness that

we're going to use

in our tests so our vrf coordinator is

going to get mapped to

our vrf core

nator mock

which will also import this

from brownie

great and just to double check

everything's working we'll want to run

just a quick brownie compile

make sure we are importing our mocs

correctly and everything is compiling so

it looks like we're good there

all right

so now we have

git contract vrf coordinator dot address

perfect what else do we need in here

we need a link token the chain link

token is of course just another smart

contract so we're going to do the exact

same thing here

get contract

link token

dot address

of course this means

in our config

for rink b

let's add a link token address

we'll go to the chain link documentation

go to

link token contracts

look for rink b

we'll grab this address

we'll drop it in here

perfect now we have it in our brownie

config

we'll also need to add it to our

helpful scripts

so we'll need

a mock link token

which again

we can just go ahead and grab

from our chain like mix here

so we can go to test and as you can

probably see what i often normally do is

literally just copy this entire test

folder project to project

so i'm going to copy this whole thing

create a new file

we're just going to call this one

link token.sol

contract link token perfect

and then in our helpful scripts we're

going to have this be linked token

and of course we're going to import this

from brownie

great git contract link token.address

perfect

what else do we need we need a fee and a

key hash so the fee and the key hush are

both just numbers right these aren't

actually contracts so we don't need to

put this through that get contract bit

what we can do

is just in our config

and our development network

we just add a default for the key hash

and for the fee

i'm just going to set my development key

hash and fee equal to the rink b ones

so to grab

those go to the chain link docs once

again we'll scroll down to using

randomness

contract addresses

we'll look up rink b

we'll grab the

key hash

here which we'll paste in for both

are development

and rink b

and then the fee it says 0.1 link so

we'll just do

that in way here which will be one

one two three four five six seven eight

nine ten

one two three four five six seven

and we'll do this

line for ring p as well

now in our deploy lottery we can just

grab this directly from a browning

config because we're always going to

have this default key hash and this

default fee here for our development

network

so we'll do config

networks

network dot show active

which one's first the fee

fee

of course this means we're going to

grab network from brownie

and also config

then we'll do config

networks

network dot show active

and then of course

our last bit here

from

account

and then additionally as we learned last

time if we want to publish this

we'll do publish

source

equals config

networks

network dot show active

we'll say dot get

verify

and then we'll add this false bit here

what this is saying is get that verify

key

but if there's no verify key there just

default to false this way if we don't

set a verify key in development that's

fine it just won't get verified for ring

b let's go ahead and set verify

to true

so we can actually verify this on the

rigby chain

and then we'll even do a print statement

here

deployed

lottery

all right lovely let's try this out

we'll do brownie

run scripts

deploy lottery.pie we won't set a

network flag so it will go to the

default development network let's try

this out

things are compiling ganache is spinning

up

it looks like we did run into a little

issue here with our our get contract

function

ah of course we forgot to add deploying

these mocks in our deploy mock script

whoops let's go ahead and add that as

well

right now our deploymox only deploys the

mach v3 aggregator

so let's add the rest of our mocks in

here

we're going to need to deploy a vrf

coordinator mock and a chain link token

mark so let's open up those contracts

see what they need

a link token

for a constructor

doesn't have a constructor so we can

just have it be blank

so we'll do

link token

dot deploy

and all we need is a from

account here

and then let's see what that vrf

coordinator mock takes

prf coordinator mock

it takes the link token as an address

perfect

so then when we deploy the link token

here

we'll say link token

equals link token.deploy and then we'll

do vrf

core

donator mock

dot deploy

ploy

and then we'll use the link

token.address

as an input parameter

and then of course from

account

all right so now we're deploying all

three of those mocks right away

let's try this again

brownie run scripts

deploy lottery.pi

ganache is spinning up

perfect

so we can see here that our mach v3

aggregator was deployed

then our mock link token was deployed

then our mock vrf coordinator was

deployed and then our lottery was

deployed with those mocks defined

and we deployed the lottery awesome

now we could 100 percent

go ahead and then run this script on an

actual test net right because our config

is set up well let's write some more

functionality for actually interacting

with this lottery

before we actually do that and then we

can actually just run a script which

will do all this functionality end to

end because again deploying to testnet

takes a long time and we really only

want to do that when we're done and

we're fairly confident that everything's

working well let's even just delete this

here

so now what's the next thing that we'd

want to do here what's the next thing we

want to do in a script here well we'd

probably want to go ahead and start the

lottery so let's write a script that can

actually do that

we'll do def

start lottery

and then here we get our account

equals get account

we'll say the lottery is going to be the

most recent deployment

of the lottery

and we're going to call this start

lottery function here this is indeed

changing state so we do have to make a

transaction

we'll do lottery

let's start

lottery

we'll say from

account

then we'll do a little print and just

say

the lottery is started

and then in our main function down here

we can even call this start lottery

function

so if we run this

again on our development chain

we'll see if everything works smoothly

here okay we did run into an issue and

this is something that you'll see from

time to time

typically the workaround is you want to

wait for that last transaction to

actually go through so we'll say

starting

transaction

equals lottery.start lottery it will do

starting

transaction.weight

1.

brownie sometimes gets a little confused

if you don't wait for the last

transaction to go through

so let's try it again and perfect we do

get this working as intended so that is

really helpful helpful tip if you run

into those weird issues you'll notice

that even when we didn't have this it's

still completed successfully i just got

a little confused at the end

all right cool so what do we want to do

next well we probably want to enter the

lottery let's do def

enter

lottery so how do we enter the lottery

say account equals get account

lottery is going to be

lottery

minus one

we need to pick some value to send when

we call the enter function

right because we need to send that

entrance fee with it

so we'll say value equals lottery dot

get

entrance fee

and just to be safe i usually will tack

on a little bit of whey as well because

sometimes it might be off by like one or

two or something like that so we'll do

lottery. get entrance fee plus you know

maybe something like this which is like

barely anything then we'll do

transaction equals lottery.enter

do from account

send a value which will be value

we'll do tx.weight

and then we'll do print

you entered the lottery

and we'll do this enter lottery bit down

here too enter lottery

we'll run this see if our enter script

is working appropriately

you entered the lottery looks great and

let's do our last function here we'll do

def

end lottery

count equals get account

lottery equals

lottery minus one we'll make a

transaction which will be lottery dot

end lottery

now before we actually end this lottery

we're going to need some link token in

this contract

because remember our end lottery

function

calls this request randomness function

and we can only request some randomness

if

our contract has some chain link token

associated with it so we're going to

need to first

fund the contract

and then

end the lottery since funding our

contracts with the link token is going

to be a pretty common function that we

use let's go ahead and turn this also

into a helpful script

so let's go to our helpful scripts we'll

make a new function

called fund with

link

and let's have this take a couple of

parameters so first we'll want to have a

contract address of course

we'll want to know who we're going to

fund with link we'll set a default

account to being none

so if you want you can send an account

but you don't have to if you don't want

to we'll also do the same thing with a

link token we'll say if you want to use

a specific link token you can otherwise

we'll just grab it ourselves

and then we'll also do a default amount

which we'll set to

1

one two three four five six seven eight

nine ten one two three four five six

seven

which is going to be

0.1 link

so first let's get an account we'll say

account

equals

we're going to do a little clever python

stuff here

we'll say account equals the account

if somebody sent it

if account

so we're saying

the account that we use

is going to be

this account thing if this account thing

even exists otherwise we'll call our get

account otherwise we'll just do our

regular get account function

then we'll do the same thing with the

link token

say the link token

is going to be equal to

the link token

that somebody supplies as a parameter

if

they applied something as a parameter

otherwise we'll just do that get

contract stuff that we did before

of the link token

now that we have this link token

contract from our get contract function

which again is basically the equivalent

of doing which again is doing this

contract up from abi on our link token

pulling from

our config or from our mock now we can

just call the functions on this link

token so we can say our transaction

equals

link token

dot transfer

we're going to transfer token to

the contract address

with a certain amount

and of course we'll do from

account

we'll do tx.weight

and then we'll do print

funded contract

and then we'll even return that

transaction

i do however want to show you another

way to work with this using the

interfaces instead of doing this

linktoken.transfer directly on the

contract we can use this interfaces

section

to actually interact with some contracts

so right now we have our mock link token

in here which is great because it has

all the definitions and all the

functionalities defined in here

sometimes you're going to have contracts

that you don't have everything you don't

have all the functionality and maybe you

only have the interface maybe you only

have some of the function definitions so

we can still interact with contracts

with just an interface because again

that interface will compile down to our

api

so as another way of teaching us how to

actually work

with some of these contracts

what we can do

is we can use we can use the link token

interface basically the same way as we

used the link token contract here so

again i'm in my chain link mix because

there's already a link token interface

in here and this will compile down to a

way that our brownie package knows how

to interact with these contracts

so if you wanted to we could just grab

this

go to our brownie section

we'll do a new file in interfaces

we'll call it link

token interface

dot soul

we'll paste it in here

save my auto format auto formatted here

and what we can do in our helpful

scripts instead

is transaction

equals interface

and we can also just import interfaces

right from brownie

interface dot

link

token interface

and we just need to give it

a contract address so we can say link

token dot address

excuse me we could say

link token

contract equals interface dot link token

interface link token dot address

so this is another way we can actually

create contracts to actually interact

with them

so we saw up here

this contract.from abi which is great

this is another way we can do that exact

same thing so then we can just do

linktokencontract.transfer

contract address

amount

from

account

so this is tx equals

so this is another way to actually

interact with contracts that already

exist you're probably starting to see

that brownie has a lot of built-in tools

that make it really easy for us to

interact with contracts if we have the

api we can just pop it into

contract.from avi and again with the

address and the api and then just give

it some name if we have the interface we

don't even need to compile down to the

api ourselves because brownie is smart

enough to know that it can compile down

to the api itself and we can just work

directly with that interface which is

incredibly powerful for now

i'm going to comment these two lines

though and we'll just use the

linktoken.transfer for now now that we

have a funding script or a funding

function we can import this from our

helpful scripts

from scripts.helpful scripts import get

account get contract

fund with link

and we can just call in our end lottery

function

we'll do fund with link

and parameters we just we only really

need a contract address because the way

we set this up we'll just automatically

grab a default otherwise so we can say

lottery dot address

and that's it that's all we need and

then i know we're doing tx.weight right

in the fund with link but just for to be

verbose here

we'll get the transaction from the fund

with link and we'll do tx.weight here as

well

and then once we're funded with link

then we can go ahead and call our end

lottery function because again this is

going to call that request randomness

function from the vrf we'll do

end

ending transaction

equals

lottery dot end

lottery and all we have to do is from

count

to ending

transaction.weight

one

so from our end this is really all that

we need to do

right but remember

when we call this end lottery function

we're going to make a request to a chain

link node and that chain link node is

going to respond by calling this fulfill

randomness function

so we actually have to wait for that

chain link node to finish

now typically it's within a few blocks

so normally what we can do is we can

just do a time dot sleep

for something like 60 seconds

and typically in that time the chain

link node will have responded

so we'll just do import time

at the top

time dot sleep

and then

we can see

who that recent winner is if that chain

link node responded with a recent winner

so we can say print

f

lottery dot resent

winner

is the new winner

all right now of course for those of you

who are thinking ahead a little bit you

might be thinking hey well there's no

chain-link nodes watching our local

ganache

and you're exactly correct so what

happens when

we add

our end lottery function

to our main function here

do you think that we're going to

actually get a recent winner back why

are we not what do you actually think

well let's give it a shot

do brownie run scripts deploy

lottery.pie

so we're doing a lot of transactions

here we've started the lottery we're

entering the lottery you entered the

lottery we're sending some link token

now we just called the end lottery

function

while we're waiting here

this is when the chain-link node would

go ahead and start responding with our

randomness however as you're probably

astutely telling however as you probably

astutely guessed

there's no chain-link node that's going

to call this fulfill randomness function

right now so for our grenache chain this

will hypothetically end

with nothing right because there's no

chain-link node actually responding here

zero is the new winner of course this

means that the chain-link node actually

didn't respond because there is no chain

link node on our local ganache for our

testing purposes we're going to figure

out how to actually get around that and

deal with that

awesome it looks like we have everything

set up to be successful in our lottery

here

but we want to do our due diligence we

want to make sure that our tests are

really solid on a development chain

before we actually test this on an

actual test then so let's jump into some

of these tests we've already started

with this testlottery.pi bit here but

we're going to iterate on this and make

this even better

now before we get into these tests

there's a couple of things we want to

talk about here and that's going to be

integration tests and unit tests unit

test is a way of testing the smallest

pieces of code in an isolated system

and we're going to use it to loosely

define testing independent functions in

our lottery contract

we also want to do what's called

integration testing which is going to be

testing across multiple complex pieces

typically i like to run my unit tests

exclusively on a development environment

and my integration tests on a test net

this is really helpful because we can

test the majority of our application

like we said on a development network

and then still be able to see what

actually happens on a real test net and

see what happens on etherscan and

everything like that

typically

what people do is in their side their

tests folder they'll create two

different folders one for unit

and another folder for intergration

since for this demo we're only going to

have one file for both i'm just going to

go ahead and not create these folders

but

but it's a pretty common practice

instead what i'm going to do is i'm

going to rename this i'm going to hit

enter to rename it

i'm going to do underscore type unit

for unit tests and we're going to create

a new file

called test

lottery

integration

dot pi so this one we'll do our

integration test and in this one we'll

do our unit tests now when writing unit

tests we really want to test

hypothetically every single line of code

in our smart contract this is incredibly

important of course because smart

contracts are open to everybody to see

and interact with so we really want to

test every single line of code we have

in here

so let's go ahead and let's go ahead and

finish writing a get entrance fee test

that will work on a local development

network as you can see we're already

going to have to refactor this from what

we originally had let's go ahead and

just delete everything under here for

now

we already learned so much more from

there all right so how are we going to

test this get entrance view function now

so first we're going to want to deploy

our lottery again

since we have

a deploy lottery script already

we can just use this deployed audio

script as well

if we wanted to we could just copy paste

this hold part into our test but

we're just going to go ahead and work

from this deploy lottery script so

we're going to import this and then we

can actually even

get rid of this from web3 line for now

we can get rid of these two comments too

and we'll say from

scripts that deploy lottery

import

deploy

lottery and on this deploy lottery

function would say lottery

equals deploy lottery

and we will return our lottery

now our unit test we'll say lottery

equals deploy

lottery

and this will give us our lottery

contract once we have our lottery

contract

we can just call this get entrance fee

so we can say entrance fee

equals lottery dot get

entrance fee

and oops let's just make sure we're

doing the arrange

act

assert mentality here

and we're going to want to make sure

this entrance fee is what we expect it

to be so what do we expect it to be

well

again our helpful scripts is going to

deploy these mocks right

it's going to deploy this mock and the

initial value is this 2000 number so if

the price

of eth here is 2 000

2 000 f usd feed and the usd

entry fee

is 50.

we'd say 2 000

over 1

is equal to 50 over x

which is going to be equal to 0.025

so we can go ahead and even do this math

here

we can say expected

expected

entrance fee

is going to be equal

to

it's going to be equal to 50 divided by

2000.

we'll just do 0.025

but we'll do this in

way so do from web3

import web3

we'll say this is web

3.2

way

0.25 ether

and now we'll assert

our expected entrance fee

equals

the entrance fee now to test this we'll

do brownie test k

and perfect this is working

exactly as we anticipated so that's

awesome now as we mentioned since this

is a unit test we really only want to

run this when we're working on a local

environment a local blockchain

environment or a local development

network so we'll go ahead and do this

with pythons again

so if network dot showactive

is not

in

local blockchain environments

pi test dot skip of course we're gonna

have to import pi test

we're gonna have to import this local

blockchain environments from our

scripts.helpful scripts my vs code

automatically added that bit here now if

we try to run this

brownie run

excuse me brownie test

dash k

get entrance fee dash dash network rank

rink eb it should go ahead and skip this

perfect that's what it does

what's the next piece that makes sense

here enter is going to be one of the

first things that these developers do so

let's do test def

test enter but let's even be more

specific than that we don't want people

to be able to enter our lotteries unless

the lottery is actually started so let's

make sure that this line actually works

so we'll call

def test

can't enter unless

started and again we're only going to

run this on a local development chain so

we'll just copy paste this section down

here we'll say lottery

equals

deploy

lottery because we're going to want to

work with the lottery and now we're

going to want to that when people try to

enter a lottery that hasn't started yet

it's going to revert so we can use what

we've used before we'll say with pi

tests dot

raises exceptions dot virtual machine

error

lottery dot enter

from

get account

value

lottery dot get entrance fee

of course we're going to import both get

account

from our helpful scripts

and exceptions from ronnie

perfect and this as well is following

the arrange

and this is actually act slash

assert so let's go ahead and test this

brownie test k

test can't enter unless starter

oops let's do start ed

and great that's passing as well let's

go ahead and keep going down this list

what else now we've tested whether or

not they can't enter let's test whether

or not they can enter so we'll do def

test

can

start

and

enter lottery

so we're going to copy this again

paste it down here since we're going to

work on a local blockchain

we'll do lottery

equals

deploy

lottery

account equals get account

we'll start the lottery

lottery.start

lottery

we'll do from

account

we'll do lottery.enter

from

account

save value is

lottery

dot get

entrance fee

and then we'll assert

that

we've correctly added a player to this

lottery so we'll assert

lottery.players

of zero is going to be this account

right because we have our players array

and we're going to assert

that we're pushing them onto our array

correctly

lottery.players 0 equals

account so here's our act

here's our assert

so let's try this now

brownie test dash k test can

start and enter lottery

and once again awesome things are

looking great

now let's test to see if we can actually

end a lottery so we've tested we can

start a lottery so we'll do def

test can and

lottery we're going to copy this again

paste it down here

do lottery equals deploy

lottery

account equals get account

we'll start the lottery with

lottery.start

lottery

now we could 100

just import the rest of these functions

in here like n lottery enter lottery and

start lottery and similar to how we're

just doing lottery equals deploy lottery

we could absolutely do that for being

very verbose here i'm just going to go

ahead and write all the functions and

transactions myself and this way we'll

actually be able to test a little bit

more granularly anyways

we'll do lottery dot

start lottery

from

account

do lottery dots enter

from

account we'll give it a value

lottery dot get entrance fee

so i'm gonna have to do account

course equals get account

now

to actually end the lottery we do need

to send this some link because we're

calling request randomness we use our

fund with link script

that we have in our helpful scripts

we'll import this from our helpful

scripts

we'll call

fund with link

on our

lottery contract

once we fund with link we'll then call

lottery dot

end lottery

from

account

and then how do we actually know

that this is being called correctly well

if we look back in our lottery contract

here when we call end lottery we don't

we're not really doing a whole lot all

we're doing is changing our state so

let's go ahead and check to see if our

calculating winner state is different so

we'll say assert

lottery

dot

lottery state

is equal to what

so calculating winner if we scroll up to

our enum

is in position two open is zero close is

one calculating winner is two

so we can say

assert lottery.lotterystate equals two

two

we can go ahead and test this as well

we'll do brownie

test k test can end lottery

we'll see if this works

and it does

now let's test the most interesting

piece of this entire lottery contract

we're going to test whether or not our

fulfill function actually works

correctly

does this correctly choose a winner does

it correctly pay the winner

and does it correctly reset so let's go

ahead and build our most

complicated and most important test of

this whole contract choosing the winner

we'll do def

test

can pick

winner

correctly

let's copy paste this bit

about getting started

we'll do lottery equals

deploy lottery

account equals get account

we'll do lottery dot start

lottery

from

account

and then we'll enter with a couple

different players we'll do lottery dot

enter

let's say from

account

value

lottery dot get

entrance fee

enter

and we'll copy this two more times

but instead

we use some different ids we'll do index

equals one

and we'll do index equals 2.

these are going to be different accounts

here because we're going to use a

different index

because we want to just test for

multiple different people here

this unit test is getting drastically

close to being an integration test but

as i said we're being a little bit loose

with the definitions here now we're

going to want to fund it with link so we

can just go ahead and copy this line

here

fund with link lottery

and now we're going to want to choose a

winner here

and this is where we actually have to

modify one more thing

in our lottery contract so in order to

test actually calling this fulfill

randomness function

and testing everything in here

we're going to need to call this fulfill

randomness function

now if we look at our vrf coordinator

moc

we have this function called callback

with randomness

and this is the function

that actually calls this raw fulfill

randomness.selector which eventually

will call that fulfill randomness

function but this is the entry point

that the that the node actually calls

we have to pretend to be a chain-link

node and call this function

we're going to return

a random number of course we're going to

choose the contract we want to return to

but we also have to pass the original

request id

associated with the original call now in

our lottery contract

our end lottery function

isn't going to return anything

and even if it did it would be really

difficult for us to get that return type

in our python so what we want to do

to keep track of when this contract

actually entered the calculating winner

state is we want to do what's called

emitting an event events are pieces of

data executed in the blockchain and

stored in the blockchain but are not

accessible by any smart contracts you

can kind of think of them as the print

lines of a blockchain or the print

statements of a blockchain

we can go to this logs section which

also includes all the different events

now there's a lot of information here so

we're actually going to do an event

ourself just so that we can see what

this really looks like you can see here

that when we call this end lottery

function

in the logs if we scroll to the bottom

there's an event here called

randomnessrequest

this was spit out by the vrf coordinator

this was spit out by the vrf consumer

base that we inherited and it even has

some data that's already been decoded

one of those pieces of data is the

request id now to add an event we first

need to create our event type

so at the top we'll go ahead and do

event

requested

randomness

we'll say bytes 32

request id

so now we've identified

a new type of event called requested

randomness

it's really similar to the enum in this

regard

to omit one of these events

all we have to do in our end lottery bid

is we'll do omit

requested randomness and then request id

because requested randomness takes a

bytes32

as an input parameter

and we're going to pass it that request

id as an input parameter now that we

have this event being omitted back in

our test when we call

end lottery it will actually omit one of

these events to our transaction

so what we can say then

is transaction

equals lottery.nd lottery

same way we've always done it

but now we can look inside of this

transaction object

inside of this transaction object is

actually an attribute called events

which stores all of our events we can

then look for

a certain event name which we know is

requested randomness so we'll say out of

all the events look for the requested

randomness event

and in there

in that request randomness event

find the request id

request id

now we can say request id

request

id

is going to get grabbed from this

event that we omit so these events are

going to be really helpful for writing

tests these events are also really

helpful for a number of other reasons

one of the big ones is is upgrading our

smart contracts or understanding when a

mapping is updated but for now we're

going to be using them for testing now

that we have this request id what we can

do is pretend to be the chain link node

and use this callback with randomness

function to dummy getting a random

number back from the chainlike node so

what we're going to do

is we're going to call our getcontract

function

and get that vrf coordinator

of course we're going to import it

from our helpful scripts

and we're going to call that callback

with randomness function

so we're going to do dot callback

with

randomness

and we need to pass it

this request id

a random number

and then the contract to return to

so we'll do request id we'll do some

random number

like we'll say static

rng

equals 777.

so we'll say the random number that

we're going to return is going to be 777

and then we'll do lottery dot address

because we're going to return it to the

lottery

once again we're going to say from

account because this is making a state

change and now that we've got a call

back what we can do is do our asserts

now so this

is us dummying getting a response from a

chain-link node and this is how we mock

responses in our tests to make our lives

way way easier

so now we can do we can figure out who

the winner of this lottery actually is

if these are our three enter entries

that means it's 777

mod 3 since our random number is going

to be 777

if we pull out a calculator

777 divided by three

it divides evenly so we know that this

means the answer to this is going to be

zero

aka our account is going to be the

winner

so let's assert

the lottery dot

recent winner

is going to be equal to our account

right because

we set a recent winner

in here

we transfer them some money

we'll assert

lottery.balance

is now zero because we're transferring

this account all the money

and let's even make sure that the

account gets more money right so we'll

do

starting balance

of our account

starting balance of account

equals

account.balance

count balance and we'll do balance

of

lottery

equals lottery dot balance and then

we'll assert

account dot balance

is now going to be

these two added together

started balance of account plus

the balance of the lottery

because we should get all of the lottery

winnings here okay so this is a long

test but this is probably the most

important test let's make sure

this is doing what we wanted to do so

we'll do brownie test k

test can pick winner correctly let's see

if this works

oops i forgot to put a

put some parentheses here let's

parentheses here

let's try this again

and perfect

we are actually updating paying out and

running our lottery correctly and fairly

with true randomness this is incredibly

exciting and we've emitted events in our

lottery contract to use in the off chain

event logging of ethereum i know we're

getting antsy

to actually run this on a real chain

so let's go ahead and do our last bit

here create our integration test which

we will run on an actual chain and then

if we wanted to we go ahead and try our

deploy lottery function on a real chain

as well all right so let's do our

integration test here this is where

we're going to actually test on a real

live chain we're going to use ring

because that's the network that we've

been using this whole time which is

great now i'm being a little bit liberal

in the way that we're doing our tests

here and we're just going to do one test

for this integration test but keep in

mind you're going to want to test every

piece of your code so let's just create

a test called def

test

can pick

winner

now this is going to be

the opposite of our unit test

our unit tests are only going to be on

our local blockchains right we're going

to skip if it's not on our local

blockchains

we're going to do the opposite of this

one

so we can even just copy this or we can

type it out we'll say if

our network

dot show active

is in those local

blockchain environments

then we're gonna do pi test

dot skip

of course since we're grabbing these

pieces we're gonna do from

brownie import

network

we're going to import pi test

and we're going to do from scripts

dot

helpful scripts

import

local

blockchain and by enronments

we're going to deploy our lottery so

lottery equals deploy

lottery

which we're just going to grab from

scripts deploy lottery

import deploy

lottery

we'll do account equals get account

of course we're going to grab that from

our helpful scripts as well

so we'll do lottery

let's start lottery

this will be from

account

do lottery.enter

say this will be from

account

we'll do some value which is going to be

dot lottery.get entrance fee

and if we run into an issue here

sometimes again we can do lottery dot

get interest fee plus like 100 or a

thousand or something like that this is

going to be barely any way but

for now let's keep it like this

then let's just copy this line

right again we'll have two people enter

the lottery

of course it's going to be us both times

and great

now we're going to want to actually end

the lottery so first we're going to want

to fund it so let's import that funding

script so we'll get fund with link or

that function

so we'll call our fund with link

function on our

lottery contract here and then we'll go

ahead and end the lottery so we'll say

lottery

dot

and lottery

we have to do this

from our main account we have to do this

from the admin account

now this is where it's going to be a

little bit different from our

integration tests

or from our unit tests

in our unit tests

we pretended that we were the vrf

coordinator and we called the callback

with randomness we pretended that we

were a chain-link node

here we're not a chain link node because

we're on an actual network so we're

actually just going to wait for that

chain link node to respond so for

simplicity we'll just do time dot sleep

and we'll wait like a minute for it to

respond

of course since we're using time

we're going to want to import time right

at the top

and then since account was the only one

to actually be in this

we'll do assert

lottery

recent winner

equals equals account

and we'll also assert

lottery.balance

0. all right great so we have an

integration test that we can run which

is going to run through pretty much the

vast majority of our functionality here

so we can go ahead and test this with

brownie

test

will be a little bit verbose here we'll

say dash k

test can pick winner

and then of course we'll do dash dash

network

rink b now before we run this

per usual we got to make sure do we have

any test that ring the ethereum we do

great do we have any test net chain link

we do perfect we have a dot env

we do it's got all of our pieces let's

check our brownie config

dot env dot env awesome and again if you

don't want to use the dot envy

you can use that other method that we

showed you guys how to encrypt with a

password that you can actually use

oops before we run this

let's set this to start lottery because

that's the

actual function here and we'll also need

to be lottery.balance with parentheses

here sorry about that and now we can run

brownie test dash k

fast can pick winner dash network

rink b

we'll also add this dash s flag which

will print out whatever brownie is going

to be printing out make everything a

little bit more verbose here and if you

want to you absolutely should because

this is something that we'll have to do

at some point anyways however if for

this tutorial you want to skip it go

ahead because we're actually going to

run through this whole process of

deploying and waiting again anyways so

now we've added all of our tests what we

can do is run our entire test suite

so we'll do brownie

test

and this is going to run through all of

our development tests here you'll see

it'll go really quickly

and you see how much faster it is for us

to run our test on a local chain as

opposed to doing everything on a test

map so it's going to make your life way

easier and we have everything passed

here so we know that our contract code

is doing approximately what we wanted to

do

so

it's time for the moment of truth let's

deploy this to an actual test net so we

have our deploy lottery script which

oftentimes

i'll have it be just this deploy lottery

bit and then i'll have some other

scripts for these other pieces or maybe

i'll do it in the brownie console

but

just to demonstrate everything end to

end we'll have deploy lottery start

lottery enter lottery and end lottery

all in this one script

so that we can see everything end to end

and see what it looks like on etherscan

so let's go ahead

and run this script on a ringbeat

network and then we'll go jump onto

etherscan and see everything

so let's do it brownie run scripts

deploy lottery

network ring can be

so first we went ahead and we deployed

our lottery we got our addresses with

our get contract method

we got our fee we got our key hash

we got our published source and

everything here then we went ahead and

verified it because of this published

source

so if we grab this address lottery

deployed here

we jump over to

rank the ether scan

paste this address in here

we'll see

this contract with a little check mark

is verified

again we'll go to the read contract we

can see all the public variables and all

the public functions we can go to write

contract and we'll see all the

transacting functions that we can

interact with after we get verified

and things get deployed we went ahead

and called our start lottery function to

actually start the lottery we got our

little print line saying the lottery

started then we entered you entered the

lottery we then funded the contract with

link so we could get our random winner

back

and then right now our end lottery is

confirmed and we're just waiting this 60

seconds right because we did this

time.sleep and if we sit on this

contract if we go to transactions

and we refresh we can actually see some

of these different method calls over

here we can see we did a contract

creation

we started the lottery we entered the

lottery and then we recently ended the

lottery and you'll see

in our script here it says

zero x blah blah is the new winner which

is perfect right that means that the

chain link node actually responded we

can actually verify that by looking in

the contract

we'll go to read contract

we can go to the recent winner and see

somebody did indeed recently win we can

also go to events

and we can see some of the events that

we created

we can see this first event right here

is this requested randomness event this

is the event that we called we have this

end lottery here we can also see an

ownership transferred function that got

called this was called when we actually

deployed this in the first place

now a little bit more on these events

aka these logs right

so topic zero this hash represents this

entire event right here

and this

bit is going to be our topic one our

first topic which represents that

request id

so this is going to be the request id

awesome we have successfully created a

working smart contract lottery with true

provable randomness this is absolutely

insane incredible job here now one

additional piece that i want to talk

about before we jump off here

is again in our testing

a file that you're often going to see

is what's called conf test dot pi python

automatically knows to look for this

comp test file and we'll grab different

functions from it we can also add

external plugins

fixtures hooks testing root path it adds

a lot of really fantastic features and

is a common thing that you'll see we

skipped over in here for simplicity but

in future projects you'll probably see

this comp test file which has a lot of

really nice testing configuration pieces

in it

now that was a lot of stuff to code and

quite frankly i don't think any of us

want to have to do that every single

time have to code everything from

scratch now you can absolutely get clone

all these repositories right from their

github but there's actually an even

easier way first to start with a blank

project here and this is with brownie

mixes so if we google brownie mixes

github we'll get this mixes organization

which just has a ton of boilerplate code

for us to go ahead and get started and

start developing the one we're going to

be working with is this chain link mix

piece which is forked from this official

one here this gives us some wonderful

contracts some tests a browning config

and really everything that we need to do

to get started so if you have brownie

installed

we can just bake this mix so we'll do

brownie

bake

chain lick mix and in our new empty

directory here

we'll get this new chain link folder

with everything inside of it so then we

can see the chain link

and we can see it has all these pieces

in here here already

in the contracts we have a whole bunch

of different samples of working with the

vrf working with the price feed

working with this thing called keepers

to automate our smart contracts and

making api calls and delivering any api

call that we want to the blockchain it

also has a brownie config which already

has a number of wonderful pieces in each

one of these networks so that we don't

have to go copy paste and add it in here

it's even got support for test nets like

avalanche polygon

finance and more it has a number of

really powerful tests including testing

some price feeds it has a whole bunch of

deployment scripts some mocking scripts

some helpful scripts and really

everything that we need to get started

and get going for starters we can run

brownie test

and it's going to compile everything

and then on a development chain run all

these

unit tests and if we wanted to test this

on a real test net we could do brownie

test dash dash

network ring b or any network that we

wanted if you're looking for a good

starter place that has a lot of really

powerful smart contracts for you to get

started i highly recommend using this

mix as a boilerplate starting point for

any of your contracts or any of your

projects here

now we are cooking so we've learned a

ton of the fundamentals of working with

brownie and working with smart contracts

now that we have kind of all the

building blocks though we can actually

code a lot of these much faster and much

more efficiently than before one of the

things that we've seen over and over and

over again is working with tokens and

the erc20 token standard

we're going to learn how to build our

own token before we do that let's

understand why we'd even want to do this

now first let's define even what are

erc20s so erc20s are tokens that are

deployed on a chain using what's called

the erc20 token standard you can read

more about it in the erc20 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 with a smart contract it's both

it's really cool tether chain link uni

token and die are all examples of erc20s

technically chain link is in the rc677

as there are upgrades to the erc20 that

some tokens take that are still

backwards compatible with erc20s and so

basically you can think of them as

erc20s with a little additional

functionality now why would i even care

to want to make an erc20 well you can do

a lot of really cool stuff with it you

make governance token you can secure an

underlying network you can create some

type of synthetic asset or really

anything else in any case how do we

build one of these erc20s how do we

build one of these tokens well all we

have to do is build a smart contract

that follows the token standard all we

have to do is build a smart contract

that has these functions it has a name

function a symbol function decimals

function etc all these functions we need

to be able to transfer it we need to be

able to get the balance of it etc and

again if you want to check out some of

the improvements that are still erc20

compatible like the erc677 or the erc777

you definitely go check those out and

build one of those instead so let's

create a new folder and get started

we're going to create our new browning

file of course with brownie init it's

going to start up our repository and

start up everything that we are going to

work with here we can kind of actually

just jump in and start right with our

contracts so let's create a new file and

we'll call it our token

dot sol

and this is where we're going to add all

of our token code

now since this is an eip right this all

this is is a smart contract so what we

could do is we could grab all these

functions

copy and paste them in here one at a

time

grab the name

grab the symbol

grab the decimals and then you know code

all these up be like this does some

stuff blah blah blah or

we could do it the much easier way right

since we're engineers we don't always

want to reinvent the wheel so once again

our friends at open zeppelin

have some amazing contract packages for

actually building our own erc20 token so

we can go right to the opens up and

documentation i'm working on the 4x

version but again it doesn't matter the

version that you use so long as in our

config file we add the version that

we're going to use which again we've

already gone over so let's go over to

their erc20 documentation and this is

the entirety of the code that is needed

to make an error c20 so we can just go

ahead and even copy this

paste it in here and boom

we have some erc20 code in here let's

actually just change the name of

everything in here though so we're going

to call this our token

dot sol

we have

this spdx license identifier mit great

we're going to be using solidity version

0.8 which i know i've done a lot of this

code actually in point in 0.6 but i

highly recommend working with 0.8

because it has a lot of really fantastic

improvements to solidity you'll notice

this is our first dive into using a

different version of solidity here

you'll notice that most of the syntax is

exactly the same there are like i said a

couple of nice improvements with 0.8 the

main one being you no longer have to use

those safe math functions that we talked

about before but then we're going to go

ahead and import opens up when contracts

token erc20.sol now of course since

we're importing open zappone we're

importing this package we've got to add

this to our browning config

diamo

and before we even get started you

technically have all the tools that you

need to code and deploy your own erc20

token now i'm actually going to

challenge you to go ahead and try to

start a browning project create your own

token using opensupplement packages and

then deploy it on a test net i'm going

to show you how to do all of it here

anyways but challenging yourself and

trying to do things your own and

exploring is really one of the fastest

ways to learn and grow in this space

did you give it a shot no really pause

it now and give it a try

all right welcome back now we'll go

through it and we'll do it together

of course we need to add these

dependencies

open zeppelin

open

zeppelin contracts

let's do their version four

so let's even go to github

open zeppelin

and we'll do

4.2.0 which was released yesterday at

this time which is great 4.2.0

and of course again compiler

we'll have silk

remappings

we'll add

at open zeppelin

equals

this

and then we're going to go ahead and

save

now we can use this at opens up line and

it will refer to the opens up and

contracts here so great now we can go

ahead and import these

let's change the contract name to our

token we're going to inherit this

erc20.sol from open zeppelin we can even

go ahead to opens up on contracts github

and we can even see what this erc20

looks like so we can go to

their contracts down to token

erc20

erc20.sol

and this is their initiation of an erc20

which has all these functions like name

symbol

decimals total supply etc in our

constructor we're going to add an

initial supply which is going to be in

way of course so the initial supply of

that token and we're going to use the

constructor of the erc20.sol which again

we can go ahead and check in the code

here and we can see the constructor uses

a name

and a symbol

so we have a name we'll call it r token

and the symbol will do ot and boom that

is literally all we need for our token

here i told you this is going to be a

much faster project now for scripts all

we have to do is create a new file

we'll add a 1

deploy token dot sol and we'll also add

a helpful

scripts apply

excuse me this deploy token dot pi

excuse me

we'll just quickly add a account

function we'll say def get account and

you can go ahead and just copy paste

from the last one and if you want you

can actually just copy paste from our

last helpful scripts because it's pretty

much going to be exactly the same so we

have all these wonderful

ifs statements so that we can deploy

from really anything that we want now in

our deployment token script we'll do

from

brownie

import

our token

and then from

scripts that's

helpful scripts

import

get account and just to make sure let's

add an init

dot pi in here

just to make sure that our scripts can

actually import so since we know

since we know that we need an initial

supply here let's go ahead and do

initial

supply

equals and then we can do you know

whatever we want here

if we want to make it a little bit more

readable we'll also

do

from web3

import web3

and we can do

web3.2

way and we'll say

1000 as the initial supply and this is

in ether

so our initial supply is going to be

1000 ether

then we just add our main function

we do account

equals get account

we do our token

equals

our token

dot deploy

we just add as a parameter

this is initial supply

do from

account and then we'll do print

our token dot

name

and that's the whole function now of

course if you don't have your

environment variable set we're going to

add our dot enb file

this is where we can add our private key

our web3

infiera

project id and then if we want our ether

scan token i'm going to skip doing this

for now because my environment variables

are already set

and then last but not least we'll add

dot env

dot env

so private key equals ox blah blah blah

when three inferior priority equals blah

blah blah ether scan token equals blah

blah blah

and perfect now if we want to actually

deploy this to a testnet all we have to

do

go into our config

we'll add wallets

from key

we'll add our environment variable

private key

now brownie knows where to grab this

from because we've defined it in our

helpful scripts what i can do now

so brownie runs scripts deploy token.pi

and we can go ahead and see that our

token is printed out

we can see that we have this token

deployed on our local ganache

we can see our token here and this is

great now i can go ahead and run

this again

network ring b

now if i grab this address go to the

ringby ether scan

pop it in after a quick refresh i can

now see that

my contract has indeed been added and

etherscan even picks up that it's a

token

now we could do we can grab this and

grab this contract address

go to assets

add it in our metamask here

next

add tokens and you'll see we are the

proud owners of 1000 hour tokens now

something else that you might want to do

is add this to a liquidity pool or add

this to a place where you can actually

go ahead and sell it and put it on the

market you can do something like that as

easily as just popping onto uniswap

going to pool hitting more

create a pool

and then adding our token in here we'd

have to manage the token list and be

sure to add the token in here but we

could go ahead and add a token

create our own pool and automatically

put it on your swap and that's how easy

it is to actually sell it on one of

these pools but alright so this was

probably our easiest project of the

course but it really shows how far

you've come along everything here

i thought we know a little bit more

about d5 and why it's such an amazing

amazing technology that only works in

the blockchain world let's look at this

site d5 pulse or if you want to look at

another one uh there's another fantastic

one out there called defined llama which

also shows a lot of these different

protocols in here so defy pulse is an

application that shows some of the top

d5 projects based on how much

total asset is locked into each protocol

ave which currently is the number one

ranked d5 application with 9.32

billion in assets under management in

terms of usd then we have some fantastic

ones like curve compound maker instadap

etc now we're going to be looking at two

of these protocols in particular the

first one of course

being ave and the second one is going to

be a type of what's called a

decentralized exchange you start with

ave we're going to go to testnet.ave.com

dashboard and it'll bring us to a screen

that looks something like this with

please connect your wallet and

everything will be pretty empty parasop

is what's known as a dex or a

decentralized exchange it allows us to

trade tokens incredibly easy on the

blockchain now there's not a whole lot

of test net indexes that actually work

so we're just going to look at them and

simulate as if we were working on them

for example if i wanted to trade one eth

for some usdt or maybe some wrapped

bitcoin or some dye or some ave

or link or really any token that we

wanted

all we would need to do is connect our

wallet here

and

a swap button would show up and we would

go ahead and hit swap some other really

powerful these dexes and really popular

ones are going to be curve finance

uniswap and it's a really really easy

way to go ahead and swap your tokens for

one another depending on what you're

looking to do ave is incredibly powerful

and it's going to be one that we're

going to be working a lot with because

it has pretty much all the fundamentals

of working with the d5 protocol that

we're looking for and it has a test

stand that we can go ahead and test and

simulate actually working with some of

these protocols so we're going to first

work with the ui or the user interface

and then we're going to do everything

here programmatically first things first

if you don't already have it make sure

you have some test net ethereum at least

and again you can get some test and

ethereum from looking at the link token

contracts

and going to coven

this one indeed uh the test net of ave

right now is only on coven so we're

going to go ahead here

we're going to add our copy our address

paste it in

i'm not a robot

70.1 test eth remember we use this

linked token contracts page because this

is going to have the most up-to-date

faucets here once we see some eath in

our coventestnet here we can go back to

ave

so whereas paraswap allows you to simply

swap between assets and do a lot of

buying and selling of tokens

ave is a lending and borrowing

application so we can actually put down

a token as collateral and we can borrow

and we can generate some yield from

interacting with this protocol borrowing

and lending is a critical piece to doing

any type of really interesting financial

applications or financial instruments

such as short selling being exposed to

more assets etc

you can also gain some percentage back

if you look at apy

it'll tell you how much percentage over

a year you'll actually get in returns

from staking or depositing an asset

so here's what we're going to go ahead

and do we're going to connect to the

application

using metamask and you'll see on the

deposit tab here we'll see our balance

be 0.1 each because that's how much i

currently have in my wallet right now

what we can now do

is click on ethereum click this max

button to deposit some ethereum

we'll hit continue

and a little dashboard will pop up

asking us okay would you like to deposit

clicking this deposit button will

actually have us deposit right onto the

ave contract on the coventest net make

sure once you hit deposit here that

you're actually on a test net here it

looks like i actually have some

insufficient funds so i'm actually going

to go

borrow a little bit more

or from the faucet here

grab a little bit more from the faucet

here

we're going to come back

we're actually going to go back

refresh and now it says i have

0.1

we're going to deposit 0.1

continue

deposit and metamask is going to pop up

saying hey are you sure you want to do

this right we can check our data

we can grab this address even if we want

pop it on to

coven.etherscan

paste it in here

we can even double check to make sure

that this is indeed the right contract

that we want funnily enough you'll see

that this is the west gateway when we

deposit our covent eath it actually gets

transferred into an erc20 version of our

ethereum and then it'll go ahead and

deposit it into the ave contract so

we're going to hit confirm

now we're going to get this pending here

we have a link to the explorer

which shows us this transaction that's

going through and then we'll see that

we've indeed successfully deposited our

ethereum now down here you'll see a

little button add a eth to your browser

wallet and we're going to go ahead and

click this

and this will automatically add this

token

to our wallet so we're going to hit add

token

and we see now in assets we have this ae

down here

we could also have manually hit added

token got the contract address but avi

was nice enough to just go ahead and add

us a little button that does it for us

ae is what's called an interest-bearing

token and it goes up in real time you'll

see if i sit here long enough you'll see

this number actually continually going

up this is the profit given to us from

other people borrowing the eath that

we've deposited into ave if we go to our

dashboard now

we can see we have 0.1 each deposited

and if we roll over it you'll constantly

see the amount go up and up and up we

can go ahead and withdraw our eath

which will convert our a

back into eath with the additional

interest that we got from depositing so

depositing into ave will give us

interest back as a payment for other

people borrowing the eath that we've

deposited we can also use this eath as

what's called collateral so if i go to

this borrow tab

i can actually use the eath to borrow

some other acid maybe i want to borrow

dye which is a stable coin meant to

always equal one dollar usdc and usdt

also are meant to always reflect a

dollar we can borrow what's called

wrapped bitcoin which represents the

bitcoin price we could borrow some

ave token some bat token some link token

we can borrow all these different tokens

now borrowing an asset is incredibly

incredibly powerful by borrowing you're

allowed to obtain liquidity without

selling your assets and borrowing is one

of the first pieces in order to actually

short sell borrowing in default

protocols is absolutely massive because

it allows you to frictionlessly short

sell obtain liquidity without closing

your position

gain yield on some deposited collateral

you can do a massive number of new

things only in the default world such as

flash loans

now an important note on borrowing

assets on mainnet since we're just

borrowing it on test net and this isn't

real money this is 100 okay to

experiment with and work with however if

you borrow an asset and you do not pay

attention to how much you have for an

underlying collateral you could get

liquidated and lose some of your funds

so be very careful and pay a lot of

attention if you're going to do this on

an actual network now let's say we want

to borrow the ave token for example we

click here and we can choose the amount

that we want to borrow now here's the

thing

since we've placed down some collateral

right 0.1 if the amount that we borrow

ends up being too high

we'll actually get what's called

liquidated every time we borrow an asset

we get some type of health factor the

health factor represents how close to

being liquidated you are once your

health factor reaches one

the collateral that you've actually

deposited will get liquidated and

somebody else will get paid to take some

of your collateral this is so that the

the ave application is always solvent

being solvent means it's never in debt

so when i want to borrow i want to

choose some amount that might be a

little bit safe here and so that i'm not

going to get liquidated so

zoom in a little bit

i'm going to choose some number where i

see a health factor maybe like 5.6 we're

going to continue now we'll have to

choose our interest rate when we borrow

an asset we actually have to pay some

interest this payment is actually going

to go to the people who are depositing

die or depositing the asset the interest

rate that we're going to pay is actually

going to be paid to those who are

depositing the asset that we're

borrowing so like how we're getting

interest on our deposited collateral

others are getting interest on their

deposited collateral based off of how

often people are borrowing it we choose

a stable apy which will always be four

percent

or a variable apy which will change

based off of how volatile and how in

demand this asset is for now i'm going

to choose variable but you can pick

whatever you want especially for this

demo we're going to hit continue i'm

gonna zoom out just a little bit

and the same interface is gonna show up

we're gonna go ahead and hit borrow

metamask is gonna pop up and ask us if

we really want to borrow we're gonna go

ahead and hit confirm

and now we've successfully borrowed die

into our application we can even hit

this little add die to your browser

wallet

to add the token to our wallet

now if we hit the button we go to assets

we can now see die is indeed in our

token assets here now if we go back to

our dashboard you'll see we have a

health factor score here this is a

really important score if you click on

this little i thing it says the health

factor represents the safety of your

loan derived from the proportion of

collateral versus amount borrowed keep

it above one to avoid liquidation

and we'll see all of our deposits here

so we still have 0.1 in each deposited

we also have 28 die deposited you can

see a whole lot of different stats here

for working with our application we can

withdraw our die we can withdraw our eth

we can borrow more die or we can go

ahead and repay we can either repay from

our wallet balance or from our current

collateral yes we could repay with our

collateral

let's go ahead and do from our wallet

balance

we'll hit max

continue

and we even get this little thing that

says you don't have enough funds to

repay the full amount well why is this

the case we just borrowed this amount

it's because already since depositing

we've accrued a little bit of we've

accrued a little bit of extra debt

remember we hit that variable apy

and every second it's going to tick up

just a little bit so let's go ahead and

pay back what we can with our wallet

we're going to confirm

we're going to approve our data to be

spent

and then we're going to go ahead and hit

the repay button and gray now if we go

back to our dashboard you can see we've

repaid almost everything here but we

have a little bit left so let's just go

ahead and hit repay with our current

collateral we'll hit max

continue

and this will use our eth to pay back

the collateral instead of the die

and then we'll hit repay this way we'll

have no more debt

great now if we go back to our dashboard

we can see we have no more debt which is

fantastic ave is one of these

applications that relies on the

chainlink price feeds in order to

understand the ratio between how much

you have deposited as collateral and

then how much you can borrow and take

out if we look in our wallet now we can

see we still have some aethe

we also have some eath and now we have

zero die because everything's paid back

but we're still gaining interest on the

eth we have deposited

let's go ahead just reconnect

let's go ahead back to testnet.aver.com

and let's just withdraw all of our eth

now keep in mind when working with some

of this this is a test net right and

working the way we're working right now

is just on a test head so sometimes the

test net doesn't work quite as well as a

main net because it's just for testing

and doesn't have the exact same support

we were just working on the test net

but if you want to go to ave for real

you can go to

app.avefork.com connect your wallet on

the ethereum mainnet

connect your wallet

move to the ethereum maintenance and

interact with it exactly the way we just

saw now if we're on the maintenance here

we can see some additional pieces when

you deposit something like die

yes you get 2.3

back as interest paid to you for

depositing the die

you also get a little bit of what's

called a governance token you also get a

little bit of ave token i know it's

really small here but

this is an additional incentive that ave

has given the users for working with

their protocol since ave is a

decentralized protocol in order for

anything to be improved or anything to

be updated on the protocol it actually

has to go through a decentralized vote

so these governance tokens actually

dictate and decide how the protocol

improves moving forward now that we

understand how to work with all of that

through the ui

let's actually learn how to interact

with ave and interact with defy all from

our scripts learning how to do it this

way will get us one step closer to being

a quantitative defy engineer or d5

researcher this is someone who

programmatically does algorithmic trades

algorithmic modeling and just does

everything in a programmatic sense

making them much more efficient and

powerful interacting with d5 now all the

code that we're going to be working with

here is in this avi brownie pie

application and you can always refer

back to it in the link in the

description or in the link in the github

repository and see all the code written

yourself so with that create a new

folder and open up your vs code to that

folder and let's get into it and ave has

some fantastic documentation that we're

going to use as well link here is also

in the description let's go ahead and

start

with our our basic brownie setup just

with brownie init and we got a new

brownie project we got all of our

folders in here and we are good to go

now for working with browning we're

actually not going to really be

deploying any contracts because all the

contracts that we're going to work with

are already deployed on chain all of

them are just going to be working right

with ave here create a quick readme.md

so we can know what we're doing here

number one we're going to try to deposit

some eath into ave

then we're going to borrow

some acid

with the eth collateral

and then if you wanted to i challenge

you to actually sell

that borrowed acid

this is what's known as

short selling but we're not going to do

that here and then we're just going to

repay everything back

great and this will be the full

functionality of working with ave in

this deployed contract everything that

we're going to learn here will teach you

how to work with other

contracts as well such as paraswap or

unit swap

or any other type of swapping contract

that will allow us to buy and sell

so let's just go ahead and create a

script we'll call it ave

borrow that pie let's go ahead and

create a function called def main and

we'll just do

pass for now the first thing that we

need to figure out how to do is deposit

some f into ave

when we actually deposited our f via the

ui

you can actually see

when we call this deposit function if i

hit this deposit button here

oddly enough

if we go to this contract address

on the coven ether scan

we'll see

that this address is actually what's

called a west gateway

what ave is doing like i was saying

before and let's go ahead and actually

cancel this for now reject what ave is

actually doing here is swapping our

ethereum for west

again west is an erc20 version

of ethereum and this allows it to easily

work with all the other erc20s on the

obvi protocol like die usd coin

you know ample fourth link et cetera

so we actually have to do the that as

well

so the first thing we're going to need

to do

actually isn't deposit some of our eth

the first thing we're going to need to

do is going to swap our

eth for

west so let's even just put this in its

own little script we'll call it get

weth.pi so we're going to have a

function

def main

i'm just going to do pass for now but

we're actually going to want to use this

get wet function in our ave borrowed a

pi

so we're going to actually have a main

and we're going to have a def

get weth

and our main function is just going to

call

getwef so how do we actually

convert our ethereum to wef or wrapped

ether we'll even do a little dock string

here

mint's weth by depositing eth

now to save gas we could actually

interact with this weft gateway for ave

but i'm going to teach you guys how to

just get west in general so we can look

up the west contract

ether scan

the west coven contract ether scan

and we'll see here

we have this wrapped ether page

and we can go to the contract and we can

see that this is indeed verified

the way ath works is there's

a withdrawal and deposit

we deposit eth into this contract and it

transfers us some wealth

so this is the first contract that we

actually want to interact with so we

need our script to be able to call this

deposit contract

so

per usual the two things that we need to

do this are going to be an api

and an address

for this web contract i really like just

doing everything directly from the

interfaces i've already copy pasted the

interface

into this here so we're going to go to

interface dot sol and we're just going

to copy all this right here

so in our interfaces

we create a new file we're going to call

it iweth

dot soul

we're going to paste it in

you can see this has all the exact same

functions as our deposit contract

symbol name

transfer pretty much everything you'd

expect from erc20 plus this extra

deposit piece

we'll call this iweb it's a common

naming standard to just have i in the

name of what your contract is when

you're talking about an interface so we

have an interface now

and we also have

an address

but again this is our address on the

coven network since we know ahead of

time that we're probably going to be

using this on different networks like

mainnet and coven and etc we're actually

going to create a new file we're going

to add our brownie config

hopefully this is starting to look a

little familiar to you now

we're going to go ahead and add our

networks in here

in here we're going to go ahead and add

coven and in here we're going to write

west

token

and we're going to add

this address of the web token

paste it in here

while we're in here

we're going to add the rest of our

pieces we're going to add wallets

from key

private key

and that's all we really need for now

speaking of which we probably are still

going to want to test this locally

now since we've done some work with

testing we know that for testing

we can do our

integration test into

integration tests

on kovan because there's an integration

test there

what about our local tests

well this is something good that we're

thinking about right now we know that

ave actually has

all these same contracts on the main net

as well

and we also know that we're not going to

be working with any oracles because that

we don't actually have to deploy any

mocks ourselves we can if we want to but

we don't have to what we can do is for

our unit tests

we can actually just use

the mainnet fork network and just fork

everything that's on the mainnet into

our own local network so instead of

actually using mocs we'll basically just

mock the entire mainnet and one more

time just so that we absolutely have it

here if you're not working with oracle's

and you don't need to mock responses we

can just go ahead and use a mainnet fork

to run our unit tests if you are using

oracle then it makes a lot more sense to

do the development network where you can

mock oracles and mock oracle responses

with this in mind we know that we're

going to be doing a lot of our tests on

mainnet fork

we can go ahead and add a mainnet fork

network here and then we can just add

the mainnet web token

for mainnet fork so we'll look up web

token

etherscan

web token etherscan

and we'll grab this contract address

remember absolutely positively if you

want to double check that the contract

address that you're working with is

correct i highly recommend you do so

because if you get it wrong you could

accidentally add some money to a

contract address that you don't want

so we're going to have the mainnet fork

address b the web token address

and in our terminal

we can do brownie

networks list

and see that indeed we have a mainnet

fork here that's going to use the

ganache cli to fork mainnet for us

there's there's a link in the

description to refer back to the section

where we actually set this up so now

that we have the interface we know that

we can actually compile it down to the

abi so back in our get wet here

first thing we need to do to make any

transaction obviously is get an account

well

this is where we can go back and make

our helpful scripts

so we can go ahead

do def

get account

index equals none

id equals none

same as before

and if you have your get account

function from our last demo you can just

go ahead and copy paste it in here all

right great now we have our get account

function so we can do account now equals

get account

oh but we have to import it in here so

we'll do

from

scripts dot

helpful scripts

import

get account

and depending on your python version

we'll add in it that pi just so that

python recognizes that scripts is indeed

a module all right cool so we have our

account where we can make some

transactions with

now let's go ahead and get our wef

contract

to do this we can import interfaces from

routing

browning

import interface

same as we did before

and we can do with

equals interface

dot i with

and the address here is going to be from

our config

config

networks

dot show active

and then

web token

we also have to import config from

browning

and network as well

now you might be asking why aren't we

using the get contract function here

well you can absolutely 100 go ahead and

use that get contract function but since

we're going to be testing on mainnet

fork here i know that we're always going

to refer back to the config so i'm

confident that i'm not going to be

deploying any mocks

it's better practice to go ahead and use

that getcontract function but for this

one we'll just make it a little simpler

and use the config

and now in a fig if we're on the coven

network we're going to use this one

if we're on mainnet or maintenance fork

we're going to use this one

for going to mainnet or for to real

production you could also have a mainnet

network and it'll just be an exact copy

of the maintenance fork

and remember we're going to want our dot

env our env file

our environment variables to get pulled

from that dot env file so we can just

set it like this now everything in our

env file will get pulled in

automatically

great so we have an address and we have

an abi which comes from the interface

now we can just call we can just call

this deposit function where we deposit

ethereum and we get wef so now we'll

just do transaction equals wealth

dot deposit

and we'll do from

account

value

is going to be let's just say 0.1 so 0.1

times 10

raised to the 18.

so we'll deposit 0.1

and we should get 0.1 wef in return do a

printf string

received 0.1 weft

this doesn't even need to be printf

and then we'll just return tx

now per usual

if your environment variables aren't set

such as private key we're going to want

to do that so in our emb we do export

private key

equals 0x at the beginning right here

we're going to export web 3

infero

project id we'll want our ad our web3

inferior project id which we've got

before

if we want to use our etherscan token we

absolutely can

and since we're putting a whole bunch of

stuff into dot and v we want to make

sure in our git ignore we have

dot and v so we don't actually push this

up to github again if you're nervous

about having all these ambs in here you

can absolutely do the accounts.add or

whatever other methodology you like to

set your environment variables anyway

let's go ahead and run this script now

so we can do brownie run scripts

get wet pie

network

coven

generating the apis from our interface

we have a little transaction hash that

we can use

pop into the coven etherscan

and we can see

the transaction going through in our

wallets

we'll get minus 0.18 and we'll get plus

0.1 weth

so we can see it's actually been

successful

to add this and see this on our metamask

we're going to grab the contract address

here we're going to go back to metamask

add token paste it in here

add tokens and you can see we now have

0.1 with if you want to switch back your

weft to ethereum you would just hit this

withdraw function or

we could programmatically add a

withdrawal function in here this

withdrawal function will run for

ethereum withdrawal and take our

ethereum out of the contract and burn

the weapons replace it with weft so you

need to swap your weft back to get your

eth out awesome we have some weft and

now we have an erc20 token we have an

erc20 token that we can use to interact

with the ave application now that we've

got this get weth function let's go

ahead and start borrowing so let's go

ahead and start with our account

it's going to equal to get account

which now we're going to want to import

right at the top

like so

then we're going to get our west address

or we can even just do our erc20 address

because the web token is in erc20 and

maybe we want to deposit some other

erc20

we'll do config

networks

network dot show active

left token

and of course

we're going to have to now add from

brownie

import

network

and now we want to call this get weth

contract

just in case we don't already have wef

we would just add another from scripts

dot get weft

import

get west but we don't actually need to

call it right now because we already

have some wrapped ethereum in our

covenant address now if we want to test

this though on our local mainnet fork we

probably will want to call this getweft

so i'm just going to add a little if

if

network.showactive

is going to be our

mainnet fork

we should go ahead and call this get wet

function and for brownie we're also

going to want to import this config

we'll also have to add

mainnet fork

to our local blockchain environments

like so

so that when we call git account in our

scripts it actually knows that it's a

local environment that we're working

with and it will just return accounts

zero instead of us having to actually

load a private key in every single time

and we want to actually wait for our

transaction to complete here so we'll go

ahead and add this weight and then do

tx.weight

and wait for this transaction to

actually finish otherwise brownie will

get a little bit mad

so now that we have that we can run

brownie

run scripts

ave bar to pie

network

maintenance fork

so you can see that actually in this

case testing everything on mainnet fork

is going to give us a really really

accurate view of what doing this on

mainnet actually is going to give us we

don't have to do any mocking we can

literally just fork all of mainnet and

go from there we are still going to test

on kovan though in a little bit just so

we can see all the transactions that go

through how long it takes for stuff to

happen

so

now that we've gotten some wealth here

we actually need to go into our second

bit we're going to deposit some f or in

our case

some

wealth into ave so how do we actually do

that

well everything that we need is going to

be in this ave

documentation here

where we deposit and borrow from in ave

is in their contract this lending pool

you can see here the lending pool

contract is the main contract for the

protocol it exposes the user-oriented

actions that can be invoked in solidity

and web-three libraries and these have

all of the functions that we need it has

deposit where we deposit our asset as a

collateral withdraw where we take it

back we have borrow we have repay

and we can have we have swap borrow

rates

and a couple other interesting ones

which we'll go into later but for now we

just really need to focus on repaying

borrowing

withdrawing and depositing

so as you probably guessed deposit is

the function that we're going to work on

right now

and since this is the contract that

we're going to work with as always the

two things you need when working with a

contract are going to be the abi and the

address so we're going to get this

lending pool contract we're going to say

lending pool

equals and we're actually going to even

make a function called get

lending pool

so down below we're going to do def

get lending pool

lending pool not poll

and we're going to get the lending pool

address and the lending pool contract so

we can interact with it down here now

something about this lending pool is

that the lending pool address can

actually change a little bit depending

on a lot of different pieces

so there's actually this address

provider which gives us the address of a

specific or particular market if we go

back to this ave ui there's actually

different markets so there's different

types of ways we can interact with ave

we're just going to work with the basic

ave v2 because it's easily the most used

on mainnet as well the address provider

registry will give us so this address

provider will give us the address of the

lending pool for our market if we want

to go across different markets we'll

have to go to the address provider

registry to find it but the addresses in

here don't change and the addresses in

here don't change it's just the lending

pool address itself might change so we

just have to go to

this address provider here and there's

just one function that we need to work

with it's this get lending pool which

will give us the address of the actual

lending pool so don't let this confuse

you too much basically all we're trying

to do is we're saying hey where is ave

located right now and ave has a contract

that will always tell us where the main

ave contracts are and that's this

addresses provider right here so this is

another contract that we have to work

with and again when we have a contract

what do we need we need an api

and we need an address so we can

absolutely once again we could go ahead

and

you know copy paste like abi equals

whatever the abi is but we're just going

to use an interface because because life

is great with an interface

so a couple of great things about

interfaces too if we know we're only

going to work with one or two functions

we can actually just make the interfaces

ourself

so an interface we could do a new file

we could do i

lending pool

address provider that's sol

and we can just add it in here ourselves

so we'll first do sp dx

license

identifier

and we'll do like mit or something

we'll do pragma

solidity

0.6.6 or whatever we want to do

and then we'll do interface

i

landing pool

addresses pro

divider

excuse me this should be a lending pool

address says

provider

and we know that there's only one

function

called get

lending pool

and we're not exactly sure what

getlendingpool is defined as but what we

can do

is we can go to

ether scan eat the scan ave

lending pool addresses

you can see here this is actually the

lending pool

but what we can look at is the ave

protocol we can go right to the github

we can go to contracts

we can see they have an interfaces

section

and they have

this lending pool addresses provider

get lending pool and kind of as we

expected it's an external view and it

returns an address so we can literally

just copy paste this

into here

and we could run with this and this

would work perfectly fine

but this leads us to the next point we

might as well just grab the whole thing

this way we know for a fact we're not

getting anything wrong but yes if we

wanted to

our interface could be this

right because this is going to compile

it could be this

because this interface is going to

compile down to an abi and the abi is

going to say hey there's a function here

and that's all the abi is really doing

it's just telling us how we can interact

with a contract but let's just go ahead

and add everything so that if we want to

interact with more things we can so now

we have the api we also now need an

address which we can definitely find

from the ave documentation we can go to

their deployed contract section we find

lending pool

addresses provider which is going to be

right here

we're going to copy that

and where are we going to put this well

as you know we're going to put this in

our brownie config we're going to do

lending

pool

addresses

provider

i'm going to paste that right there and

since we know we're also going to do

coven

we can also grab from kovin here

so lending pool addresses provider

we're going to copy this here

and do

and we're going to add this addresses

provider for coven as well

boom now we have it for both coven and

for maintenance fork

awesome

so we can keep going now now that we

have an avi and we have an address for

both coven and for our mainnet

maintenance fork

what we can do now

is we first get the lending pool

addresses provider

it's going to be

from our interface which again

we're going to grab from brownie

interface dot i

lending pool

addresses provider

which the address of that is going to be

config

networks

network.showactive

lending

pool

addresses provider

and then we're just going to say

lending pool

address

it's going to be equal to

blending pool

i'm just going to copy and paste instead

of typing the whole thing address

divider provider dot get

lending pool

right because again

this address provider has this get

lending pool which returns this address

which is the address of the lending pool

then now that we have this address we

can actually return the lending pool

contract

by once again getting the api

and the address

of the actual landing pool so we have

the address

check

we just now need the api which once

again we can work with our wonderful

interfaces here do new file

i

lending pool

and there's only going to be a couple of

functions we're going to work with here

but ave actually gives us the interface

right here

and

ave actually even gives us the interface

of the lending pool address provider for

us so we can go ahead and copy this pop

it over into here now we do need to

actually change one thing in here as

well this interface imports locally with

this dot slash so we actually just need

to change these imports to actually

import directly from github instead of

importing locally

luckily this is something we already

know how to do so let's go to our

brownie config

and up at the top we're going to add

this dependencies bit in pen

then c's

so we're just going to work with ave's

protocol right from github

so

we're going to work with ave slash pro

tow call

v2

and let's see what their latest version

is

looks like they got a couple different

versions here

1.0.1

so let's go ahead and work with this one

at

1.0.1

and then with compiler

sulk

remappings

per usual

we're going to say at

ave

is going to be equal to this dependency

this way brownie will download this

right from github and now we can just

use this at ave

instead

so back in our eye lending pool.sol we

can just change this

to poll right from github and if we look

in github

we go to their contracts section

we go to their interfaces section

by lending pool

we know that we can pull this from

at ave

slash contracts

slash interfaces

because we see this eye lending pool

addresses provider

right in here

and then this data types bit

you can actually look in contracts

and this i know because i've i've been

through already it's in protocol

libraries

types

and here it is datatype.sol so we can

just take this exact path again

and do at ave

contracts

slash protocol

slash libraries slash types

data type dot sol okay great so now that

we've actually imported this interface

for us to use we can go ahead and

compile just to make sure that

everything is working correctly brownie

compile

and perfect if these interfaces had an

issue they actually wouldn't compile

through brownie here so we know that

they're compiling correctly but great so

now that we have an interface we know

that these interfaces compile down to

the abi

and we already have the address here so

to actually interact with the lending

pool now we can just do

lending pool

equals

interface

dot i

lending pool

and we'll add this lending pool address

blending pool and then we can return

lending pool so now we have a function

that goes through the lending pool

addresses provider from the ave

documentation and returns this lending

pool contract that we can now interact

with and we can even test this out by

just printing this landing pal address

in our script

so we'll do brownie

run

scripts

ave borrow network

mainnet fork

and perfect we we can see the address

here is printed out and there are no

errors so we know we're doing it right

so now that we have the actual address

what we're going to do now is we're

going to take this wrapped aetherium

that we've got this erc20 version of

ethereum and we're going to deposit it

into this contract just like what we did

in the user interface in order to

actually first deposit it we need to

approve this erc20 token erc20 tokens

have an approved function that makes

sure that whenever we send a token to

somebody or whenever a token calls a

function that uses our tokens we

actually have given them permission to

do so so that's the first thing that

we're going to actually have to do

is we're going to have to approve

[Music]

sending our erc20 tokens

and this resembles so since i know that

we're going to have to approve a lot i'm

actually just going to go ahead and make

an approve

erc20 token function similar as to what

we did with the get lending pool

so we're going to need to approve this

erc 20 so we're going to need to approve

this erc20 so let's go ahead and make a

function we'll call it def

approve

erc20 so how do we actually call this a

prove function on a token contract

well

as always we're going to need the abi

and the address of the token contract

same as always i told you i was going to

be saying this a lot now we could create

our interface ourself looking at all the

functionalities of the erc20 tokens so

we could go to eip20 look at the token

standard find all the different

functions and put them into our

interface

or we can go ahead and just cheat and

just grab it from my github repository

here

so i already have an ierc20.soul right

here

and we're just going to copy everything

in here and

add it in a new file called i yourc20

that's sold

and paste it in here so you can see

there are a number of different

functions in here

we can check the allowance we can check

the balance of different addresses

how many decimals a token has the name

the symbol we can do some transfers and

transfer from and then the function that

we're going to be using is this approve

function so right here we can already

see

the parameters this approved function

takes

we're going to need to have a spender of

who to approve can spend our tokens and

then how much they can actually spend so

if we come back over to approve erc20

we know that for input parameters we're

probably going to need an amount

a spender

address

the erc20 token address

so which token we're actually allowing

to spend

and then an account right or this is

going to be that from

account bit so we'll just have this be

passed as part of the function

parameters so let's go ahead and code

this let's first just do a quick print

line

so that people know what this

transaction is doing we'll say approving

prc20

token

and then we'll get the erc20 token by

saying e or c equals interface

same as always dot i e or c 20

and then we'll give it

whatever erc20 address that we pass to

this function

and now we can actually interact with

this contract and we can call that

approve function

so we'll say transaction

tx or again tx usually stands for

transaction

equals erc20

dot approve and we're going to approve

this spender

for

an amount

and then we'll say from

account we'll do tx.wait we'll wait one

block confirmation for it to finish

and then once it's done

we'll do print

approved and we'll return the

transaction

awesome so now we have an approved erc20

function that we can use to approve any

erc20 token so back up in our main

function we can run approve vrc20 for

some amount which right now we don't

have defined

the spender is going to be this lending

pool but the address of the lending pool

because remember lending pool is the

entire contract we just want the address

the erc20 address of course is going to

be the erc20 address and the account of

course is going to be our account

the only thing we don't have to find

right now is some amount which we can

make it really whatever we want to be to

keep things standard let's just go ahead

and do 0.1 so i'm going to make this a

global variable i'm going to say amount

equals

one

one two three four five six seven eight

nine ten one two three four five six

seven and we can go ahead and do

amount

we're gonna of course doing all these

zeros is from incredibly disgusting so

we're just gonna refactor to do from web

33 import web and then instead of always

and we'll just do web three three

two two

0.1 0.1 which is the amount that we

actually want and we'll say either

now we can run browning

run scripts ave borrowed a pie

network main net fork

and we can go ahead and see that our

approval function is working as intended

network that will always be doing this

fine

any type of

we can do so let's go foreign and change

our default network to mainnet for

mainnet so we don't have any network in

our browning let's go back to our ave

borrowing section now so we have

everything approved

now we just need to go ahead and deposit

it into ave

since we know we're probably going to

use this a lot too let's go ahead and

create a

deposit function since we have

everything approved we can now go ahead

and use the lending pool deposit method

and we can check the documentation here

or look on github or etherscan to see

what the parameters that it takes are so

i'm even just going to go ahead

and copy all this

bring it over here

so what we can do now

is we do lending pool

dot deposit

and then all these parameters let's go

ahead and walk through them one by one

so first thing is going to be the

address of the asset which we know

is going to be your erc20 address

boom

the amount

of the token which we can go ahead with

our amount variable

address on behalf of is just going to be

our account.address we're depositing

this collateral for ourselves

and then referral code so referral code

is so the referral code is actually

deprecated and workloads don't actually

work anymore so we're just always going

to pass 0 here and just to make sure we

know that this is what we're doing we're

going to go ahead and print

depositing

one two three

and then after we're done we're gonna do

print

the ted

and whoops looks like we forgot to add

that final dictionary here

of from

accounts

ah one more thing here let's go ahead

and do tx for transaction

equals lendingpool.deposit and we're

going to go ahead and once again we're

going to wait for one block confirmation

wait

one

transactions still being processed so

now if we run brownie run scripts ave

borrowed up high

we can see that this actually went

through fine

all right now that we have some

collateral deposited we can go ahead and

actually take out a borrow we can go

ahead and borrow some other asset the

question is going to be how much how

much can we actually borrow how much

should we borrow

what would result in a positive health

factor well maybe we should actually

pull off chain some of our stats how

much do we actually have deposited

how much collateral we have how much

debt we have and so on and so forth that

way in the future when we don't start

clean we can take some inventory of

where we stand with our collateral in

our debts at the ave documentation

we can go ahead and see this this

function called get user account data

this is going to return the user account

data across all reserves so it's going

to get the total collateral that we've

deposited in terms of ethereum it's

going to get our total debt in terms of

ethereum how much we can borrow the

borrowing power that we have the

liquidation threshold or how close to

that liquidation threshold will be the

loan to value ratio and again this

health factor this health factor is

obviously incredibly important because

if it drops below one or reaches one

users can call this liquidation call now

this function returns all these

variables but for now we really only

care about how much collateral we have

how much debt we have and how much we're

available to borrow so let's go ahead

and write a function that will actually

sort that out for us we'll call it get

borrowable

data

borrow a bull

data so let's go ahead and create this

def

get borrowable

data

and we're going to pass in the lending

pool as a first parameter and then the

account as the second parameter because

we're looking to call this function on

the lending pool from an account so

let's go ahead and just call that

function so we'll do lending pool

dot get user account

data

and we'll pass in account that address

because we look at the api again

all that it needs is a user's address to

get started here

and it returns one two three four five

six

variables so we can go ahead

and get all of them

with this tuple syntax here so we'll say

total

collateral eath

total debt eath

available

borrow eth

current

liquidation

loan to value

and then the health factor

so it's with this syntax here that we

can actually get all of these variables

with this one call and again this get

user account data is a view function so

we don't need to spend any gas all of

these variables are going to return in

terms of way so let's just go ahead and

convert these from whey to something

that makes a little bit more sense to us

so we want to get this available borrow

each so we can figure out how much we

can borrow let's get that

in terms

that we can actually understand so we'll

do fromway

available borrow eth in terms of ether

we'll do total

collateral eth equals web3

that from way

and we'll do total collateral eth

ether

ether

and then we'll do total

debt eth

equals same thing web3 dot from way

total debt eth

terms of ether

and let's even do a little printf

statement for each one of these so we'll

do print

f

this f allows us to put variables inside

the print function and we'll say

you have

total collateral eath

worth

of eath deposit 10.

we'll even copy paste that a couple

times and we'll change this one to

total debt eath

and we'll change this one to

available borrow eth

so we'll say you have

worth of ease deposited

you have total death eat worth of

f borrowed

and you can borrow

available borreeth worth of eath

and then we're going to go ahead and

return

again we're going to use this tuple

syntax so we can return two variables

and we're going to say a float

of this available borrow eth

and a float

of the total debt eth

the reason that we have to add this

float variable here is that without it

some of the math that we're going to try

to do later won't pan out as well so now

we have this function get borrowable

data we're going to pass the lending

pool

and we're going to pass our account here

since we're returning

the borrowable eth and the total debt we

can say borrowable

eath and then total

debt

equals that function right there so

let's go ahead and try this out

with

running run scripts ave borrowed a phi

pi

again

because in our config

we have a default network of mainnet

fork

things seem to be approving things seem

to be depositing and awesome

we have we have our output here we

deposited 0.1 worth of f we have 0 f

borrowed and we can borrow 0.8 worth of

f yes this is correct even though

we have 0.1 f deposited

we can only borrow

0.08 this is because the liquidation

thresholds of different assets are

different in this risk parameters

documentation here we can see

the different liquidation thresholds on

the different assets we can see that

ethereum has an 80

loan to value so with ethereum we can

only borrow up to 80 percent of the

deposit assets that we have

and

if we have more than 82.5 percent

borrowed will actually get liquidated it

also tells about the liquidation bonus

reserve factor and some other helpful

pieces in here as well but now that we

have this borrowable ether mount we can

go ahead and actually borrow some dye so

let's do a quick print saying

let's borrow now in order for us to

borrow some dye we also need to get the

conversion rate

we need to get die in terms of f so

we're going to have to use some price

feed here luckily we already know how to

work with chain link and how to get

price feeds ave uses the chain-link

price feeds as well so we're using the

exact same conversion rate tools that

avi is going to use so let's go ahead

and create a function to get us this

conversion rate we'll say the die to f

price

is equal to get

asset price and then here we'll pass the

die

f

price feed

this will be the address of the die

ethereum conversion rate let's go ahead

and create this function call it def

get

asset price

and the parameter needs is going to be

price feed address so the first thing

that we're going to need is we're going

to need to get this die f price feed

where can we get this

well as we know per usual we'll head

over to the chain link documentation

we'll go to ethereum price feeds we'll

find done

and we'll paste it into our config for

mainnet so we can go ahead and add the

die

f

price feed

in here and paste it into our config

again if we want to test the coven we

can obviously just scroll down

look for coven

find the dieth right here

grab that address

pop it in for coven

and then we can get this the same way

that we got the address of the web token

so i'm just going to go ahead and copy

this

paste it here but instead of having weft

token in here

we'll do die

f

price feed

and now we have a way to change the

price feed address depending on what

network we're on so in our get asset

price function we're going to do the

same exact thing that we always do we're

going to grab an api

and an address

to work with the contract so again we

can get the abi by just working directly

with the interface

so we'll say die

f

price feed

equals interface

dot

aggregator

v3 interface because this is the name of

the price feed interface

which again if we look in our interfaces

it looks like we don't actually have so

what we can do

is we can go to the chain like github or

as you guys are already starting to

figure out all my example code has all

these interfaces as well but we can go

right to the source too

what we can do we go here we go to

contracts

we're going to add source

we'll do

0.6 we'll do interfaces and right here

is the aggregator v3 interface so if we

want we can just copy this whole thing

move back over to our interfaces

new file and this file is actually named

aggregator v3 interface you could call

it eye aggregator v3 or aggregator v3

interface you could keep it with i

aggregate or v3 outsole to keep with the

convention that we have

or you can just call it aggregator

v3 interface dot sol

to keep in line with what the chain link

code is actually called them i'm going

to call mine aggravated v3 interface

you'll notice a couple different

projects have a couple different

conventions but now that we have it

saved we can do interface the aggregator

v3 interface and we'll pass it this

price feed address now this diet price

feed is going to be a contract that we

can call a function on again we can

always refer back to the get the latest

price documentation to see how to

actually work with it there's even some

python code here for working with it in

web 3. we're going to go ahead and call

this latest round data function which we

can also find in our aggregator v3

interface this latest round data

which returns a round id

answer started at ended at and answered

it around

all we're really concerned with is this

answer bit here so the way we can do

this is we can say latest price equals

die dieth price feed the latest

round data and instead of grabbing

all five of these one two three four

five

what we can do is we can actually just

grab

the price which is at the one index so

round id is at zero price is at one

started it's two et cetera

so we can just say

at the first index and then we can

return

a float

of

this latest price

we can even print

another printf statement

the die

f

price is

latest price

so let's go ahead and run this

and great we have the die f price video

which of course we know that looking at

this right now this isn't in the right

units we know the diet price feed has 18

decimal places so what we can do then is

we know that this number would be one

two three four five six seven eight nine

ten one two three four five

six seven eight

this number is really zero point zero

zero zero four blah blah blah blah blah

so maybe we don't want to return it like

so maybe we want to say the diet price

feed is and we add

a little bit of web3.pi to make this

make a little bit more sense so we'll

say web3

dot from

way

and we'll add this latest price bit in

here comma

ether

maybe we'll even do a converted

latest price which is going to be equal

to

web3 dot from way

latest price

ether

and we'll print that out instead

so let's go ahead and run this again

all right that looks a little bit more

accurate perfect

okay great now we have the die eat price

we're getting really close to being able

to borrow this actual asset and let's

even return this converted lated price

here just so that we're always working

in units that we understand

okay now we're getting somewhere now we

can calculate the amount of dye that we

want to borrow we can find this by doing

a little bit of math we're going to do

the reciprocal of the die eat price

times

our borrowable eath and just to be safe

we're going to times it by 0.95

so this line we're converting our

borrowable each

to

borrowable

die and then we're timing it by

95 percent we're timing it by 95 because

we don't want to get liquidated so we're

going to be a little bit more cautious

remember how we slid that sliding scale

around to make it safer and less safe

well the lower percentage that we

actually borrow maybe we even borrow 50

of our collateral the safer that we're

going to be so keep that in mind when

you're deciding how much to actually

borrow if you want to run this in a

production environment so now that we

have this amount data borrow let's even

print it out let's say print

f

we

are going to borrow

amount down to borrow

die and then

we're finally going to do it

now we will borrow

looking at the ave documentation we can

look at their borrow function and we can

see the api here let's go ahead let's go

ahead and call this function so we'll do

borrow transaction it's going to be

equal to

lendingpool.borrow

let's look at those parameters so the

asset that we want to borrow die address

so first we should get a die address

which we can once again we'll want to

put in our config

so we'll go over to our config

and we'll add

a die address or a die token here which

we can find on etherscan

token it looks like this is the token

right here so we'll copy this address

for mainnet remember if you want to run

this on coven you're also going to need

to have a die token for coven now on

test nets avi actually changes up where

the tokens for its test nets are

actually going to be so if we go to

their documentation we go to deployed

contracts

and we go to coven here you'll always

see this little flag thing pop up say

always ensure using the latest lending

pool address since coven is updated from

time to time it's going to be the same

thing if we scroll down for tokens they

have an up-to-date list of coven

addresses in a json file here so it

looks kind of gross but if we look up

die

we can see symbol die and the address of

die on the coven test net so sometimes

this does change so if you run into an

issue maybe it's because the die token

that you were working with on their

coventestnet has actually changed then

we're going to do config networks

network dot show active

diet token great now let's move on to

the next parameter

the amount which we just figured out

here

amount diet to borrow

which we do need to change back to whey

so we're going to do web3.2a

mount dye to borrow

ether

because right now amount down to borrow

is in our human readable version which

we need it in way

then our interest rate mode which is

going to be stable or variable stable is

where the interest rate will always be

exactly the same

variable will change depending on a lot

of different things going on with ave

for safety we're just going to go ahead

and add one here

then we're going to do a referral code

and on behalf of so referral codes no

longer exist so we'll leave zero it's

going to be on behalf of our self

so we'll do a countdown address

and then of course we have to do a from

account

then we'll wait for this transaction to

complete

and if we've done this right we should

have borrowed some dye programmatically

from the ave protocol so let's even

print

borrowed some die

and we can once again call our get

borrowable data function

since this get borrowable data function

will print out our new account

information for how much we borrowed so

let's go ahead and run this on mainnet

fork again

awesome so if we've done this correctly

we now see that we've borrowed some die

so we can see here we now have 0.1 worth

of f deposited

0.059999 worth of f borrowed

and we can borrow a little bit more

worth of f

this

0.75999 is actually

the die that we've borrowed so we've

deposited some eath and we've borrowed

some dye and obvious telling us how much

that dye converted to eat is there so we

actually borrowed 160 die

which is great all right we've now

learned how to borrow everything which

is fantastic let's go ahead and actually

repay that back so we're going to call

their repay function and let's just put

this into its own function called repay

all and we'll give it the amount that we

want to repay

the lending pool address and our account

so let's call

let's define

repay all or we're just going to repay

everything that we have

again we're going to add an amount

lending pool

and account

for parameters

so if we're going to pay back this

network first thing that we need to do

is actually call the approve function

i'm going to prove that we're going to

pay back so the first thing we're going

to have to do per usual is we're going

to actually have to approve that erc20

so

let's say how much

we're going to approve

web 3.2 way

amount

ether to the lending pool

and we'll grab it from the config

networks

network dot show active

and this is going to be the

die token again

and of course

with our account i believe our proof

erc20 already calls weight so we don't

have to call it here so once we approve

we're going to be using this die that we

borrowed to pay most of what we have

borrowed back now we're going to call

the repay function so we'll say repay tx

equals

lendingpool.repay

first we need the asset

that we're going to use to repay which

we're going to use config

networks

network dot show active

diet token the amount which is going to

be passed in here amount

the rate mode

which

we've hard coded to one

and the address on behalf of which is

going to be account

dot address

and then of course we always have to do

from account

then we're going to do repay tx

dot wait

we're going to wait one block

confirmation

and then we'll print

repaid

and if we've done all this right we'll

do one more print line saying

you just deposited

borrowed

and repaid

with ave

brownie

and chain link

all right moment of truth

let's see if this works

we did it repaid you just deposited

borrowed and repaid with ave brownie and

chain link awesome work now if you want

to what we can also do is we can see if

this will work

with our wallet address here so what i

can do is i can copy my address

go to coven ether scan

and paste it in here

and right now we can see

that i have a whole bunch of link and

some ether

what i can do

is actually test everything that we just

ran through on the cove intestine and

see

everything happen

right on this ether scan address so if

we've been following along correctly and

we've added contract addresses

appropriately

we should be able to run the exact same

script on the coven test net i'm going

to do one additional thing here though

i'm going to have us not repay so we can

see

us with a little bit of debt

so let's go ahead and run brownie

run scripts

ave bar to pie and we'll change to

network coven

and now it's going to take a lot longer

as we've seen before because we're

actually

making these transactions on a real

network whoops it looks like i got one

of the die f price feeds wrong for coven

so i can once again just go over to the

documentation

die

s

it looks like this is the real address

for coven

so we'll copy that

paste it in here whoops we should also

probably have some wet token so first

let's go ahead and run

our get wet script for coven

and we're going to change this account

to get account brownie

run scripts

from our helpful scripts that way we can

actually

that way we can actually use our wallets

correctly all right great so now we have

0.1 weft

and actually

again what we can do

is grab

this address here

add token paste it in

add tokens for the web token and now we

can see we have 0.1 with which is

perfect

so now that we have some width we can

run the borrow script ave

brownie run

scripts ave borrow

network coven

and wow we can see that everything went

through correctly and successfully

so since i actually commented out this

repay function we still should have die

in our address here in our wallet here

and again we can see that

by going to our brownie config

grabbing this dye token address

add token custom tokens next

ad tokens and we can see we do indeed

have 160 die in our wallet

we have no weft since it'll be in ave

now and we have borrowed die instead you

can also see that we now have this a

weft if we added it from when we were

working with the ui

we have this interest bearing with

instead of regular wrapped ethereum

let's look at one of these transactions

we can see

that our borrowed transaction

gave us some stable debt bearing dye and

also some dye so we owe ave some die

from this debt we got some debt we got

some dye and we gave out some ave

interest bearing dye to the rest of the

albe protocol you'll notice now if we go

to test.ava.com dash dashboard we'll see

exactly what our script just did we have

160 borrowed

and we have 0.1 eth deposited if we want

to repay

our funds we can do it

with our current collateral or from our

wallet balance

and you'll notice something if i try to

repay

everything from my wallet all the diet

that i've actually borrowed you'll

notice we don't have enough funds to

repay the full amount

this is because since we actually

borrowed a little bit we've include some

of that interest so we actually owe more

back than we originally borrowed that's

how the loans work so when you're

designing this repay functions be sure

to have that in mind you can also have

your repay be -1 to repay the entire

debt it's recommended to send an amount

slightly higher than the current amount

borrowed but in any case maybe we say we

want to do from our

current wallet we'll hit max but maybe

we want to actually just repay with our

current collateral we can go ahead and

repay the maximum amount again we could

do this all from the ui

we'll approve and this is exactly what

our repay function actually did and now

we're all repaid up if we go back to our

dashboard and we hit refresh we'll see

we just have a tiny bit of ethereum and

no more borrowed assets awesome you've

essentially learned everything that we

need to go through for here

this is a massive step forward in

teaching you how to become

quantitative defy wizards and build

really robust applications and really

robust financial applications in the

default world now something i want to

point out even though this isn't a

python course and we're teaching more

about solidity and smart contracts it's

still in your best interest to test

these functions

yes i know they're python functions but

it's still going to be in your best

interest to test them to make sure your

application always works as you expect

it to now i'm not going to go through

this testing suite that i put here but

it's a really simple testing suite to

test some of the different functions

that we created

it can be really helpful especially for

something like get asset price where the

math might be a little bit off and you

want to make sure it's correctly again

link in the description to seeing some

of these tests

this is actually going to be even easier

than that lottery contract that we did

since we're just testing python

functions

and again you can test these all with

brownie test

all right you are all doing

fantastically now is another fantastic

time to take a break go for a walk get

some food because our next session our

next lesson we're going to be learning

about nfts how to build them use them

and deploy them

look nfts are hot right now nfts also

known as

erc721s are a token standard that was

created on the ethereum platform nft

stands for non-fungible token and is a

token standard similar to the erc20

again erc20s like link ave maker all

those goodies that are found on the

ethereum chain an nft 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 one dollar is

interchangeable with any other dollar

one dollar 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 nfts those you nerds out there would

know like a pokemon would be a good

example of an nft your one pokemon is

going to have different stats different

move sets and isn't interchangeable with

any other pokemon or maybe a more

relatable one is like a trading card a

unique piece of art or the like so

that's what these nfts are they are

non-fungible non-interchangeable tokens

that for the moment are best represented

or thought about as digital pieces of

art that are incorruptable and have a

permanent history of who's owned them

who's deployed them etc now like i said

nfts are just a token standard so you

can actually make them do much more than

just be art you can give them stats you

can make them battle you can do really

unique things with them you can do

pretty much whatever you want with them

but right now the easiest way to think

about it and the most popular way to

think about it is by calling them art

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 axe infiniti sell nine plots

of their land nine plots of their unique

land for 1.5 million dollars we also saw

the original creator of the neon cat you

know this cap

sold for like 300 eth so like i said

they're just tokens that are deployed on

a smart contract platform and you can

view them on different nft platforms

like openc or 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 help and give a

good user interface so that's the basic

gist of it let's talk some more about

the standards the erc721 standard or the

nft standard this is the basis of it all

there is another standard that's

semi-fungible tokens the 1155 we're not

going to talk about that here but you

can check it out the main differences

between a 721 and an erc20 on erc20s

they have a really simple mapping

between an address and how much that

address holds 721s have unique token ids

each token id has a unique owner and in

addition they have what's called a token

uri which we'll talk about in a minute

each token is unique each token id

represents a unique asset so since these

assets are unique and we want to be able

to visualize them and show what they

actually look like we need to define

those attributes of the object if it's a

piece of r we need a way to define what

that art looks like if it's some type of

character in game we need a way to

define that character's stats in the nft

this is where metadata and token uris

come in so if you know anything about

ethereum you know that sometimes gas

prices get pretty high especially when

it comes to storing a lot of space it

can get really really expensive so one

of your first questions might be well

are they storing these images and and

these are pieces on chain and the answer

is sometimes back when they were coming

up with nfts and artists were deploying

stuff the eth devs and the artists were

like yeah art let's do that art i'm just

going to deploy this one megabyte image

onto the ethereum chain and oh god it's

so much a gas expensive how do i

totally find it

i don't know why it's not um it's not

delivered and they realize that if they

put all this art on chain it's gonna be

incredibly expensive so to get around

this what they did is they put in the

standard what's called the token uri

this is a universally unique indicator

of what that asset or what that token

looks like and what the attributes of

that token are and you can use something

like a centralized api or ipfs to

actually get that token uri typical

token uri has to return something in

this format like this it has the name

the image location the description and

then any attributes below now if you're

like me your first question would

probably be we paul from a single

source

seems pretty

centralized

this is a current limitation of the end

of the ecosystem 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 you lose your image you lose

everything associated with your nft

because of this most nft marketplaces

actually can't and won't read off

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 games with your nfts 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 pokemon 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 nfts and you're like wait this is

kind of a lot of information i'll make

it easy for you if you're looking to

render an image of an nft add your image

to ipfs add a metadata file pointing to

that image file on ipfs and then grab

that token uri and put it and set it as

your nft the chain link dnd article does

a great job of walking you through this

and showing you how to do this so be

sure to read that if you're looking to

learn how to do that so all the code

that we're going to be working with is

actually available for you in this

nft mix brownie mix it's an official

brownie mix and it allows us to deploy

these three adorably cute dogs

and there are two different types of

contracts that we're going to be working

with we're going to be first working

with a simple collectible and then we're

going to work with an advanced collect

the simple collectible is going to be a

very simple erc721 standard we're not

going to really add any bells and

whistles other than give it like a name

and then our advanced collectible is

going to take advantage of some of those

more advanced true scarcity features

that we were talking about so protocols

like avagochi and ethercards use

chainlink vrf to get verifiably random

numbers to create verifiably scarce nfts

something that's important to keep in

mind is that in the real world when

companies create trading cards there's

no way to prove how scarce or how

valuable these trading cards actually

are if we use a verifiable random number

then whoever is deploying these nfts

can't even control how rare these nfts

really are so we get this verifiable

scarcity and this verifiable rarity

which adds some value to the tokens if

you want to just go ahead and work right

from the brownie mix you can actually

just run brownie bake nft mix

and then cd into nft

and all of our code

is gonna be right in here we're gonna go

through and deploy and develop

everything from scratch because we're

going to actually take some previous

concepts that we've learned improve on

them and we're going to learn a lot of

nitty gritty interesting pieces about

making this hybrid smart contract

because these nfts really are a perfect

example of a hybrid smart contract they

have some off-chain component

interaction with a random number and

restoring their metadata with ipfs and

i'll explain ipfs a little bit more in

depth as we go on here

so let's go ahead and get to it i'm

going to go ahead and make a new

directory

called nft demo

i'm gonna cd into it

code

period

and perfect i have a blank project here

and you already know what the first step

we're gonna do is

is do brownie init to create our blank

brownie repository now let's go ahead

and create our first

contract we'll call this

simple

collectible

dot soul since this is going to be it

since this is going to be a simple

collectible a simple nft that we're

going to get started with now similar to

the erc20 this erc 721 standard

has a number of functions that we can

actually work with we can go ahead and

even look at the 721 the erc721

non-fungible token standard on the

eips.ethereum.org website and we can see

a sample interface and some sample

events and some functions and kind of

everything that we've grown to know and

love and once again instead of us kind

of recoding copy pasting all this from

scratch we're going to be using we're

going to be using open zeppelin's erc721

documentation for this

now we're going to be working with

version 3.x there is a version 4.x that

has come out using version 3.x of their

open zeppelin contracts is also i think

a little bit easier to explain but again

those who want to challenge yourself

definitely try their 4.x version so

let's go ahead and jump right into it

first we'll do our srspdx

license identifier

mit

then we'll choose our solidity version

we're going to use pragma solidity 0.6.6

but again most of this should work for

0.8 moving forward

and then we're going to go ahead and

look at the open zeppelin erc721

documentation

and we're going to go ahead and

grab this line right here

import open zeppelin slash contracts

token

erc721

erc21.soul you can even see

a sample erc721 that they give you and

this is actually going to be similar to

the erc721 that we're going to make so

we're going to go ahead and paste that

and of course since we're doing this at

opensupplement contracts we're going to

need to

create our brownie config

and same as always the pen

[Music]

then sees

it's going to be

open zeppelin slash open

zeppelin contracts

and again like i said we're versing

we're using version three

so

3.4.0 again and then we'll do compiler

sulk

remappings

and we'll say

at open

zeppelin

equals

this

and great let's even try to just compile

this right now browning compile

and perfect it has been compiled now

similarly to our erc 20 that we did with

open zeppelin we're going to do the same

startup here so we're going to say

contract

simple collectible is erc erc721

and this is how we're going to inherit

all of those functions

in the erc721 token standard here and we

can start adding r

and we can start coding our simple erc

721 now for our erc 721 we're going to

make it be a couple of these cute

adorable dogs so it's going to be one of

these three dogs for our simple

collectible we're just going to go ahead

and use the pug here so so you can use

any image that you want for this demo um

however if you want to just follow along

with us

we can just download this

dog and we'll call it pug create a new

folder

here called img and then i'm just going

to add pug.png to this img folder so

this is going to be the mft that we're

going to deploy we're going to deploy

this very simple pug for our smart

contract so we're going to be deploying

this pug this is the image that we're

going to use for our nft it's going to

be this adorable pug so let's go ahead

and create the rest of the contract for

this pug so the first thing we're going

to make is our constructor

it's going to take no input parameters

it's going to be a public constructor

and then we're going to go ahead and use

the erc721 constructor

which if we look at the documentation

we give it a name

and then a symbol

we're going to use the erc721

their parameters

which is going to be a name which we're

going to say is doggy and a symbol

which we're going to say is dog and

perfect

that's all i really need to do for the

first part this nft contract is actually

what's known as a factory contract

there's a main contract and in it it has

a list of all the nfts and the owners

that are of this type of nft so in this

example all the type of nft is just

going to be this pug and it's just going

to be this dog and we actually need a

function to mint new nfts based off of

this pug now we can absolutely have an

nft factory contract that only creates

one single nft but we're going to use

this factory implementation to create

multiple nfts we're going to do it with

a function called create collectable

this will create a new nft and assign it

to whoever called this function so

anybody can come here and create a new

puppy for themselves or in other words

adopt a puppy so we're going to say

function

crate collectible

public

and we're going to say returns

you went 256.

you'll see why we need to do this in a

minute now when we create this

collectible all we're doing is we're

assigning a new token id to a new owner

and if we look at the open zeppelin

erc721

github

we can see they have this safe mint

function this is the function that they

use to

mint or create a new nft

this function it's it takes a new

address 2 which is going to be the new

owner of the nft and a token id every

nft in this factory contract has a

unique token id we're going to have our

token ids start from 0 and and just

increment every time we have a new token

minted this safe mint function calls

this safement function which calls this

minting function so

if you're looking at the code here

this mint function is really the the

function that calls and creates this nft

you'll see actually that they just have

two mappings that they update

they update this owner's mapping

which is just a mapping of token ids to

the owners of the token ids

and then they update this balances

mapping

which is a mapping of owner address to

the token count so the number of tokens

that an owner actually has and that's

all that's happening when we call this

mint or in our case safement function

the difference between safe mint and

mint

is safement checks to see if a token id

has already been used or not and this

way we don't actually override who owns

tokens and who owns tokenids so we're

going to use the safement function so

first we need to think okay well we're

going to need to a way to count these

token ids so that every single person

has a unique token id

so let's create a global variable un256

public

token counter

and we'll initialize it tokencounter to

zero of course

this is the same as initializing token

counter to zero

but let's just make it very explicit so

when we create a new collectible

we're going to say uwen256

new token id is going to be equal to

this

token counter and we're going to iterate

this every time we mint a new token so

for example we're going to iterate that

in this create collectable here so new

token id equals token counter we're

going to call

this safement function since we're

inheriting it from open zeppelin's

erc721 we need to give it this new nft

and owner which is going to be

message.sender so whoever calls this

function

and then we need to give it

a unique token id which is going to be

this new token id now whenever we mint

one we're going to want to

increment this token counter so then we

can say token counter

equals token counter plus one

and we can then return

this new token id so we'll return the

token id of the token that we just

created and boom if you're looking for

an incredibly minimalistic contract to

deploy nfts this is all that you need so

we can run brownie compile

to make sure we did everything right

and project has been compiled we can see

it in the build so great job obviously

this might be a little dissatisfying to

you after the breakdown that we just

gave how do we view this token what does

this token look like i thought we wanted

this to be a doggy how do we know that

this looks like a dog how do we get this

image on the blockchain this is where

metadata is going to come into play now

if we look at the original erc 721 there

is this part called the metadata

extension is optional for erc 721 smart

contracts as we've talked about anytime

you make a transaction on chain it costs

some gas even very tiny amounts of data

can cost more and more gas images are

much bigger than these little bits of

data here and they can cost a lot more

gas

so when this standard was being created

the developers kept this in mind and

knew that storing entire images and

entire gifs and entire videos on chain

was going to be incredibly costly so

they added this piece about metadatas

and token uris the token uri is a

distinct uniform resource identifier for

a given asset this is an example of a

uri and the metadata that we're going to

be demoing today a uri is just a unique

resource identifier so this can be

something like https or ipfs or any url

string that uniquely points to some

metadata your metadata file is going to

look like this

it's going to have a title

for the title of the nft

can have a type

and it can have all these different

properties or stats or attributes for

example we're going to have our pug nft

which is going to be defined like this

it's going to have a name as pug

description is going to be an adorable

pug pup and it's going to have what's

called the image uri which defines what

the token actually looks like and if we

copy paste this into another browser

we get returned this it's this token uri

with this metadata json object that's

going to enable different nft platforms

to actually render our nft so this is an

example of what this pug is going to

look like on different nft

marketplaces like openc

platforms like openc understand that

they need to show this image they need

to use this name they need to use this

description and have these traits so if

we look back at this

nft on openc we can see the name is pug

we can see the description here if we go

to levels we see its cuteness as 100 out

of 100 now this of course leads us to a

really interesting point if we're

storing the image off chain then how is

this image decentralized if we're

storing this image off chain how can we

guarantee this nft is going to stay

forever now this leads us into a little

tidbit about storing data on blockchain

as of current recording storing a lot of

data on chain can get incredibly

expensive the more data that you store

the more transactions that you have to

make to store that data on chain and the

more gas that you're going to have to

spend at the time of recording ethereum

is about little less than 900 gigabytes

in size if a ton of people were to put

full videos or movies or

massive images ethereum would grow

exponentially out of proportion and this

would become unsustainable for the

blockchain network as a whole so

ethereum isn't great for actually

storing a ton of data it can store a lot

of data but it's a lot better for doing

the logic and the smart contracts so

there are a lot of different platforms

that are actually working on this

problem of storage these platforms allow

people to store data in a decentralized

way that isn't going to exponentially

explode the size of ethereum or

different smart contract platforms the

decentralized storage methodology we're

going to work with is going to be ipfs

or interplanetary file system and this

is where we're actually going to store

our image and this is actually where

we're going to store our image so that

nft marketplaces know what our nft looks

like now here's what some protocols do

some protocols just set up a server and

set this token uri to instead be from a

decentralized service like ipfs and use

just maybe their own centralized server

this is obviously a massive issue

because if their server goes down or if

they want to change the

image or they want to change the stats

all they have to do is change it in

their server and this is why a protocol

like ipfs is going to be a lot easier

quicker and more decentralized version

of doing this the full solution is going

to be using something with ipfs and

filecoin but easy solutions to do that

are still being built out so for now

we're just going to use ipfs because

it's free it's quick and it's easy and

it can be expanded to combine with file

coin to be even easier to work with now

something else that i want to touch on

too when it comes to this metadata right

now all these nft marketplaces only know

how to pull attributes

from this token uri now if we want to

build really cool nfts that can interact

with each other having some attributes

or maybe some like like attack stats or

attack moves like in pokemon for example

or trading cards we can't just store

these in this token uri

because the blockchain doesn't know

anything about this token uri so we

actually need to store these attributes

on chain i'm really hoping in the future

a lot of these nft marketplaces are

going to get better at

and pulling metadata from on chain but

now right now any attribute that we give

our nfts we actually have to reproduce

in the token metadata and the token uri

as well so we've just learned a lot

about metadata ipfs token uris and

everything like that let's update this

simple nft to be able to render on openc

and render on these nft platforms

because right now if we were to deploy

this nobody would know what this doggie

looks like so let's give it a token uri

so in this crate collectible let's do

string

memory

token uri

and after we call this safemint function

there's another function that we're

importing

called set

token uri

and we're going to set the token uri

for the token id

and we're going to give it this token

uri

this will allow our nft to actually have

an image associated with it that we can

actually see

so let's go ahead and so let's go ahead

and create a script that's going to

deploy this nft factory contract and

then create us a collectible

so we're going to do new file we'll call

it deploy

and create

dot pi and let's jump into our script

so we'll do def main

first we need to start with an account

and

once again we can go ahead and create

helpful scripts

dot pi

we can go ahead and copy paste this get

account function in here if you want

but of course since we added this config

wallet from key we're going to go to our

browning config we'll add wallets

from key

and we're going to grab our private key

environment variable

since we're using a private key

again

we're going to create a dot env

and we need our to export private key

and we're also going to need to export

our web3

infuro

project id

so we can just copy paste for my last

project the private key web3 inferior

project id and our etherscan token so

that we can actually verify this on

chain and we'll add a new file

init

dot pi

so that older versions of python know

that this is indeed a package

so we'll go ahead and do from

scripts

dot helpful scripts

import

get account now all we have to do

is import our simple

collectible

and run

simple

collectible

equals

simple collectible

dot deploy and if we look ours and if we

look at our simple collectible we have

no constructor parameters here so we can

just do from

account

and now this will have our simple

collectable deployed now we need to

actually call this now we actually need

to call this create collectable function

and we're going to pass it a string

which is going to be this token uri

i'm going to go ahead and use this

sample token uri that is included in our

nft mix so if you're looking to get this

token uri

look up nft mix patrick collins

hopefully the github will show right up

and we can just go right to the scripts

in here

it's in the simple collectible folder

create collectable

that's the bigfoot we're going to grab

this and in our script we're going to do

sample

token uri

equals

this

now when you paste this token uri in

your browser if you can't see it you

might have to add something like ipfs

companion to your browser like this

some browsers don't natively have it so

so there is a link to ipfs companion for

this project in the github repo but now

that we have a token uri we can call

this create collectable function so

we'll do

transaction

equals

simple collectable

dot create

collectible

and we'll pass in this sample token uri

and then of course we'll do from

account

we'll do tx.weight we'll wait for one

block and then if we've done this

correctly we'll actually be able to see

this nft

on an nft marketplace like open c

so let's do a quick print line here

we'll do print

awesome

you can now

you can view your nft

at

and we'll do this in fstring

and this is where we're going to put the

openc url for this ring b

so we're going to say open c url

which is going to be equal to if we pop

over to open c if we pop over to this

open c pug here on the ring p test net

we can go ahead and grab

this first start of the string so it's

going to be https testnets.openc.io

assets and then this is the address of

the contract

so we can say openc url is going to be

this slash

and we'll put this little brackets here

slash and then another one of these and

this is because the url for here

testness.openc.io assets

it's the contract address and then the

token id on the end here so this is what

it's going to look like

so in our print line awesome you can

view your nft openc.format

simplecollectable.address

comma

and we do simplecollectable dot

token counter

minus one

for the most recently deployed one and

then we'll run this now

brownie run scripts

deploy and create

network

rink b

and awesome we get this print line here

saying

awesome you can view your nft at https

testness.openc.io just keep in mind

obviously for mainnet we can't use this

testnet.openc.io

but

assets the address of the nft contract

and then the token id as well

so if we go ahead

and click this and it looks like it's

already actually been rendered here in

openc we could even go ahead and hit

refresh metadata just in case it doesn't

show up right away but it looks like for

us it did show up right away which is

awesome some other kind of fun parts

about openc is if we go to our profile

here

we'll actually be able to see all the

nfts that we own on this testnet i've

actually deployed this this doggie twice

here once to test and then once i

actually do it great we've created our

simple collectable of course no project

is complete without some tests so let's

create some tests since we're also going

to be doing an advanced collectible i'm

going to skip the integration test and

i'm just going to write a really simple

unit test so we'll create a new folder

we'll call it unit

and in here we'll do a new file

test

simple collec

so let's create our first test we'll do

def test can

create

simple collectible

we'll just make sure that we can

actually create a simple collectible now

we'll make sure that this is our unit

tests so we'll do from scripts dot

helpful scripts

import local blockchain environments

and then we'll do if

network.showactive

not in

local blockchain environments

pi test.skip

so of course we need to do from

brownie

import

network

and then also import pi test

now something that we could do here is

actually in our test we could go ahead

and even test our scripts by importing

uh deploy and create here and testing

this we do something like return

simple collectible

and in our test then we could do

from scripts

dot deploy and create import deploy and

create

and then back in our deploy and create

script we can modify this a little bit

instead of main here we'll call this

deploy and create and then we'll have

our main function

just call

deploy and create

and you'll see ronnie runs scripts

deploying create to pi if we go ahead

and run this again we can just run this

on the development network real quick

instead of on ring p you'll see that

this does also work obviously we won't

actually be able to see our nft on openc

because this is deployed to the brownie

temporary ganache chain as opposed to a

persistent wrinkly chain in our test

here

we could then just do we just run

simple

collectible

equals deploy and create

and then we'll do an assert here we'll

assert

simple collectible

that owner of zero

is going to be equal to get account

and then we'll also import

get account

so we can run brownie test

make sure this works and perfect now

this was all fun and dandy but there's a

couple of things that we didn't go over

and that we didn't do so let's create a

quick readme.md for a couple of notes

so number one

we didn't upload an image

to ipfs ourselves so we just used a

token uri that was already existing

right we didn't actually upload

something to ipfs we didn't go over why

is ipfs

decentralized we didn't really talk too

much about what ipfs is number three

anyone can mint an

nft here

with any type of stats right it's not

going to be it's not verifiably scarce

or random right this isn't that cool so

we want to actually build an nft project

that has all these pieces where we

upload the image to ipfs ourselves we're

going to talk a little bit more about

why ipfs is decentralized and it's the

preferred solution for storing nft

metadata and we're going to make our nft

more verifiably random and verifiably

scarce like for things like ethercards

and avagoji let's go ahead and do this

project again but we'll integrate the

chain link vrf

to make this nft verifiably scarce and

verifiably random and then we'll also

teach you guys how to upload to ipfs and

work with ipfs ourselves so let's go

ahead and do this so let's create a new

file in our contracts and we'll call it

advanced

collectible dot sol and what we're going

to do here is we're going to make again

an nfc contract

where the token uri

can be one of three different dogs so if

we look at this nft mix in the images

section there's a pug a shibba in you

and a saint bernard or one of these

three dogs

we're gonna make it so that when you

mint one of these nfts you're gonna get

you're gonna get a random one of these

three dogs now i'm not gonna go over

stat generation

and like creating battle battling nfts

or really games out of these nfts if you

guys wanna see a version of those

contracts check out this dungeons and

dragons nft there's a link in the github

to see this and it actually creates

characters that can do battle and have

like stats and attributes like

um like attack

and different things you'd find in

dungeons and dragons this one's done

actually with truffle as opposed to

being done with brownie but all the

contracts are going to be the same other

than this migrations.soul so if you're

looking to check this out you absolutely

can it is a ton of fun and they have

some really cool images as well so be

sure to check that out if you're looking

for more anyways here's what we're going

to be looking to do we're going to make

an nft contract where the token uri can

be one of three different types of dogs

and it's going to be randomly selected

so let's go ahead and do it so first

again we're going to do this spx license

identifier right at the top so we can go

ahead and put that there

and we're going to even use

same solidity version and we're going to

use open zipline again so

we can literally just copy and paste

that from our last project now we're

going to create our contract

advanced

collectible

we're going to say is erc

721

great

and then since we're going to want to

work with chain link vrf to get a

provably random nft we're also going to

want to import

at chain link

contracts

slash src

v0.6 vrf con

consumer

base dot sol

and of course that means we're going to

go back to here and we're going to add

smart contract kit

slash chain link

brownie

contracts

at 1.1.1 and then we're going to go

ahead

and add the remapping in

we'll say

at chain link equals

boom

awesome so we've imported the chain link

bit

our advanced collectible is erc 721 and

it's going to be vrf

consumer base so same as always let's go

ahead and start with the constructor we

know from our lottery smart contract

that we're actually going to want to

parameterize a lot of these pieces for

working with the vrf coordinator for

working on different chains and

different test nets

so we're going to do address

vrf

coordinator we're going to do address

link token

bytes32

keyhash

and we can always head back over to

docs.chain.link go to get a random

number just in case we forget what some

of the parameters are vrf coordinator

link token keyhash and fee

great you went 256 feet

i will make this

public as well

add a little curly bracket there

and we can go ahead and start doing the

rest of this of course we need to do the

vrf consumer based constructor and the

erc721 constructor

so

vrf consumer base

is going to be this vrf coordinator

and this link token

and the erc 721

we could paramore ties these as well but

we know it's going to be a dog so we'll

do doggy and the symbol of dog

which is the same

as our simple collectible here we know

we're also going to need to do this

token counter bit

so we'll do

you want 256

token counter

and right in here

we're going to do

token counter

equals zero of course we're going to

need a key hash

so let's make this unit 56 public token

counter

excuse me

we're going to do a bytes32

public key hash

and we're going to do

a uint256

public fee

and we'll set

key hash

equals

key hash

and fee equals

fee

great so this is a combination of a lot

of the stuff we did in our lottery smart

contract and some of the pieces that

from our erc 721 we need the key hash

the fee vrf coordinator link token all

for the vrf consumer base

oops i should put a extra quote here and

then we need dog doggy and a token

counter for erc 721 so now

we're going to create

our function create collectable

so we're going to do function

create collectible

and again we're going to do a string

memory token uri

but this time in our python scripts

we're actually going to define where

we're getting this token uri from and

we're going to create it ourselves but

we're going to make this public

and it's going to return

a bytes32 remember way back in our

lottery when we did this event requested

lottery winner when we called the

chainlink vrf we're going to do a

similar thing here where we're going to

make an event for whenever we request

one of these new dogs and that is also

what we're going to return we're going

to return that request id here so since

we're using the chainlink vrf here we

can go ahead and call that request

randomness function which again

over the docs.chain.link this is

imported from the erc721

and then in that request and receive

model it's going to call back with our

fulfill randomness function we're going

to need to do a couple of different

things here because we want the user who

called create collectable to be the same

user who gets assigned the token id

so first we'll do bytes 32

request id equals request

randomness

and we're going to pass obviously the

key hash

and the fee

this is going to create our randomness

request to get a random breed for our

dogs so let's go ahead and just define a

little bit of the fulfill randomness

function so we can figure out how we're

actually going to pick a random dog well

the first thing that we're going to need

is we're going to need some definition

of what the different breeds that the

dog can actually be and again similar to

the lottery we're going to create a new

type called breed using the enum

so we're going to do enum breed

and then we're going to give it three

types

pug which is going to be state 0

shiba inu which is going to be state 1

and say bernard which is going to be

state 3. so our breed is going to be one

of these three breeds here so then in

our function

[Music]

fulfill randomness

when we get that random number back we

can use that random number to pick one

of these three breeds

so of course we need to have a byte32

request id and uint256

random number

and we're going to make this internal

override so that only the vrf

coordinator can call this and what we're

going to do now is we're going to select

a breed based off of this random number

so we're going to say breed

breed which we're saying

this breed variable is of type breed

it's going to be equal to

breed generated from that random number

mod 3.

since we have one two

three different breeds awesome so this

is how we're going to get our random

breed however we do need to assign this

breed to its token id so now that we

have a random breedback how do we

actually go ahead and assign this well

we're going to have to create a mapping

to do this it'll look something like

token id

2

breed we're going to have to get our

token id somehow

and we're going to have to equal it to

the breed

so then our first question is okay well

in order for us to assign this breed to

the token id

how do we actually get the token id well

we're going to grab the token id by

doing

uin256

new token id

equals

token counter

and then

we'll just set the token id to breed

using this new token id equal to the

breed so we're going to want to make

this token id to breed

mapping up here

so which we can do

mapping

uint256

map2

breed

and we'll call it

tokenid to breed this way each token id

is going to have

a very specific breed based off of this

mapping's results perfect okay what else

do we need in this fulfillment we need

to mint the nft and we need to set a

token uri well when we minted it before

we call this safement function however

message.sender here is always going to

be the vrf coordinator since the vrf

coordinator is actually the one calling

this fulfill randomness so we can't

actually have this just be

message.sender we need to figure out how

we can get the original caller of create

collectable here how do we get

the original message.sender of create

collectable

well the answer there is actually going

to be in another mapping when we call

create collectable we can create a

mapping of request

id

to

[Music]

sender and this is going to take the

request id as a key

and then whoever sent it as the value

so we're going to create this new

mapping at the top

and then actually let's make this other

mapping public as well

we'll do

mapping bytes32

to

address

we'll call this public

request id

to

sender now in our fulfill function the

same request id that requested the

random breed is returned so what we can

do is we can say address

owner

or sender

is going to equal

request id to sender

of request id

and then this address owner is who we're

going to safemint the nft to and of

course while we're matching up the

functions we don't want to forget to

always do token counter equals token

counter plus one at the end

awesome now we still need to set the

token uri here

so back in our advanced collectable

we're gonna have to do this set token

uri at some point so let's actually

think about this for a second

we're only going to know breed of our

dog once this random number is returned

and we know the breed of the dog is

going to be one of these three breeds

it's going to be a bug a shiba inu or a

saint bernard and let's actually for now

let's even just go ahead and add those

three images to our project here create

a new folder

we'll call it image

and you can put whatever images you want

here i'm actually just going to download

i'm actually just going to download the

three images right from

the nft mix boom and now i have my pug

my shiba inu and my saint bernard in

here so anyways it's going to be a pug

shipping in you or a saint bernard here

we're only going to know what the breed

is once the random number is returned

and the breed is actually going to

govern if it's a pug ship in you or a

saint bernard so we technically could

actually just get rid

of the input parameters for crate

collectible since there's going to be no

token uri initially created what we

could do is we could create a new set

token uri function that sets the token

uri based on

the breed of the dog for the simplicity

of this project we're actually just

going to create our own set token uri

function that we're going to update

based off the breed of the dog a

challenge for you after we finish this

project is to make this even more

decentralized and have the fulfill

randomness function actually

be the one to decide what the token uri

is but for now in our fulfill randomness

function we're going to skip setting the

token uri and we're actually going to

call it in a separate function we're

going to create our own

function called set

token uri

and we're going to pass it a uin256

token id

a string

memory

token uri

and we're going to make this a public

function once this fulfill randomness

function is responded the breed of the

dog is going to be set right this token

id to breed is going to say hey this

token id

now is associated with this breed which

is going to be pug shiba inu or saint

bernard all we want to do then is now

that we have the on chain metadata we're

just going to reciprocate that with the

off chain metadata so we're going to

need three token uris for those three

dogs we're going to need one for pug

ship inu and then obviously saint

bernard however we want to make it so

that only the owner of the token id can

actually be the one to update the token

uri

so we can use a require function for

this we can say require and we're going

to use an imported open zeppelin

function called is approved or owner

message sender

token id

and we're gonna do comma here

erc 721

caller

is not owner nor approved

this is approved or own a function if we

go into the erc 721 github for open

zeppelin

we can find this this function is

approved or owner which checks the owner

of the erc721 of that token id and it

makes it so that only the owner or

somebody approved to work with this

token id can actually change the token

uri so then we're just going to call

that function called set token uri of

the

token id

and the token uri now we're actually

manually going to be the ones to call

this set token uri once the breed has

been decided we could of course like i

said use a mapping at the top that

automatically routes it there but so

that we can experiment a little bit more

and learn a little bit more about ipfs

we're gonna leave it a little bit more

general like this and perfect this is

pretty much the majority of what we're

going to need for our erc 721 contract

obviously we still need to work with

ipfs and getting our token uri but for

the most part this is everything that we

need now i do i am going to introduce a

new best practice here whenever we

update a mapping typically a good best

practice is going to actually be to omit

an event so let's create an event for

each one of these mapping updates we'll

call it event

requested collectible

and we'll do a bytes32

indexed

request id

and we'll also do a

address

requester this requested collectible

event is going to be omitted when we

request id to sender because we're

updating the mapping here this is also

going to be really helpful when we run

our tests so we can get this request id

similar to what we did with the lottery

so down here we're going to do omit

requested collectible let's collect

dibble here

let's use an i instead of an a here

collectible

and we'll pass it

this request id

and then message.sender

we also update a mapping down here with

tokenid to breed

so we're going to do a new event

we're going to call event

breed assigned

and we'll do uint256

indexed

token id

and then we'll do a breed

breed

and then when we assign the breed here

we're going to omit

breed assigned

with

new token id

and breed

so let's see if we did everything right

let's do brownie compile

looks like we have a quick error here

did you mean fee or fee

let's

do a quick underscore there

now let's try to compile

much nicer all right great let's move on

all right so now let's take a little

look-see at our scripts here so we have

this deploy and create script which is

going to work for our simple collectable

so let's go ahead and actually give them

both their own folder so we're going to

do a new folder

we'll call one simple

collectible

and we'll do another new folder

called advanced

collectible and we'll grab this original

deploy and crate and we'll place it into

this simple collectable folder here

awesome

now if we wanted to run this we would do

brownie

run scripts

simple collectible deploy and create and

we can go ahead and test this out on our

local ganache here

and cool looks like it's working

correctly great so now let's create our

advanced collectable script and a lot of

what we're going to do is going to be

the same as this simple one deploy and

create so i'm actually going to copy

this

we're going to create a new file called

deploy and create

dot pi we're going to paste everything

in here but we are going to change a

couple things up so let's do a little

bit of refactoring first so this opencrl

we're going to be accessing in a couple

different scripts so we're actually

going to take this

copy it

get rid of it in our deploy and create

here

and we're going to move it to our

helpful scripts

and place it under here openc url equals

this script right here

and now what we do in our simple

deploy and create

is we're going to do from

scripts.helpfulscript

import

openc url

we're going to delete that here

so now in this script

this openc url is going to come from our

helpful scripts which is what we want

and we're going to do the same thing for

our deploying create for advanced

okay great so i've now copied and pasted

all the code from deploying create into

this deploy and create for our advanced

collectable so let's go ahead and modify

this now

so instead of from brownie import simple

collectible we're going to import

advanced

collectible

and we're going to do the same thing

down here

and i'm just going to go ahead and

delete everything

before this we're going to change this

to advanced

collectible

and awesome okay this is going to be our

starting point and we actually we can

even get rid of this sample token uri

great so this is going to be our new

starting point we've done a little bit

of refactoring now openc url is going to

be in the helpful scripts we're pulling

in advanced collectible instead of

simple collectable and the rest applies

we're still using our get account to get

the account and now we have this

advanced collectible equals

advancedcollectable.deploy

of course

our advanced collectable has a different

constructor

it's got a vrf coordinator a link token

a key hash and a fee so we're going to

have to add those

as the parameters in here we want to

work with ringpi for this because the

openc marketplace right now for test

nets only works with rinkby so that's

why we're going to work with ringby here

so let's get started and just grab those

ringpie addresses first

so our advanced collectable needs a vrf

coordinator and a link token so if we

head over to the chainlink documentation

we go to contract addresses for the vrf

we can scroll down to

rank b

we'll grab the vrf coordinator here and

same as before

we'll jump into our browning config

we'll do

networks

rinkaby

and we'll do vrf

core did nator

we're also going to need the

link token here

so we'll do link token

we need the key hash

key hash

and we need the fee which is going to be

0.1 link which we can do fee as one one

two three four five six seven eight nine

ten one two three four five six seven

which can be 0.1 you can of course just

copy and paste brownie configs over to

different projects because

because these values are always going to

be the same now on our advanced

collectable deploy and create we can go

ahead and add those variables in here

since we're going to be interacting with

actual contracts that are on chain and

we're going to want to be able to flip

back and forth between the mock versions

of them we're going to bring back that

get contract function that we used

before this is the function that's going

to be smart enough to know if we need to

deploy a mock or just grab from an

actual contract i'm going to show a

little fast forward of me rebuilding

this function but feel free to copy and

paste it from our last project now

something that we do need to talk about

though is our deploy mocks function the

syntax here is going to be basically

exactly the same however we do need to

deploy a couple of mocks so make sure

you have these in your deploy marks

function

specifically we're going to need a mock

link token and a mock vrf coordinator

and again feel free to just grab these

from our last projects

and then of course be sure to add your

contract to mock dictionary where the

link token is mapped to the link token

and the vrf coordinator is mapped to the

vrf coordinator if you guys look in the

github repo there's a couple try catches

there that just make it a little bit

nicer for error handling

but this is basically the entire script

so now what we can do we can go back to

our advanced collectable deploy and

create

import this get contract from our

helpful scripts

and we'll just replace this with get

contract

vrf coordinator

get contract

link

token and then for key hash and fee

since these don't really matter these

can be whatever we want and these aren't

really contracts

we can go back to our config

we'll add

the development network and we'll just

add key hash

and fee

and again since it's just testing we can

just go ahead and make them exactly the

same as ring b

done a lot of work now let's go ahead

and run this on the development network

again so we'll do brownie

run scripts

advanced

deploy and create

no network so it's going to default to

development let's see what happens here

and awesome so we can see we actually

did a couple of things here

so first we deployed this mock link

token

then we deployed our mock vrf

coordinator

we finished that and then we deployed

our advanced collectible all on a local

network so let's go ahead and continue

here once we deploy this code we're

going to want to fund this contract with

some link the reason we're going to want

to fund it with some link of course

is that we can call the random number i

like to have my funding with link also

in a function so we'll do fund with link

and we'll give an address

advancedcollectable.address

and let's go ahead and create this

function in fastforward we're going to

fast forward this as well but feel free

to copy and paste your fund with link

functions from past projects or if you

want to slow this down and follow along

feel free to do that too

let's go back to our deploy and create

we now have this fund with link that

we're going to do right here and then

all we have to do now

is call our create collectable function

here so we'll just do advanced

collectible

dot

create collectible

of course

from

account

and we'll do

creating tx

we'll wait one block confirmation

and then we'll print

your token has been created

so we are definitely going to want to

test this because we have a number of

custom scripts here right

so let's go ahead and just do a manual

test

so we'll do brownie

run scripts

advanced collectible

deploy and create and we'll do it on a

development network

whoops we got to add ether here sorry

about that in the web 3.2 way one ether

so let's go ahead and run this script

again

and all right it looks like everything

worked everything was deployed new token

has been created

great this is fantastic now ideally

before we do an integration test we

would of course write some tests but i

want to teach some things that are

easier to demonstrate on an actual test

net so we're going to go ahead and

deploy this to an actual test dent

before we write our tests so we're just

going to run the script again

and do dash dash network

rank b

and awesome a new token has been created

so what we can do

is we can grab the contract address once

again

we'll paste it into the rank b ether

scan

and we can see everything in here we can

see we've given it a little bit of link

we can see our two function calls one is

going to be the contract creation one is

going to be create collectable

our contract has already been auto

verified actually because i verified

this contract on rank b already and

etherscan says ah this bytecode is the

exact same of another contract that

we've already verified and if we go to

read contract and we go to token counter

we'll see

one token has been created

we've actually created our first token

now what we can do in our advanced

collectable scripts we can create a new

script and just call it create

collectable

dot pi

and in here we'll just create a

collectable

so well all we have to do is we'll do

def main per usual

we'll have to do from

brownie

import advanced

collectible

we'll import accounts from our helpful

scripts

we'll import

fund with link

in our main function we'll do account

equals get account

of course we need to import this as well

for my helpful scripts

then we'll do

advanced

collectible

equals

advanced collectible minus one because

we just want to get the most recently

deployed we'll fund this contract with

link so we'll do advanced

collectible.address

and we'll also choose an amount here

we'll just do web3.2

way

of 0.1

with ether

that means we also have to do from web3

import

web3

then

we'll do transaction

then we'll do

creation transaction

equals

advanced collectible

dot create

collectible

from

account

we'll do creation transaction dot wait

we'll wait one block confirmation

and then we'll print

collectible

created

oops sorry i actually don't have to

import account here or accounts excuse

me

and sorry this actually needs to be

amount equals excuse me

now let's go ahead and run this and what

we're going to do

is we're going to fund our advanced

collectible with link which is 0.1 link

and then we're going to create a new nft

awesome collectible created so if once

again

we take this address

go back over to etherscan

do a quick refresh here

we go to our contract read contract

we'll look at the token counter it may

still be one so you might have to give

it a second for the chain link vrf to

respond

once the chain vrf responds we'll see 2

in here we can also check the token id

to breed

if we look at 0 with 1 we'll see the

breed

is 2.

and if we look back at our contract

the advanced collectible without soul we

know that if the breed is two that means

it's a saint bernard

see the token id of one

it has a breed of one so it got randomly

assigned a shiva inu

awesome so we have tokens and they're

get randomly assigned breeds fantastic

as you can see we're doing kind of a lot

of manual testing work here right so

what we're probably going to want to do

instead is you guessed it automate these

tests

now go ahead and want to deploy dance

import that deploy script that we just

wrote

so we would do

from scripts

dot advanced collectible

dot deploy and create

import deploy and create

and then all we have to do is call

deploy and create

in this function we'd probably want to

then return the advanced collectible

contract so we can make sure that we

actually get what we want here

so we'll say advanced collectible

equals deploy and create

and that'll be our acting

step

beginning we'll do arrange

then we'll do an assert

of

we'll just check to see

that the token counter has been

increased we'll do assert

advanced collectible

the token counter

is equal to one all right great so this

will return our advanced collectable

however we know that since we're

actually going to be working with a mock

vref coordinator if we look at our

advanced collectible

we know that the bulk of the work

actually comes in this fulfill

randomness function and we're going to

have to tell our mock to actually return

and call this function so in order to do

that we should probably also return this

creating transaction here so that we can

get the request id remember how in our

lottery we actually just directly called

everything

and we needed this request id to call

this callback with randomness function

in our test here we're actually using

our scripts a little bit so we could

either just go ahead and write out all

the steps similar to what we did in the

lottery or we could adjust our scripts a

little bit for simplicity here we're

just going to go ahead and have this

deploy and create function also return

the creating transaction this way we can

go ahead and get the request id so back

in our test here that means we have to

do deploy and create

equals advanced collectible and

creation

transaction now that we have this

creation transaction we can use it to

get our events

and again if we look back in our

advanced collectible we can see here

that we're omitting this requested

collectible with request id so we can go

and do request id

equals creation transaction dot events

we'll add the name

of our event here which is requested

collectible and then we'll get

that request id once we have this

request id we can then go ahead and grab

the vrf coordinator so from our scripts

we'll grab this get contract

and we've coded our get contract in a

way that if the mock has already been

deployed again if we go back to our

helpful scripts if the contract has

already been deployed then we're just

going to go ahead and grab it so since

here our mock will have already been

deployed so we don't have to redeploy it

so we can just do get contract

vrf

core did nator

dot call back

with

randomness

and we'll use the request id

we'll pick some number like 777 we'll

give it to

the address of our advanced collectible

and remember we're going to be calling

the callback with randomness this is

what a real chain link node is actually

going to call back and it just needs a

request id a randomness number and a

consumer contract

so request id random number and then the

consumer contract

and then of course we have to do a from

account

from get account

and we'll import get account as well

now we can move into our cert phase

so first if this is correct then our

token counter

should be at least one so we can assert

advanced collectible

dot token counter

is greater than zero

or we could be a little bit more

specific here

equals equals

one we also should technically be able

to get the breed and figure out the

breed of this first token of this first

collectible let's go ahead and

parameterize the 777 we'll call it

random number

equals 777.

we'll place that here

and then what we can do is we can say

certain

collectible

dot token id

to breed

of zero

right in our fulfill randomness we're

going to assign the token id

to being the breed and the breed is

going to be this random number mod 3.

so on our test we can say

the token id to breed of dog 0 is going

to be equal to

random number

mod

3 and this is pretty much our full test

so let's go ahead and run this

we can do that test with dash k

whoops it looks like our simple test has

actually got an error now we're getting

this module not found no module named

scripts.deploy.create

this now since we actually changed it

it's going to be

scripts.simplecollectable.deploy and

create

so now if we rerun our test

we'll see brownie isn't going to err out

anymore

so even though we skipped this test

brownie still compiles it to make sure

that everything makes sense but what we

see here is fantastic our advanced

collectible unit test has worked

perfectly let's go ahead and make an

integration test for our advanced

collectible here so now we'll have our

test folder here and we'll have unit and

we'll have integration

our integration test is actually going

to look really similar to our advanced

collectable here so i'm just going to go

ahead and copy everything new file

test

advanced

collectible

integration

pi

and we'll just paste everything in here

now the only thing that we're going to

have to change is that we're not going

to be the ones to call back with

randomness here

so we can remove this part

we also don't need the request id

anymore since the chain link node is

going to be responding this means that

the breed that we're going to get is

actually going to be random so we can

get rid of that assert as well all we

need to do is wait for the transaction

to get called back

so we're going to import time

and instead of us calling back with

randomness

we're just going to do

time dot sleep

then we'll wait 60 seconds

test can create collectible we should

also give this a different name

integration

now we should be able to test this on a

ring b chain and our token counter

should indeed increase with the chain

link node actually responding so now we

can run brownie test dash k

just that test dash dash network

rink b

oh whoops right now we're skipping this

because we're saying only for local

testing now since this is going to be

our integration test we're going to do

the opposite

if network.showactive is in these local

blockchain environments then we're going

to skip it and say only for

integration testing

all right great so now we have a quick

and dirty integration test that we can

run we're not going to run it for now

because we're going to be working a lot

with this rigby chain and we're going to

be deploying a lot of different things

and we don't want to wait so long so

this is fantastic we have a way to

deploy this we have a way to get these

new collectible tokens and create them

but if we were to take this address

right now and try to view this token on

something like openc

we would get nothing back we wouldn't

get any result right now our token

doesn't have a way to be viewed or be

visible by everybody else these mt

platforms don't know what they look like

and again this is where that set token

uri is going to come into play

so we have to figure out a way to host

an image and host all the metadata for

our token uri

and the way that we're going to do this

is by using

ipfs and this is a lot better than

actually hosting this on our own server

because anybody can then go ahead and

host this image or this metadata

themselves

now there's further improvements to this

with something like filecoin

where you actually pay to have your

image hosted forever however ipfs can

hook into filecoin in the future and is

going to be a good enough solution for

what we're looking to do here

just keep in mind that what we do not

want to do is run this on a centralized

server when we spin up our ipfs node we

will be the only node that actually runs

and actually hosts our image however the

image is open for anyone to pin to their

nodes as well

so it's much easier for us to host our

images in a decentralized manner what's

bad obviously is if we just had the

image stored on our own centralized

server because if our server goes down

then that url no longer exists if at

least one node on the ipfs network is

hosting this image it will be available

for anybody to see so that's why it's

going to be a much better solution than

some centralized server as i mentioned

decentralized storage is a topic that's

getting better and better and we're

looking forward to seeing more and more

ways to interact with them in any case

we need to create an ipfs node that's

going to host some data that looks like

this or like what we saw with our simple

collectable

it needs to host metadata that will look

like this we both have to host a

metadata file and an image uri file

which will host the actual image

both of these need to be stored on ipfs

so let's go ahead and create a new

script called

create

metadata

which will read off chain and create our

metadata file so we'll start our scripts

per usual

with def main

and we'll get the most recently deployed

advanced collectible

using this -1 syntax

of course we're going to do from

browning

import

advanced

collectible once we have this advanced

collectible we can then loop through all

of the tokens and actually figure out

the metadata for each one of them so

we'll do

number

of advanced

collect

bowls

equals

advanced collectible.tokencounter

because we want this crate metadata to

create the metadata for every single

token that we've created do a quick

print line here just saying print

you

have created

number of collectibles

collectibles

we even run this really quick brownie

run scripts

advanced

create metadata

network rank b since we've already run

this on the ringpi chain

we'll see you've created one collectible

if i were to run our create collectable

script again and then our create

metadata script would of course get more

but right now we only have one

collectible

now let's loop through all these

collectables and create their metadata

so we're going to create that that file

it looks like this and it's going to

have it's going to have the name which

is going to be based off of the random

breed that i got it's going to have the

description which is based off of again

the random breed that i got it's going

to have an image which will also be

based on the random breed that it got

and i just put some attributes in here

but again these attributes so we're

going to say for each token id

in the range

of number of advanced collectibles

for each one of these advanced

collectibles

first we need to get the breed so we're

going to say the breed the breed is

going to be equal to advanced

collectible dot token id

to breed

of the token id

now advanced collectible that token id

to breed this is going to return an

integer right because again our advanced

collectible

this enum breed is going to be 0 one or

two so we actually want to create a

quick mapping that represents that zero

is pug one is shipped in u and two is

saint bernard so i actually like to

create this in a helpful script

called def get breed

and then it takes as an input it takes a

breed

number

and it uses a switch statement so up top

we'll say

breed mapping

equals

zero is going to be pug

one is going to be

shiba inu

and two

is going to be saint bernard

so in this get breed function now

we can just do return

breed mapping

of that breed number that we get

so

instead of doing advanced collectible

the token id to breed we can now just do

get breed

and this will this will return the

number and this will return the actual

string so we can just do from scripts

dot helpful scripts import get

read

now that we have the breed we can start

creating this metadata file now what

we're going to want to do is we're going

to want to have some type of format for

our contract to always pull from so what

i like to do here is i'll create a new

folder

called metadata

and in this folder

i'll have a new file

called samplemetadata.pi

and then i just have metadata

template

equals and i'll just have this this

template that we're always going to use

now in here we're going to need a name

and then

we're going to leave the name blank

because we're going to want to fix it

later

we're going to have a

description which we're also going to

leave blank for now

we're going to have that image uri which

will also leave blank

and then we're going to have some

attributes which should be blank for

this dog because we don't actually have

any on-chain attributes but i'm just

going to go ahead and add some to show

you what you could do if you wanted to

give your dog some stats you know maybe

maybe cuteness maybe

maybe raw power maybe speed agility you

know whatever you want to do so we'll do

trait

type

gonna be cuteness

and then

value is gonna be 100. this would

basically say hey there's a trait type

called cuteness and the value of that is

a hundred so the cuteness of the dog is

100. so now once we have this sample

metadata file we can import this into

our script here so we'll say from

metadata

dot sample metadata

import

metadata template

and another quick note you might have to

put a underscore underscore init

underscore underscore dot pi file in

that metadata folder

if you're working on older versions of

python and we start creating our new

metadata file for this break for this

dog we want to save each collectible

under their network and with their token

id so let's go ahead and create a new

folder

call it rink b and this is where we'll

save all of the rink b metadata for all

these collectables for all these token

ids now before we actually save it

though we should just check to make sure

that the file doesn't already exist

right because if the file already exists

that means we've already created the

metadata for that token and we don't

need to

so we can just go ahead and get the

metadata

file name

which is going to be equal to

dot slash metadata

slash network dot show active

of course this means we need to import

network from brownie

slash

the token id

token id with a hyphen

with the breed

dot json

just to make sure we're doing this right

we can even just print this out

do a quick manual test

brownie run scripts

advanced

create metadata

network rink b

so this will be the name of the file so

metadata rink b

token id and then the

breed.json okay cool now we can actually

check this to see if this already exists

and we're going to use a python library

called path so we're going to say from

pathlib

import path

and we're going to say if that path

this metadata file name

dot exists

if that path exists

we'll do a quick print saying

metadata file name

already

exists

delete it to overwrite

this way we won't accidentally overwrite

metadata that we've already created and

do extra work so if it exists we'll

print that out great otherwise

we can go ahead and print

print def

creating metadata file

metadata file name

you can even run this real quick

great you have one collectible

creating metadata file perfect

so let's go ahead and start creating

this metadata file so we're have to give

it a name description

image uri and we're not gonna give it

any attributes though so just name

description and image uri so name is

easy enough since this is a dictionary

or a mapping in python we can actually

just go ahead and start mapping so up

above before this if

we'll do

collectible

metadata it's going to be equal to

this template

so this is going to be where all we sort

all of our metadata and we'll say

collectible metadata of name

is just going to be the breed so if it's

a pug the name will be pog if it's

shipped in you name it will be shipped

in you if it's st bernard name will be

saint bernard and we'll give it

collection metadata

description

is going to be equal to

we're going to do an f string here

and adorable

breed

pop

now if we print out this collectible

metadata we should see

at least the start of the metadata which

we do great name saint bernard

description and adorable saint bernard

pup of course you'll have a different

random breed but it should look

something like this

now we're going to need

collectible metadata

image uri

this is where we're going to have to

have our image already uploaded to ipfs

so we can assign it to our metadata here

so how are we going to do this well

we're probably going to need some upload

to ipfs function it's going to return

our image uri and then we can just set

that image uri to the collectible

metadata

of image

so let's go ahead and start doing that

let's create

our upload to ipfs function now in order

to upload to ipfs we of course need to

have the images ourselves i already have

them downloaded here and again you can

download them right from the github

yourselves if you like to make this a

little bit generic we'll have this

upload to ipfs take a file path

that way we can pass

this imagery upload to ipfs we're going

to give it some type of file path here

we're going to have to grab that image

path so we'll grab that image file name

by just doing breed

dot lower

because right now our breeds are all

upper case so we're going to want to

make a lower case then we're going to

replace

the underscores with

hyphens

dot png

so we'll say plus

dot png

and then you know let's just go ahead

and add the full path here so we'll say

dot slash image

slash

plus

3. lower perfect

so and then we'll even change this

to image path and then we can pass this

to our upload to ipfs so this file path

now is going to be the location of the

object that we're going to upload to

ipfs we're going to use this path

library to actually grab that path to

upload it to ipfs so we're going to say

with path

file path

dot open

rb

as file path

now this is a little bit of

sophisticated python here what we're

doing is we're taking this path here

we're opening the file rb means we're

going to open it in binary since these

are images that's how we're going to

actually

open it and we're going to upload the

binary actually to ipfs and then as fat

fp so we're saying this opened file

is going to be named fp or file path

we're going to do image

binary

equals fp.read

and that's how we actually read the

whole binary and now this whole image is

stored as binary in this image binary

here now here's where we're going to do

the upload stuff now to get started here

we're actually going to have to download

the command line for ipfs download

command line ipfs

we'll come right to the docs here and

again there's going to be a link

in that github and in here there are

instructions to

to download it for whatever system that

you're working on right if you're

working on windows if you're on linux if

you're on mac these are the different

ways to actually download this ipfs

command line you'll know you've done it

right if you can type ipfs

version and you see something like ipfs

version 0.9.0 it's important to note

that we could also do the ipfs download

desktop

and we could download the desktop

version of this and we'd see a user

interface which looks something like

this we could upload our files manually

and then manually go ahead and

grab those files and place it into our

scripts but we're engineers we want to

do this programmatically in any case

once we have this api downloaded we can

actually follow the documentation here

the http api reference for actually

uploading our code we're going to be

mainly working with this endpoint api v0

slash add as this is the endpoint that's

actually going to add our file or

directory to ipfs now what we're going

to want to do is we're going to actually

upload our images to our own ipfs node

we can run our own ips node by doing

ipfs

daemon and we'll see an output that

looks something like this we can even

see a web ui using this web ui url here

this will look similar to what the ipfs

desktop looks like but again we're going

to work just mainly from this damien

from our own ips note congratulations

you're running your own ipf's node right

now as you can see it's currently

running on our own localhost right here

http 127 0.0.1 at port 5001. so to

actually upload this we're we first need

to get that ipfs url

which is going to be equal to

this url right here

paste

now we want to make an api call or a

post request to this

endpoint

using

this

api v0 ad and these are all the

different parameters that this ad

can actually take in

so that we can actually post it to ipfs

for those of you familiar with curl and

you want to test this out using a curl

i've added a curl into this create

metadata file as a comment so that you

can actually go ahead and test this if

you want to use this now what we're

going to want to do to keep working with

our scripts

is you should have like a little plus

button somewhere on your vs code

we're going to hit that plus button

and now we're actually going to have two

different shells one which is running

our ipfs node

and one which is running our bash or zch

or whatever other shell that your os

natively works with now that we have

this ipfs url we're going to grab the

endpoint

which is going to be

again this right here

dash api dash v0 add

and we can make a post request to it so

for us to do that we're going to say

response equals requests dot post

we're gonna do the ipfs url

plus the endpoint and we're gonna say

the files that we're gonna upload

is gonna be equal to

file

image binary

requests is a python package that we're

going to import so we're going to say

import requests

now if we go back to the ipfs

documentation we can scroll down to see

what the response looks like

it's going to return a bytes

a hash

a name

and a size

now if we look at this sample

token uri we can see the api call here

ipfs stores all its data using a hash

and if we're looking at this and if

we're looking at the simple collectible

this hash here

is the hash that represents this

pug.json file everything in ipfs gets

hashed and every single piece of data

has a unique hash which is why it's so

fantastic if we were to change anything

with this image this hash would be

drastically different all we need to do

is get the hash that ipfs gives the

image that we upload we go ahead and

plug it into a template url like this

one here so what we're going to do then

is we're going to say ipfsh

it's going to be equal to

this response.json

since

we're just going to jsonify the response

to make it look like this response here

and we're going to grab

that hash

right since it's going to return this

dictionary

we just want the hash here

then

we're going to give it a file name

by saying it's going to be that file

path

dot split we're going to do some fancy

python stuff here we're going to say -1

to 0

which basically all this line is doing

is saying you know if we have dot slash

image slash pug

dot png

we're going to remove

we're going to split it up by these

slashes

into an array and we're going to grab

the last part of the array so we're

basically just

changing this to this with this line

right here then with this we can get the

image uri which is going to be equal to

an f string again

https

ipfs.io

ipfs

slash

ipfshash

question mark file name

equals

file name

and it's this format right here which

will give us

this

so if i go ahead and even just copy

paste this under as a comment to show

you guys

we see this part's exactly the same

and then this is that hash here

represented here

and then we have question mark file name

equals

and then the file name

so excuse me this is actually gonna be

like

zero hyphen pug

zero hyphen pod and that's exactly what

we need we need this image uri so we'll

do a quick print

image

image uri

and then we'll go ahead and return

the image

uri

now since we're actually going to be

testing this with

ipfs we can add a new integration test

so we'll call this test

ipfs

upload.pi

now you might want to write a test for

this and we're not going to do one but i

challenge you to later on maybe come

back and and write your own test for

this upload to ipfs

for now we're actually just going to

manually test it

so we're going to go back up to our

script here and we're going to run image

uri equals upload to ipfs image path

and then we're going to get printed in

image url since we're working with the

saint bernard here we should get a saint

bernard image uri

so if i run brownie

run scripts

advance

create metadata

network rink b

let's see what happens i need to add

brackets here sorry about that

now let's try it again

awesome we were able to create this

metadata file

now if we go ahead and copy this

and paste it

perfect we see exactly what we're

looking for we see our saint bernard

awesome job and this has been uploaded

to our own ipfs node now i want to show

you guys actually another service and

another way we can actually upload these

to ipfs some people don't want to run

their own ipfs node because they're not

actually going to be keeping it running

the whole time anytime their node goes

down this means that nobody will be able

to see your image unless somebody else

pins your image or or uses your image so

what i also like to do is i like to

upload it to some other third-party

service as well as uploading it to my

own ipfs note so i like to create

another script actually called

deploy to pinata

so let's go to scripts new file

upload to

pinata.pi

so pinata

pinata is an ipfs file management

service and they actually will pin

whatever files that we're working with

as well so we'll have it pinned in our

node and they will have it pinned as

well so we can go ahead and register

awesome this is what pinata looks like

it's a way to upload and work with ipfs

and they'll give us some extra support

and they have a free tier which is

fantastic as well they have some

wonderful documentation as well under

this documentation section so let's go

ahead and upload this to ipfs so that

when our node goes down our images don't

go down so we'll do pinata

base

url

is going to be equal to

https dash dash api.pinata.cloud

you can find all this in the

documentation as well if we scroll down

the documentation we're going to be

using this pin file to ipfs endpoint

here and you can see that entire

endpoint right here

with the base and then the endpoint so

we're going to copy that endpoint

we're going to say endpoint

equals

pinning

pin file to ipfs we're going to choose

some file path

and for us we're just going to do dot

slash image

slash

pug.png

of course if you want to upload some

other image you can you know change this

file path or you could even do some type

of for loop to pin everything uh in the

image section here again we're going to

do file name we're going to use that

same syntax before that's

we're doing file path

dot split

slash

some fancy python stuff

just to get

this last part and we also need and we

need to use some headers in this post

request so it's a type post request we

need to use some headers here so we're

going to say headers

equals

copy this pinata api key

which is going to be some api key and

then we also have this pinata secret api

key pinata secret api key

which is going to be something else

we can find these two api keys if we

scroll all the way down we hit api keys

create a new api key

i'm going to call this you can make this

an admin key i'm just going to do limit

max users

limit max uses i'm going to set this to

200

because i'm going to make this a public

key so i don't want people using this a

million times

please make sure you select at least one

permission

pin file to ipvs for those of you guys

watching you can absolutely just grab

all these if you want you can make this

an admin you know do whatever you want

to do here since i'm only going to be

using this pin file to ipfs that's all

i'm going to do

hit create key and here are our tokens

here so our api key is going to be right

here and we're going to copy that

we're going to open back up that dot env

and add this as one of our environment

variables here so we're going to export

pinata

api key

equal to that key there

this api secret we're going to copy and

we're going to export pinata api secret

equals that key there

and we actually don't need this

jwt but if you guys wanted to you could

copy it as well

so now that we have them in our dot env

file these are now going to be

environment variables that we can use

and brownie's going to automatically put

them into our

environment

so what we can do then is we can do os

dot get env

pinata

api key

and then of course we're going to import

import os

and then

for our secret key we're going to do the

same thing os dot get env

pinata api secret

this is how we get those two headers for

uploading to pinata then we're going to

do a lot of the same code we did before

we're going to say with path

a file path dot open

rb for the binary as fp

of course since we're using path we're

going to do from path lib

import

path

we're going to do this same piece image

binary

equals fp.read

response is going to be equal to

requests which we have to import

requests

import requests

dot post

pin you have a base url

plus that endpoint that we have

and for files

oops

it's going to be equal to

file

and we're going to upload a couple of

things here though we're going to give

it a file name

we're going to do the image binary and

that is getting really annoying when it

keeps getting in the way

file name image binary

and then outside of these brackets here

we're going to do comma

headers equals

equals headers

and then we're just going to print

response.json so to have this run in

browning we're just going to do a def

main function here

a nice little trick we can do is we can

select all this text and just hit tab

and it'll move it over one

and perfect we can now run this inside

of brownie

so we can do brownie

run scripts

upload to pinata

and perfect we get a little output

that's going to look something like this

it's going to give our ipfs hash the pin

size the timestamp

so now if we go back to pinata

we go to pin manager

do a little refresh here

we now see

our pug has actually been uploaded to

pinata awesome work we're going to keep

going using the ipfs daemon to actually

upload things but if you want you could

totally swap out this upload to ipfs to

use that script that we just created to

upload it via pinata instead of our own

ipfs node anyways this upload to ipfs is

going to return this image uri so we can

go ahead then

and set the image uri it's going to be

set on this collectible metadata image

and then all we have to do is dump this

collectible metadata into its own file

and then upload that as well to ipfs

we'll dump this to its own file by doing

with

open

metadata file name

and we

open it with a w which means that we're

going to write

as file

json.dump

collectable metadata to the file

so we're going to import json to do this

and what this is going to do is just

going to dump this dictionary as json to

this collectable metadata file then we

can upload to ipfs also

this metadata file name and this upload

to ipfs should print out the image uri

or in this case the metadata uri so

let's go ahead and try this out

so remember we do need our ipfs daemon

running

let's go back to our scripts and we'll

do brownie

run scripts

advanced

create metadata

network

rank b

and boom okay so here is our image uri

which we click this will be able to see

looks just like this

and then here is our uploaded

saint bernard metadata file which is

fantastic so now we have both a metadata

file

and we have an image uri

this is fantastic we've uploaded both of

these

to our ipfs

and if we scroll over

go to our metadata file in ring b we'll

see

we have this new file in here because

we've gone ahead and saved it in here

it has everything that we need it has st

bernard

it has the description it has this image

uri that we just created and it has some

attributes that again we're basically

ignoring now to make our lives a little

bit easier and since i've already

actually uploaded these to ipfs myself a

couple times and since the hashes of

these are going to be the exact same for

all of us when we upload this we're

going to go ahead and just quickly

refactor this to make it a little bit

easier so we don't always have to have

ipfs running so in our dot env i'm going

to add a new environment variable called

upload

ipfs

and we're going to set it equal to false

so now down here i'm just going to say

if os dot get env

upload

ipfs

equals equals true

anyway since we're going to do os here

we're going to do import os

and before this i'm going to do

image uri equals none

and we're going to say

image uri

equals image uri if image uri which

again i know this could be a little

confusing but we're saying

we're setting image uri to whatever

image uri is if image uri isn't none

else we're going to create a mapping

called breed

to

image uri

of the breed so again

since i've already uploaded them i

already know what all these image uris

for these three dogs are going to be

so up at the top we're just going to

create a new mapping called breed to

image uri

equals

i'm actually just going to go ahead and

copy paste this whole thing

now you can skip this you don't have to

refactor here

and you can just always have your daemon

running and always upload to ipfs it's a

little bit quicker to not always have to

do that again this brief image uri is in

the github repo feel free to just copy

paste it to use it you can even click

the links to check it to check to see

that those image uris are really there

and this is what we'll use

so back down here reach the image uri

uri perfect and then we're also going to

add if

again os.get

env

upload ipfs

equals equals true

then we're also going to upload to ipfs

down here but this is to go and actually

just show you how exactly we could

upload all this stuff to ipfs since i've

already done it we're going to make it a

little bit easier on ourselves another

thing that you might do is you might

actually save

all these urls to their own file to

their own json object maybe inside of

the metadata folder maybe under wrinkby

or something

and then you could go ahead and just

pull directly from those files same

thing with the metadata once we upload

to ipfs we're not actually going to save

these urls anywhere you could absolutely

100 percent

after you run this upload to ipfs script

we go ahead and save it to a file and

pull directly from there moving forward

but awesome okay so

we've done a lot of work here we have

uploaded to ipfs our metadata

and our image uris so we have everything

that we need to actually just set the

token uri

finally for our advanced collectible we

finally can call this set token uri

function so let's go ahead and do this

last bit here this last set token uri

function

so let's go to scripts advanced scripts

create a new file we'll call it set

token uri

uri dot pi

and this is where we're gonna set the

token uri so we'll do def main

and in here we'll do a quick print print

f

working on

network dot show active

of course since we're using network

from browning

imports network

to close that there and let's grab the

most recent advanced

collectible

it's going to be equal to advanced

collectible

minus one

since we're using advanced collectible

contract let's import that from brownie

let's once again loop through all the

tokens that have been deployed

so we'll do number

of collectibles

equals

advanced collectible dot token counter

do a quick print

you have

print f excuse me

number of collectibles

token ids

and let's loop through this list of

collectibles again so we'll say for each

token id

in range

number of collectibles

first we'll get the breed

saying breed

equals advanced

collectible

token id to breed

of the token id

we actually have to call this

getbreed function again

which luckily we generalize so we can do

from

scripts.helpfulscripts

import

get breed

and now let's first before we actually

set the token uri let's check to see

if it already has a token uri set so

we're going to say if not advanced

collectible dot token uri

of token id

dot starts

with

https

so what this line is doing i know it's a

little bit long is we're grabbing

advanced collectible.token uri

of the token id so we're grabbing this

token ids token uri

and we're saying if it doesn't start

with https that means we know that it

hasn't been set

so we can go ahead and print

setting

token uri

let's actually make this a print f

of

token id

and then we can set the token uri so i'm

actually going to generalize this out

into its own function

so let's go ahead

and we'll do def

set

token uri

and as inputs this is going to take the

token id

the nft contract which is going to be

our advanced collectible contract

and the token uri so the first thing

that we're going to do we'll say account

equals get account

so we're going to grab this

get account of course

from our helpful scripts

because this set token uri is actually

going to call that set token uri

function we're going to say

nft contract

dot set

token uri

of the token

[Music]

and the token uri

remember this is a function that we

added to our advanced collectible right

here set token uri it takes a token id

and a token uri and this is going to be

from of course

account we just created so we're going

to say

transaction

equals that we'll do transaction.wait

wait one second for it or one block for

it and then we'll print

we'll do printf

awesome

you can view

your nft at

we use that openc url

dot format

nft contract.address comma token id

then i'm just going to add another print

here saying

please wait up to 20 minutes

and hit refresh

metadata and hit the refresh metadata

button

so now we have our set token uri

function

we can add

the token id in here

the advanced collectible contract and

then we just have to add the token uri

here so since we've already uploaded and

since i've already actually uploaded all

three

what you could do

and what i like to do is just have a

dictionary here so we don't always have

to be pulling from something

so i have a dog

metadata

dictionary it's going to be equal to and

we're going to add those different dogs

in here so saint bernard

this this saint bernard url

we're going to paste it here i've

actually gone ahead like i said and

uploaded this metadata for all three

dogs

so i'm just going to go ahead and copy

paste all three in here

again we're shortcutting a little bit

here but what you could do is you could

save all these metadatas to their own

file and you could just pull from that

file instead of doing kind of this dog

metadata dictionary so in any case

though we're going to do

dog metadata dictionary

of breed

right because dog metadata dictionary of

saint bernard is going to be this which

again

has

our image uri has everything about our

dog and is perfect what we also might

want to do is write some tests around

our set token uri function of course but

i'm just going to move on so

in any case we've done a lot here i'm

actually going to even close down my

ipfs node

and we should be just about ready for

everything

so of course we'll run our brownie

test

we want to make sure that all our unit

tests are working great

which they look like they are working

fantastically but we are ready to

do a full end-to-end manual test here

and you could 100

and i actually highly encourage you to

100 we're just gonna run these scripts

in order and look to see if our stuff

shows up on the openc nft marketplace so

are you guys ready let's do this so make

sure of course your environment

variables are set here make sure that

your metamask

for rink b

has some eth and

has some link and then we can go ahead

and start running some of these scripts

so we'll do brownie

run scripts

advanced collectible deploy and create

network

rink b integration test moment of truth

and perfect a new token has been created

awesome

we can even go grab this address

let's delete all these tabs that we have

opened up

and we'll go to ringpi.etherscan.io

we'll paste it in here

and we can see

contract has been verified even though

we didn't verify it because it matches

some other source code we can see token

counter is one and we can even go to

tokenid to breed of zero see what breed

it is

so it's breed two and it looks like

we're getting a saint bernard again

which is incredibly adorable we can even

go to events here and we can see the

different events since this is verified

we can even see the name of the events

so we have our breed assigned event

and we have our requested collectible

event first is an index topic of token

id and then there's the un8 read

and then we have the bytes32 request id

and the address requester now let's run

our create metadata script here

so we'll do brownie

run scripts

advanced

create

metadata

network rink beam we don't have to run

create collectible since our deploying

crate already does that so now if we run

our create metadata

i've actually already have i actually

since this is the same bernard again i'm

going to go ahead and get this already

exists delete to overwrite

so what i'm going to do is i'm actually

going to even create another one so that

i get a new nft so i am actually going

to run this crate collectible script so

we're going to do brownie

run scripts advanced collectible

create collectible

network rank b

and what this is going to do all it's

going to do is it's going to fund with

some link

which it's going to be a little bit

overkill with the link but that's fine

and then we're going to do advanced

collectible.create collectable

so we're just going to do two

transactions here

perfect collectible has now been created

now i'm going to wait a solid 30 seconds

to have that chainlink vrf respond

and i'm even going to go to the contract

give it a quick refresh look at this

token counter once the chain-link vrf

responds this token counter will then be

2. now that i see a token counter of 2

here that means that it actually has

responded so we can now run

the create metadata script

and we should have

a new metadata file now you have two

collectibles

zero saint bernard already exists

deleted to overwrite create a metadata

file metadata ring b pug so now if we

look in metadata

for rink b we have a saint bernard and

we now have a pug awesome so we're going

to set the token uri of both of these if

i grab this contract and i go to

testnets.openc

open c

i can paste this address in

and i'll get this doggy and then this

random hash here right and we see there

are two

token uris deployed again if they're not

here you might have to refresh but they

don't have the images right because we

haven't set the token uri so we'll go

back look at the advanced collectible

we've deployed and created we've created

another collectible we've created their

metadata now all we have to do is set

the token uri

so brownie run scripts

advanced collectible

set token uri

network rink b

and this script it's going to loop

through

all

of them and actually going to set those

token arrives so we have

setting token uri of 0

so this transaction is doing exactly

that

and it's going to go ahead and say

awesome here's your output and then it's

going to say setting token uri of token

id one and that's that second

transaction and it also gives us an

output to that one as well

so if we've done this correctly

and we hit refresh metadata on this

testnet openc.io

and we do a little refresh here

we can now see our saint bernard which

is fantastic and then if we change

this from 0 to 1 since i've deployed 2

and i refresh this one's metadata and

then refresh the page

we can now see the pug as well

again just keep in mind sometimes the

refreshing metadata does take some time

and you might have to wait up to 20

minutes

but for all intents and purposes we have

just deployed our nfts given them token

uris that aren't around centralized

servers we can now see them on an nft

marketplace like openc

you can let out a big sigh of relief

because you just did something fantastic

that not a lot of other engineers can do

you should be incredibly proud of

yourself at this point let's take a

minute go back over to some of the new

things that we've learned here

when deploying your smart contracts on

chain we all know that those smart

contracts are immutable or unchangeable

but what if i told you that they were

mutable

well technically i wouldn't be correct

however smart contracts actually can

change all the time when people transfer

tokens when people stake in a contract

or really do any type of functionality

those 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

and 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

contractor protocol to do more things or

we want to fix some glaring bug or issue

that we have now even though we can't

change the specific code that's been

deployed to an address we can actually

do a lot more than you think 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 now at first glance you might be

thinking

if you can upgrade your smart contracts

then they're not really immutable then

in a way you'd be right so when

explaining kind of the different

philosophies and patterns that we can

use here we do need to keep in mind the

philosophies and decentralization

implications that each one of these

patterns have as they do all have

different advantages and disadvantages

and yes some of the disadvantages here

are going to affect decentrality so we

need to keep that in mind and this is

why it's so important that before you go

ahead and jump in and start deploying

upgradable smart contracts you

understand the trade-offs we're going to

look at three different ways to upgrade

your smart contracts the not really

upgrading method the social aka my

grading method and then the method that

you're probably here for which is

proxies so let's talk about the not

really upgrading method or the

parameterization method or whatever you

want to call it this is the simplest way

to think about upgrading your smart

contracts and it really isn't upgrading

our smart contracts because we can't

really change the logic of the smart

contract whatever logic that we've

written is there we also can't add new

storage or state variables so this is

really not really upgrading but it is

something to think about upgrades is

just parameterizing everything whatever

logic that we've deployed is there and

that's what we're interacting with this

function means we just have a whole

bunch of setter functions and we can

update certain parameters like maybe we

have a reward parameter that gives out a

token at one percent every year or

something like that maybe we have a

center function that says hey update

that to two percent or update that to

four percent it's just a setter function

that changes some variable now the

advantages here are obviously this is

really simple to implement the

disadvantage is that if you didn't think

of some logic or some functionality the

first time you deployed their smart

contract that's too bad you're stuck

with it you can't update the logic or

really update anything uh with the

parameterization aka not really method

and the other thing you have to think

about is who the admins are who has

access to these setter functions to

these updating functions if it's a

single person

guess what you 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 ave used before you call function you

actually check some contract registry

that is updated as a parameter by

somebody and you get routed to that

contract and you do your call there

again this really doesn't allow us to

have the full functionality of upgrades

here you can argue that this registry is

a mix of one of the later versions but

for all intents and purposes this

doesn't really give us that flexibility

that we want for our upgrades but some

people might even think that upgrading

your smart contract is ruining the

decentrality and one of the things that

makes smart contracts so potent is that

they are immutable and that this is one

of the benefits that they have so there

are some people who think that you

shouldn't add any customization or any

upgradability you should deploy your

contract and then that's it trillabits

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 setting it for getting it

and not looking at it again now if i

were to deploy a smart contract and i

wanted to upgrade it with this

philosophy in mind that hey we got to

keep it immutable we could use the

social yate method to actually upgrade

to new versions the social yet method or

the migration method is just when you

deploy your new contract not connected

to the old contract in any way and by

social convention you tell everybody hey

hey this new contract this new one that

we just deployed yeah this is the real

one now and it's just by convention of

people migrating and over into using

this new one that the upgrade is done

hence my slang name of social yi because

you

yeet the first one out of the way and

move to the second one

i think i'm funny

this has the advantage of truly always

saying hey this is our immutable smart

contract and this is our new one this is

really the truest definition of

immutable because since you give it no

way of being upgraded in place then if

somebody calls that contract in 50 000

years in the future it'll respond

exactly the same another huge

disadvantage here is that you have to

have a totally new contract address

so if you're an erc20 token for example

you have to go convince all the

exchanges to list your new contract

address as the actual address keep in

mind that when we do this we do have to

move the state of the first one over to

the second one so for example if you're

an erc token moving to a new version of

that erc token you do have to have a way

to take all those mappings from the

first contract and move it to the second

one obviously there are ways to do this

since everything is on chain but if you

have a million transfer calls i don't

want to have to write the script that

updates everyone's balance and figures

out what everyone's balance is just so i

can migrate to my new version of the

contract so there is a ton of social

convention work here to do trailer bits

has actually written a fantastic blog on

upgrading from a v1 to a v2 or etc with

this yeet methodology and they give a

lot of steps for moving your storage and

your state variables over to the new

contract so link in the description if

you want to read that now let's get to

our big ticket item so in order to have

a really robust upgrading mentality or

philosophy we need to have some type of

methodology or framework that can update

our state

keep our contract address and allow us

to update any type of logic in our smart

contracts in an easy way which leads us

to our big ticket item the proxies

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 daily gate

call is a low-level function where the

code in the target contract is executed

in the context of the calling contract

and message.sender and message.value

also don't change so you understand what

delegate call means now right great and

in english this means if i delegate call

a function in contract b from contract a

i will do contracts b's logic in

contract a so if contract b has a

function that says hey store this value

in a variable up top i'm going to store

that variable in contract a this is the

powerhouse and this combined with the

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

implementation contract has all of our

logic and all the pieces of our protocol

whenever we upgrade we actually launch a

brand new implementation contract the

proxy contract proxy points to which

implementation is the correct one and

routes everyone's calls to the correct

implementation contract you can think

the proxy contract sits on top of the

implementations the user the user is

going to be making contracting function

calls through the proxy contract and

then some type of admin the admin is the

one who's going to decide when to

upgrade and which contract to point to

in this scenario the other cool thing

about the proxy and delegate call is

that all my storage variables are going

to be stored in the proxy contract and

not in the implementation contract

this way when i upgrade to a new logic

contract all of my data will stay on the

proxy contract so whenever i want to

update my logic just point to a new

implementation contract if i want to add

a new storage variable or a new type of

storage i just add it in my logic

contract and the proxy contract will

pick it up now using proxies has a

couple of gotchas and we're going to

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 trillabits 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 2 we go ahead

and set value to 2. but these smart

contracts are actually kind of dumb we

actually set the value of whatever is in

the same storage location on contract a

as contract b so if our contract looks

like this and we have two variables in

contract a we're still going to set the

first storage spot on contract a to the

new value this is really important to

know because this means we can only

append new storage variables in new

implementation contracts and we can't

reorder or change old ones this is

called storage clashing and in the

implementations we're going to talk

about they all address this issue the

next one is called function selector

clashes when we tell our proxies to

delegate call to one of these

implementations it uses what's called a

function selector to find a function the

function selector is a 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 same 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 these functions

are totally different they actually have

the same function selector so yes we can

run into an issue where some harmless

function like

get price has the same function selector

as upgrade proxy or destroy proxy or

something like that this leads to our

first out of the three implementations

of the proxy contracts this is called

the transparent proxy pattern and this

is actually going to be the pattern that

we're going to be demoing to you today

in this methodology admins are only

allowed to call it 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 run 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 you're a user

you're calling implementation functions

so if you're an admin and you build some

crazy awesome d5 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 upgradable proxy or the

ups

this version of upgradable contracts

actually puts all the logic of upgrading

in the implementation itself this way

the solidity compiler will actually kick

out and say hey we got two functions in

here that have the same function

selector this is also advantageous

because we have one less read that we

have to do we no longer have to check in

the proxy contract if someone is an

admin or not this saves on gas of course

and the proxy is also a little bit

smaller because of this the issue is

that if you deploy an implementation

contract without any upgradeable

functionality

you're stuck and it's back to the yeet

method with you and the last pattern or

methodology that we're going to talk

about is the diamond pattern which does

a number of things but one of the

biggest things that it does it actually

allows for multiple implementation

contracts this addresses a couple

different issues for example if your

contract is so big and it doesn't fit

into the one contract maximum size you

can just have multiple contracts through

this multi-implementation method it also

allows you to make more granular

upgrades like you don't have to always

deploy and upgrade your entire smart

contract you can just upgrade little

pieces of it if you've chunked them out

the disadvantages here really only seem

like you have a lot more complicated

code all the proxies mentioned here have

some type of ethereum improvement

proposal and most of them are in the

draft phase there isn't really a

standard here for the proxy that the

whole community has landed on and says

yes

this is great let's do it so for all

these be sure to jump on the discussion

and give your thoughts all right so now

that we know a lot more about upgrades

and how they actually work and some

different methodologies behind them

let's go ahead and learn how to actually

implement some of these strategies and

implement our contract so that we can

upgrade them now there is a brownie

upgrades mix directly in the brownie

mixes organization that if you want to

use you absolutely can once again to do

that it's just brownie

bake upgrades mix and this will have all

the code that we're going to teach you

how to use right now but let's go ahead

and build this up from scratch ourselves

so

we're going to go ahead and run brownie

knit

this of course we're going to create our

new browning project here we're going to

be using the open zeppelin proxy

contracts to actually work with this and

run with this the methodology that we're

going to be working with is the

transparent upgradable proxy now they've

been using the universal upgradable

proxies a little bit more however the

transparent upgradeable proxy is really

fantastic and easy to understand so

that's going to be the one that we're

going to be working with here and these

are the two contracts that we're going

to be importing directly from open

zeppelin so let's get to it we're going

to create a really simple contract that

we can easily tell if it's upgraded or

not

we're going to be using the exact same

ones that open zeppelin actually uses so

let's create a new file and this is

going to be called box.soul we're just

going to have it store and retrieve some

type of value so let's give the spdx

license

identifier

of mit so let's pick our solidity

version

and for this we're actually going to use

0.8.0

oftentimes you're going to have to

quickly pick up new versions of solidity

anyways anyways we're going to do

contract box and we're going to give it

a uint256

private value

we're going to do an event called

value changed

i'm going to give it to you in 256 new

value

give it a function store

uin256

new value

and this is going to be a public

function that anybody can call

and all we're going to do is we're going

to set value

to be new value

and we're going to omit

this value changed

event then we're going to have a

function

retrieve and this will be a public view

and it's just going to return

the ui 256

value return value and this is going to

be our whole contract hopefully you can

understand everything that's going on in

this contract i should spell license

right shouldn't i now we're going to

copy all of this code

and create a new contract called box

v2.sol

we're going to paste it in

and box version 2 is going to be exactly

the same

except we're going to add

one more function called increment

this is going to be a public function

and we're going to set value equals

value plus one

and we're also going to omit

a value changed event

with that new value

now this is going to be really easy for

us to check to see if a contract has

been upgraded or not

if we can call increment

on the same address that we originally

deployed box to then this means that the

contract has been upgraded we shouldn't

be able to call increment

on this box contract but we should be

able to call it on box v2 perfect so

that's all we need to do to get started

now to actually work with the proxies

and the transparent proxy that we're

going to be working with we do need to

add them

to our browning project

so we're going to create a new folder

and we're going to call it transparent

proxy

and in here we're going to add those two

contracts we're going to add one

called proxyadmin.sol

and all we're going to do is we're going

to grab all the code

from the opens up and proxy contract and

paste it right in here

since

since this code is pulling directly from

it it opens up one package we are going

to have to

fiddle with the imports a little bit to

make a match so brownie can actually

compile it

and of course since we're going to be

working with another package we have to

add this dependencies to our browning

config

so

dependancies

open

zeppelin

open

zeppelin hyphen contracts

and for this one we are going to

actually use 4.1.0

then we have to do compiler

soak

remappings

at open

zeppelin

is going to be equal to this dependency

now while we're in here we might as well

do our dot env

so we can get our environment variables

and we'll add our wallet in here

while it's

from key

private

key

we can now just have this be

at open zeppelin

contracts

access

ownable.soul and we don't need to change

this at all because we're actually going

to keep this transparent

upgradableproxy.com

because this

is the second contract that we're

actually going to grab from open

zeppelin

so let's create a new file

to be called transparent

upgradableproxy.soul this exact

text here

and we're going to copy paste this whole

thing from open zeppelin

boom

paste it in here

awesome and then same thing here we just

have to a little reverse engineer this

at open

zeppelin slash contracts slash proxy

erc

1967 erc 1967 proxy and perfect that is

exactly where we are

so great now if we've done this right we

should be able to run a quick

brownie compile

oops i got to change this to box

v2

now let's run a brownie compile

and perfect

looks like we have compiled we've got

some stuff in build great everything's

working correctly so okay so we have our

box here our box v2 and we have our

proxy contracts as well that we can use

to upgrade this box to a new version we

can even look if we go back to proxy of

open zeppelin if we look at our proxy

admin here

we see it has this function upgrade and

call and this calls the upgrade to and

call on the proxy contract if we look in

the transparent proxy this upgrade to

and call calls upgrade to and call which

has been imported actually so we can

actually even go back go back

go to erc 1967 proxy upgrade

look for that again and this is the

function that it's actually going to

call

and it calls this upgrade to function

which calls this set implementation

function

and all we're doing is we're doing

storage slot dot get address slot of

this implementation slot

that value is going to be this new

implementation

all it's doing is it's setting the

implementation slot to being our the new

address that we wanted to use and we can

see now if we look in the proxy contract

the way that it actually works is it has

this fallback function

where it's always going to delegate all

of our calls to whatever the

implementation contract is

this delegate function if we look at him

there's a little bit of low-level

assembly here

and he uses this low-level delegate call

to send any

function call or any call to this

contract to the implementation contract

so this is exactly the function doing

all that delegation all right so now

that we've dug deep into the code let's

actually script this out and turn this

into a script so let's create a new file

and we'll call it zero one deploy box

dot soul and this is gonna be how we're

actually gonna deploy the box so since

this is a brand new script

we're gonna do def

main of course

our account

going to be equal to get account

which

we're going to do from scripts dot

helpful

scripts import

get account

so let's go ahead create a new file

help

full scripts

oops

scripts.pi

and again we're just going to paste in

that getaccount function from our past

helpful scripts

all right our get account script again

so we can just do account equals get

account oh this should be sorry should

be dot pi excuse me

do a quick print

deploying

to

we'll do

network dot show

active

that means we got to do

from

brownie import network and then we'll do

box equals box

dot deploy

from

account

little brackets

here of course since we're going to be

deploying this contract we also have to

import that from brownie and perfect

this alone should just deploy the box

contract right so this means we could do

something like print

box dot

retrieve

and it should be zero right so if we run

brownie run scripts

o1 deploy

it will deploy that

whoops we also got to add our env

we don't have to put anything in here

yet because we're not actually deploying

to a real network

but let's go ahead and run this

i spelt retrieve wrong

it's probably good to

spell things right let's try it again

and great so we get 0 here perfect

that's exactly what we'd expect it's

cool however though if we run

box dot increment this should error out

right

boom exactly it has no attribute

increment so this is what's known as our

implementation contract this box is

implemented it's the implementation

contract

now we have to hook it up to a proxy so

let's first give it a proxy admin and

proxy admins are optional um and it's

also recommended that if you do have a

proxy admin you're and you're going to

use some type of default protocol

sometimes it's great to have your proxy

admin be something like a multi-sig

gnosis safe which is really fantastic

there's going to be a link

in the github for learning how to

actually spin one of those up let's go

ahead and do a proxy admin because

they're really helpful anyways we could

optionally we could just set ourselves

to be the proxy admin but let's set it

to be this this contract

so we'll do proxy admin

equals

proxyadmin.deploy and again this will be

from

account

and since we're using this proxy admin

we're going to import that as well

so if we look at the proxy admin we see

a couple functions here we see like get

proxy implementation which is just going

to return the address of the

implementation

we have get proxy admin

it's going to be us

change proxy admin we have this upgrade

which is just going to call that upgrade

function on the proxy and then we have

upgrade and call upgrading call

changes the implementation to the new

implementation and then calls that

initializer function since we want these

to be proxies you can see here that we

don't have a constructor

this is intentional instead we could

have some type of initializer

function for example maybe we want to

have this store be our constructor

instead of having a constructor what we

do is we call what's called our

initializer function the instant we

deploy this contract for the demo here

we're just not going to have an

initializer anyways so now we have this

proxy admin we have the implementation

contract we have the proxy admin let's

now hook them up to the actual proxy

first thing that we need to do actually

is we need to

encode the initializer function if we

wanted store to be our initializer

function like i said we could do

something like ini shi al

lizer

equals

box.store comma one and this would be

our initializer box.store combined with

one

what we then have to do is we'd have to

encode this for our proxy if we look at

our transparent upgradable proxy if we

look at the constructor

we have address logic address admin and

data here

the logic is that implementation right

this is going to be the address of our

box the admin is going to be ourselves

or in our case it's going to be that

proxy admin contract

and then data is going to be

that initializer function if we go into

the erc

721 proxy

contract

should go back to proxy erc

1967 upgrade

and we look at this as one's constructor

we can see that this data bit here

once this is built with this constructor

it's immediately going to call this

upgrade to and call so it's going to

call this this initializer if we go to

upgrade to and call if we go back to

this upgrade contract we can see this

upgrade to and call it's going to call

this address dot function delegate call

new implementation data and this is how

it actually

calls that initializer function we have

to actually encode this

into bytes so we have to say box.store

is the is the function a call

and then one is going to be the first

parameter right if this is what we'd

want to do

so we do box

encoded

initially

function

equals encode

function data and this is where it gets

a little bit tricky

but i usually have this encode function

data once again in my helpful scripts

so we'll do quick def encode function

data

and it's going to take

an init

which we're going to start off as none

and then any number of arguments after

that so again this could be like

you know

initializer equals box.store

and then the arguments could be you know

one two three four

five etc or whatever right for us we

only have one variable that can be put

into store but this is how you would do

it and to do this brownie actually has a

built-in function that can actually do

this we just return initializer dot and

code

input

star args

and that's all we'd have to do however

there is a bit of an issue when the

length of the args is zero so i've

already hacked away at it for you guys

so we're just gonna do if

the length of the args

is zero or we're not using an

initializer

then we're going to return

s utils dot two bytes

x string

equals ox

and we do have to import f util

import

at utils and of course we'd have to pip

install it with pip

install

ethertails so i know i kind of rushed

through that but basically what we're

doing like i said

is we're encoding this into bytes so

that our smart contracts actually know

what function to call

so we're just encoding it that's all

we're doing and if it's blank or there's

no initializer we're going to return an

empty hex string and our smart contract

will understand ah okay arguments are

blank here perfect i've got a nice doc

string in the upgrades mix that explains

this even better i'm even just going to

paste it in here for now if you'd like

to pause and read this a little bit more

to

kind of get the full depth of what this

function is really doing feel free to do

that this is a little bit lower level

solidity and evm stuff that we're

getting into here but it can be good to

know anyways

okay great so now that we have this we

could go ahead and run box encoded

initializer function equals encode

function data

which we would import from our helpful

scripts and this is what we use when we

call the constructor for our transparent

upgradable proxy

i'm just going to have it be blank for

now but feel free to fiddle around and

try to actually use an initializer after

we run through this demo so this box

encoded initializer function is going to

be blank we're saying hey

don't use an initializer and that's

totally fine

if we were to add some stuff to here we

would say hey use an initializer so now

we can actually deploy this transparent

upgradable proxy if we open this up with

the constructor we can see

what we need here

so

we're going to say proxy

equals

transparent

upgrade able

proxy.deploy

of course

import this from brownie

and what are those

variables that we need okay we're gonna

need the address the logic this is gonna

be our implementation contract address

so we just say box.address which is our

because we've already deployed this

which is great

then we're going to need our admin which

we could just say is us but we're going

to use the proxy admin

dot address and then last we need that

function selector we need that encoded

function call which for us is just blank

but we still need that

so

box encoded initializer function and

then we have to add from

account of course and i've also noticed

that sometimes it's helpful to add some

type of gas limit

so i'll even add a gas limit

of one

one two three one two three that's six

zeros there but sometimes you might be

fine but uh

with the proxies they they sometimes

have a hard time figuring out the gas

limit so i've just manually put it in

here you can if you want to it might

work fine without it and then great

let's do a quick print function we'll

print

f

proxy deployed to

proxy

you can now upgrade to v2

now what we can do is on the proxy's

address we can call functions so

typically right if we wanted to call a

function on this box contract we do box

dot you know retrieve or however you

spell it box.store let's just do box

store right you'd call it like this

however we want to actually call these

on the proxies right because box this

box contracts address this box contract

is always going to be the same address

and can't change

the proxy code can change we want to

always call these functions to the proxy

and not to the box here right so the way

we do that is we can do proxy box

equals

contract dot from

abi

we'll call it box

on the proxy.address

box.abi

and of course we'll

import this from brownie

what we're doing here

is we're assigning

this proxy address the abi

of the box contract and this is going to

work because the proxy is going to

delegate all of its calls to the box

contract

typically if you put an abi on top of an

address that doesn't have those

functions that the api defines it would

just error

right but the proxy is actually going to

delegate all those calls to the box

so we could actually go ahead and try

something like print

proxybox dot

retrieve hopefully that's about that

right and even though

we're using the proxy address here we

are going to delegate the call

to

box so let's go ahead and run this so

we'll do brownie run scripts

deploy box it's going to deploy the box

it's going to deploy the admin it's

going to encode that initializer

function which we've set to nothing then

it's going to deploy our transparent

upgradable proxy and then it's going to

call

retrieve

on the transparent upgradable proxy

instead of our box so let's do this

and perfect we did it right it's

returning zero here that's awesome what

we could also do is we could also do

proxybox.store

one

and then we'll call retrieve we'll see

what happens here

whoops it's yelling at me because i got

to do

from

account

now let's go ahead and run it

and perfect see so after we stored on

the proxy box on this proxy

we're able to retrieve the value there

so this is fantastic all right now that

we've deployed it let's learn how to

upgrade it we're going to change this to

deploy

and upgrade

dot pi and we're just going to do

everything in here so now that

everything's deployed let's go ahead and

now upgrade this so so now we can always

point to this proxy box address and it's

going to be the most recent upgrade it's

always going to have the code that we

want it to have so let's go ahead and

upgrade from box that doesn't have that

increment to box v2 that does indeed

have this increment function so let's

try this out so first thing we need to

do is we actually need to deploy that

box v2

so we'll do box v2

equals box

b2

dot deploy

we'll save from

account

and we'll leave it like that of course

we're going to have to import box v2

from brownie

and right now actually let's even do

proxy box

increment

if we call boxy proc

proxy box that increments from account

this should error right it shouldn't be

able to call this increment function

because that doesn't exist

oh and then we also change the name of

the script sorry

this is actually going to be

deploy and upgrade

and perfect we see it actually errors

out here it says hey box object doesn't

have this increment function you're

crazy i don't know what you're talking

about

well good that's what we want to do

so let's delete that line

box v2 and we'll even do a quick little

upgrade here

now all we need to do is call

an upgrade function now basically all we

have to do is call this upgrade to

function right but depending on if we've

added a proxy admin contract if we're

using initializer function there might

be a couple of of different ways to go

about this so i like to just wrap

everything up into its own upgrade

function you'll see what i mean in just

a second so

what i like to do again we're going to

pop into our helpful scripts and we're

going to create a new one called upgrade

now for parameters in here of course

we're going to take some type of account

so that we have something to account

to deploy from

we're going to use the proxy which is

again going to be that proxy contract

which is going to be our proxy contract

here we're going to need a new

implementation

address we're gonna need the proxy admin

contract

which could be none for us we're gonna

have one but it could be none and then

we're gonna have an

initializer

which also could be none

and then we're going to have the args

for the initializer which also could be

known again this star

is a special thing in python which says

any number of arguments

will just get stored into this list

called args and perfect this is going to

be our function that's just going to

take care of everything for us so first

thing let's check to see if there is a

proxy admin contract

so we'll say if

there is a proxy admin contract

then we want to check to see if there is

an initializer

what we're going to do is we're first

going to want to encode that function

data of course so we'll say encoded

function call

equals and code

function data

with the initializer

and those star args

this is going to be the encoded

initializer function here

then all we have to do and actually

let's do start with a blank transaction

equals none

we'll say

transaction

equals

proxy admin contract since we're using

one of these proxy admin contracts since

we've detected one

dot

upgrade and call since we also have an

initializer

we're going to pass the

proxy.address

new implementation address

and the encoded function call and then

of course

from

account

so this upgrade and call if we look in

that proxy admin

there's this upgrading call function

right on the proxy admin and it just

calls upgrade to and call of the proxy

contract

so hopefully don't don't let this bog

you down a little bit that there's kind

of a lot of mix and matching going on

but this is what's going on

i'm sorry this is encoded function call

not encoded function data

great now if they don't have an

initializer

well what do we do well we don't need to

encode any function call here we need to

say

transaction

equals

that proxy admin contract

dot upgrade

so it has an upgrading call it also just

has a regular old upgrade so we'll just

call upgrade

and we'll give it the proxy.address

the new implementation address

and then

from

account

now if it doesn't have a proxy admin

contract this means that the admin is

just going to be a regular old wallet

well what do we do then well first

check to see if it has an initializer

still

and if it does we need again

to encode that function call we can just

copy and paste that there and then once

that's encoded we can just call directly

off the proxy contract we're going to

call exactly what the proxy admin

contract is calling which can be

proxy.upgrade

to

and call

we're going to give it the new

implementation address

the encoded

function call

and then from

account

and let's wrap this all up in a big else

so if proxy admin contract do this stuff

else do this stuff

if initializer do that otherwise we can

just do

transaction equals

proxy dot

upgrade 2 and we just add that new

implementation address

from

account

and then we'll finally return

transaction

so i know that there's a lot here but

we're really just making this upgrade

function really general we could always

just know okay if we we we're going to

use a proxy admin let's just do it like

this okay no we're not going to use a

proxy admin we're also not going to use

an initializer great it would just look

like this but this is essentially all

that we have to do so now that we now

that we have our upgrade function

we can go ahead and use it here

so we need to give it an account a proxy

a new implementation address

so we'll say account so we'll say

upgrade

transaction equals upgrade account

we need a proxy and a new implementation

address we're going to give it the proxy

and we're going to give it

box

v2.address for that new address

we do have a proxy admin contract

so we'll say proxy

admin

contract equals

proxy admin and we don't have an

initializer so we can leave that part

blank

of course we need to import this upgrade

function from our helpful scripts

and this is all that we need so now we

can do print

proxy has been upgraded and what we

could do now is we can do proxy box

equals contract dot

from abi

we'll call it box v2

we'll give it the proxy.address

box v2.abi

and now we should be able to call

proxybox.increment

from account and then we can print

proxy box

dot re

retrieve

and this should now be one and what

we'll actually see is that this will

return two

why does it return two

well in our original proxy box we stored

one so it started with one we then

upgraded to this new contract and then

let's actually just do a

wait of course

we upgraded to a new contract

right here

however the storage of that contract

stayed in the proxy so that one stayed

in the proxy so even though we upgraded

the contract

there's still one stored at the location

in storage so then when we call

increment now and then we call retrieve

it's gonna go from one to two so let's

go ahead and run this

brownie run scripts

deploy an upgrade enter

and boom that is exactly what we see

output here this is an incredibly

incredibly powerful and advanced feature

and if you've gotten to this point you

are on the border of being one of the

most powerful smart contract engineers

on the planet huge congratulations for

getting this far but we're not quite

done we of course need to write some

tests because that is what's going to

make sure our project always stays in

sync and always stays up to date so

let's write a couple of tests here so

let's create a new file

we'll call test

box proxy dot pi

and for this we're really just going to

test to see that our contracts work

we're going to see that this box

actually is going to work correctly so

let's create a new test

def

proxy

delegates calls

so we're going to make sure that we

actually can delegate calls to our

contract we're going to say account

equals

get account

which means we have to do from

scripts.helpfulscripts

import get account

then we're gonna do

box

equals

box.deploy

of course this is going to be from

account

since we're using box we're going to do

from brownie import

box

we're going to do this proxy admin so

we're going to say proxy admin

equals proxyadmin.deploy

of course from

account

let's import proxy admin from brownie

all right so now we'll do the box

encoded

initializer function

or whatever we call to perform this is

going to be that encode

function data which

my vs code actually automatically

imported thanks vs code

and again we're leaving it blank

because we're not actually going to have

a store there and then we're just going

to go ahead and run that deployment so

we're going to say proxy equals

transparent

upgrade

proxy

and we're going to grab this from

brownie dot deploy

say again the box.address

proxyadmin.address

box encoded initializer function

i'm going to say from

account and then we'll give this a gas

limit

of

two three one two three

now we're gonna put the abi on top of

this proxy so we're gonna say proxy box

equals

contract dot from abi

we're gonna name it box

this is going to be with the

proxy.address

[Music]

and the box.api

of course we're going to need to

import contract from brownie

and okay so now we can assert

proxybox

dot retrieve

if i spot that right is equal to zero

then we're going to do proxy box

that's store

we'll do one

and this will be from account

and then we're going to sir again

this proxybox.retrieve

should now equal 1.

so we're using this proxy contract

we've slapped the abi on top of it and

this should work

so we're just testing to see that our

proxy is working correctly

so we can go ahead and test this then

with

rounding test

and beautiful it passed

now let's go ahead and create a new

script for testing the upgrades create a

new file called test

box v2 upgrades

dot pi

and let's do it

called def

test

proxy upgrades

so account

it's gonna be equal to get account

hopefully at this point you're getting

pretty good at writing these these tests

from

scripts.helpfulscripts

imports

and of course we want to add this init

dot pi just in case you forgot so now

we're going to import get

account perfect so we have our account

here now as you can see we're doing a

lot of this box equals box dot deploy

deploy the proxy admin it would probably

make sense in one of your scripts to

just write a deploy three

to write a function called like deploy

all or something like that

so again if you guys want to learn more

if you want to improve upon this i would

highly recommend you go back and you

make some of those improvements to to

really modularize this up but for the

time being let's just keep going

so box.deploy

from

account

and since we're doing this we're going

to do from

brownie import box

say proxy

admin

equals

proxyadmin.deploy

this will also be from

[Music]

account

comma proxy admin

we're going to get those initializer

functions so we'll say box

encoded

initializer

function

equals encode

function data which we're going to grab

from our helpful scripts as well

and then we're going to do the proxy

again

box equals transparent up

gradable proxy

that deploy

we've got to import this from brownie as

well oops not twice though

deploy

it's going to have the box that address

proxy admin dot address

box encoded initializer function

from account

gas limit

one two three one two three

all right

so we have the proxy deployed we've

already tested that this proxy works in

this test box proxy so we're not going

to go ahead and test that again

what we're going to do instead now is

now we're going to deploy

box v2

and we're going to update the proxy and

make sure that everything still works

so we're going to do box v2

equals box v2

dot deploy

it's going to be from

[Music]

account of course

now we're going to say proxy

box

equals

contract.from api

box v2

proxy.address

v2.abi

and we're going to grab

both this

and this from brownie

and what we're going to try to do

is slapping this abi

onto this proxy address we're going to

try to call a function only box v2 can

call

however we know that

like what we tested before it actually

should revert

so we can actually check for reverts by

importing

pi test

and we can say

with pi test

dot

raises

and i know that

this is a brownie exception i know what

type of exception this is it's an

exceptions dot virtual machine error

you can figure out what type of error

this is by

just just running it and getting the

error so this is actually from brownie

this exceptions thing so we're going to

actually also import exceptions from

brownie we're going to say

proxybox.increment

from

count

and i saved and everything sorry got

formatted here but calling

proxybox.increment should throw this

exceptions.virtual machine error so this

test will pass if this throws an error

and that's how we test that so we want

this to throw an error the first time we

call it then we're going to upgrade and

then we'll call it again and it'll

actually work

now we're going to call upgrade

on account

proxy

box v2

proxyadmin

contract equals

proxy admin

we're going to need to grab upgrade from

our helpful scripts and now we should

actually be able to

call increment with our proxy box

so first we'll do a quick assert

proxy box dot

retrieve equals zero

then we'll do proxy proxybox.increment

from

account

and then we'll assert

proxybox dot retrieve

is

one so we're deploying our box we're

deploying our proxy and everything

around it

then we're deploying our v2

implementation

we're trying to call increment which

won't work we then upgrade our proxy to

this new address

and then we can go ahead

and call

increment and it should actually

increment our box here

so let's go ahead and run this test

brownie run test

excuse me

ronnie test dash k

grab this paste it in

and we've done it our tests are working

correctly so we know that our box is

working correctly

awesome great job like i said this is an

incredibly incredibly powerful feature

to be able to do these upgrades with

these there comes a lot of risk at least

in the form of centralization risk if

you're the only wallet that controls the

proxy that means your application is

centralized full stop so if you're going

to deploy anything with proxies to

mainnet

absolutely absolutely be sure to get it

audited beforehand

now before we close this project up

let's actually deploy this to an actual

test snap

so that we can see everything that goes

on when we call this deploy and upgrade

let's go ahead and do it

so

let's pop into our emv file

and let's paste the variables that we

have in here we need the private key web

three inferior project id the ether scan

token

awesome

let's even

let's even publish the source of all

these contracts so that we can see them

on etherscan

so for box we'll do a little comma here

we'll say publish

source equals true

i'm just going to copy this comma to

publish source equals true

and paste it on all of my deployments

over source equals true

publish source equals true on the

on the admin

on the initial transparent upgradable

proxy

on the box v2 deployment

and that's it

i've got my ether scan token my web 3

and fira my private key my brownie

config is indeed pulling from the

private key my env has env let's check

to see my wallet

we have some rink being here perfect

let's do this

brownie run scripts

deploy and upgrade

network

rink

all right so it looks like a couple of

our contracts weren't able to actually

verify there are a couple bugs being

worked out with some of the verification

so we're going to ignore the ones that

weren't able to be verified here but

let's go ahead grab these addresses pop

them onto the rink etherscan and see

what just happened

this is our box implementation let's

grab this address let's paste it into

the rinkby testnet ether scan awesome

this is exactly what we have contract

has been verified this is exactly the

code that we have here

and we can see all we have is a contract

creation and this is exactly correct

because when we call

the store function on this it's actually

going to get stored we never actually

called any functions directly on this

contract all we did was deploy it which

makes perfect sense let's go check out

this proxy admin now

this second address

the second counter that we deployed

sadly this one didn't get

verified however we can see we did

indeed call this upgrade function at

some point

which makes a lot of sense

if we look at our script

proxy admin

in our upgrade code since we did have a

proxy admin contract we did call that

upgrade function

perfect makes sense now let's go to this

transparent upgradable proxy this is

going to be the most interesting one out

of all of our

applications

interestingly enough we look at this

contract we can see store in increment

both have been called on this contract

not on the box because again this is the

proxy that we're going to call all the

functions on to make our contracts

upgradable internal transactions are

calls that another smart contract made

to this transaction and if we look at a

couple of these

we can see if we click more

we had increment called from another

contract which makes sense we had

upgrade called from the proxy admin

and then we also of course we had store

called from another contract and if we

verified this we would be able to see

etherscan recognize this as a proxy

contract as well hopefully when you work

with this you'll be able to verify it as

well but if not not a big deal you can

always just manually do it later

yourself so this was an incredibly

powerful project that we just did here

and that we worked on and all right

maybe take a nap maybe go for a walk get

some food get a drink because we are on

to our last coding project now i do want

to say that this project is considered a

bonus because we're going to be going

very quickly over the front end pieces

we're going to take all the building

blocks that we've learned and build an

amazing full stack application gear up

get ready let's jump into this bonus

project and then after we finish this up

we're going to close everything out with

a final quick section about security the

future and and thank you for joining

this course so let's do this last one

all right now we are moving on to our

final project this is going to be the

most advanced products and combine all

the knowledge that we've learned so far

into one project

then we're additionally going to put a

front end or a user interface onto this

project when we build our own

applications we're going to need a way

for non-devs to actually interact with

it in a meaningful way so now this isn't

a front end or react tutorial course

although we will be explaining some of

the choices that we've made and how to

actually do them you should be able to

follow along fine even if you don't have

any front end experience here if you're

looking for a full front end tutorial

free code camp has some amazing videos

that you can absolutely try out all

right welcome back everybody and now

we're going to be embarking on the most

exciting the most end to end we're going

to take everything that we've learned

and wrap it all together in this single

last application here and we're also

going to be learning about front end

development we're going to be building a

front end on top of our application on

top of our contracts here now this isn't

a front end tutorial however free code

camp has some wonderful wonderful react

tutorials we're going to be teaching you

guys just enough so that you can go

ahead jump in and build your own simple

but also kind of nice looking front ends

on top of whatever contracts that you

have

for those of you who want users to

actually interact with your applications

and interact with your contracts

building a usable front end is a really

important piece so let's take a quick

walkthrough of what this application is

going to look like so here is our our

front end here and what this application

is going to allow users to do is it's

going to allow users to stake or deposit

their tokens into what's called our

token farm contract once they have some

token deposited that's when you can kind

of go get creative with what you want

those tokens to do

you could use it as staking in some

governance you could use it to you could

go ahead and invest it in something like

ave or another d5 protocol to gain

interest you could build a yield

aggregator there's a ton a ton of

different features that you can actually

do once you have users stake their

tokens and here's how they would do it

on their ui side so we have this little

button here which we go ahead and click

connect on metamask is going to pop up

and we're automatically going to sign in

that's going to connect our meta mask to

this user interface now so if i look at

my meta mask i'm on the coven test

network we can see that i am indeed

connected now what i can do

is i can now stake some of my tokens

into this contract we currently have

three different types of tokens that

this platform allows you to stake

wrapped ether

fiu which is mimicking die on the test

network and our dap token this dap token

is going to be the reward token that our

platform gives users as an incentive for

staking on our platform once we stake we

can actually then unstake and that's

really it

so we'll go ahead and stake maybe we'll

stake 10 dap we'll hit stake metamask

will pop up this is the approve function

this first approved function that gets

called we get a really nice little

waiting

bar here and once it's been approved we

get a notification saying the transfer's

unapproved we then go ahead and we'll

confirm staking we'll get this little

loading bar while it's being staked and

we'll see that pop-up that says tokens

staked successfully

now if we go to the token farm contract

we can see that we have 10 of this dap

token state

we can also unstake it the other thing

that we can do is as admins of this

wallet we can actually issue a reward

to our users based on how much they've

staked so you see right now we have 95

dap token

we have 10 dap tokens staked on the back

end i'm going to run an issue token

script it's going to send all users that

have some stake a little bit of a dap

token reward now you can see it's been

updated

and we have we've been given a little

bit of dap token that resembles the

amount of dap token that we have staked

the way that we figure out the value of

all of our different tokens is using of

course chaining price feeds we can then

of course unstake everything

and we see tokens unstaked successfully

and that's it and this is what we're

going to build now we aren't going to go

over the unstaking portion of the front

end application here right here's what

it would look like if you were to go

ahead and finish building out the front

end yourself there is a full repository

with the entire front end with this

unstaking piece but for simplicity we're

just going to skip over this unstaking

bit so let's go ahead and get started

i'm going to go ahead and make a new

directory called defy

stake

yield

brownie

and then i'm going to open

this up in a new text editor now the

first thing of course that we want to

work with

is going to be our contract so we're in

here remember

always start with brownie init

or you can start with the chain link mix

i'm just going to go ahead and start

with brownie unit and perfect here is

our setup all right first thing we're

going to do is we're going to make our

app token dot sol

this is going to be the token that we're

going to give out to users who are

staking on our platform this is our

reward token you might have heard of

yield farming or liquidity mining this

is our token that allows users to

actually engage and participate in that

and this is just a regular old erc20 so

you guys already know we've done this

before and for this one we're even going

to use the latest and greatest in

solidity remember i said that you're

going to have to get really good at

bouncing around between solidity

versions so for this one we're going to

do everything in 0.8

so let's go ahead and do that so we're

going to do pragma

solidity

0.8.0

and we're going to do this the exact

same way we made our other erc20 token

we're going to go ahead and use open

zeppelin again we can even just copy

paste the import from their

documentation or we can just write it

out

import

at open zeppelin

contracts slash token

erc20

erc20.sol

and you guessed it because we're using

this at opens up on syntax we're gonna

make a new file

routing config.yaml

we're gonna make some dependencies

we'll do open

zeppelin slash open

[Music]

zeppelin

contracts

this time we're going to actually use

version 4 of these

at 4.2.0

and again you can find out everything

about this package by going to opens up

when slash opens up on contracts on

github and then compiler

sulk

remappings

at open

zeppelin

equals

this part right here

paste it in okay

great

then what we can do

we can go back to our dap token and just

do some basic erc20 bits here

so do contract

dap token

is erc20

and we'll give it our constructor

public

erc20

we'll call it

depth token and we'll give it a symbol

of dep

and we'll give it an initial supply as

well

so we'll call the mint function

and we'll set the

meshes.sender as the owner give it an

initial supply of one million which will

be one one two three one two three plus

those eighteen zeros so one two three

four five six seven eight nine ten one

two three four five six seven eight

and now that we have our first contract

we can try to compile it

ronnie

compile

and looks like it worked great

now we're gonna go on and to create our

more interesting contract

our token farm

we can even take a quick second and

figure out what we want this to be able

to do

well we want to be able to stake tokens

tokens

issue tokens this is going to be issuing

those token rewards

we're probably going to want to add

allowed

tokens to add more tokens to be

allowed to be staked on our contract

and we're probably going to want some

type of

get f value function where we can

actually get the value of the underlying

stake tokens in the platform with that

in mind let's move on so

you know the drill pragma solidity

carrots 0.8.0

and we're going to be here for a while

so i'm going to close those out

and this will be our contract

token farm

contract token farm oh and let's not

forget

our s

pdx

license

identifier

of mit well let's go ahead and start

with the staking of the tokens right

because that's going to be the most

important piece of our application so

we're going to do function

state tokens

you'll probably want to stake

an amount of token

and they'll probably want to stake

a certain address of the token

so

some amount of some token

now there's a couple things we need to

keep in mind here what tokens can they

stake

how much

can they stake

so these are our first two questions

for our application we're just going to

say you can stake any amount greater

than zero so we can even add that we'll

do require

amount

is greater than zero

and if it's not we'll just say

amount

must be more

than zero

since we're using version 8 we don't

have to worry about anything to do with

safe math which is awesome so we can

just go ahead and do stuff like this we

now we only want certain specific tokens

to be staked on our platform so we could

say require token

is allowed

or something to this effect so we might

have to actually create a token is

allowed function

so let's go ahead and create that

function

token is

allowed

it'll take

some token address make it a public

function and it'll return

a boolean it'll return true if that

token's allowed or false if it's not

allowed so how do we know if a token is

actually allowed we probably want some

list or some mapping of these tokens and

whether or not they're allowed after all

we've learned you'll probably learn that

there definitely are some trade-offs

between lists and mappings here for

simplicity's sake we're just going to

stick with a list for now

so we're going to create an address

array

we'll make it public

called allowed token

and this will just be a list of all the

different allowed tokens

for our token is allowed function we'll

just loop through this list and see if

that token is in there

so we'll do a for loop

four

uint256

allowed tokens index

equals zero

allowed tokens index

is less than

[Music]

allowed tokens dot length

allowed tokens index plus plus

so we're going to loop through this list

and we're just going to say if

allowed tokens

of allow token index

equals equals

this token

then we're going to return

true

otherwise if we get through this whole

for loop and we don't find this token in

here we're just going to return false

now we have a way to check to see if

allowed tokens are there let's actually

write a function to add aloud tokens

so we can do function

add aloud tokens

address token

public function and we'll do allowed

tokens and we'll just push

it onto that array now adding allowed

tokens is probably something we only

want the admin wallet or the owner of

this contract to do so we'll add only

owner

as a modifier to this function and we'll

make this token farm ownable is

ownable and we'll import from open

zeppelin here too

import at open

zeppelin

contracts slash access

ownable.soul

let's do a quick compile

great things are being compiled

fantastically now that we have a little

bit of functionality here now might be a

good time to actually go ahead and start

writing some tests if you want to since

i know that we're going to change the

constructor a little bit and we're going

to change a little bit of how this is

actually formatted i'm just going to

keep going but now might be a great time

should i start writing some tests for my

application

you know we're going to do those tests

later on anyways though all right great

but in any case now that we have these

two functions we can go ahead and

actually start checking to see if the

tokens that these stakers are going to

stake is actually allowed

so what we can do now is we're going to

add this require statement in we can

require token

is allowed

of token

otherwise we'll just say token

is currently

not allowed

and perfect now we have two required

statements that answer these questions

what tokens can they stake

and how much can they stake so now all

we have to do is we just have to call

the

transfer from function on the erc20

remember erc20 remember erc20s have

these two transfer type functions they

have transfer and they also have

transfer from

transfer only works if it's being called

from the wallet who owns the tokens if

we don't own the token we have to do

transfer from and they have to call

approve first so we're going to call the

transfer from so we're going to call the

transfer from function on the erc20

since our token farm contract isn't the

one that owns the erc20 we also have to

we also have to have the avi to actually

call this transfer from function so

we're going to need

the ierc20 interface we could go ahead

and pop it in here we could also make it

near c20 contract we could also just

grab it from openzep1

so we'll do import

at open

zeppelin contracts slash token slash

erc20

ierc20.sol

we're using the interface here because

we don't need the whole contract anyways

let's now wrap ier c20 let's wrap this

token address

as an erc20 token so now we have the abi

via this interface and the address

and we'll call that transfer

from

from the message.sender

and we'll send it

to this token farm contract so from

whoever calls stake tokens

to this token farm contract

and we'll send the amount

and perfect now we just need to keep

track of how much of these tokens

they've actually sent us so we're going

to want to create

some type of mapping here

and this mapping is going to map token

address

to

sticker address

to

the amount this way we can keep track of

how much of each token each staker has

staked

so it's a mapping per token per staker

per amount

so we'll just call this

mapping of that token address

which is going to get mapped to

another mapping

of those

user addresses which then gets mapped to

a uni-256 so we're mapping the token

address to the staker address to the

amount we'll make this a public mapping

we'll call it

staking balance now that we have this

mapping

in our state token function

what we can do is we can say staking

balance of this token

from message.sender

is now going to equal whatever balance

that they had before plus

the amount

all right this is great now we have a

way for users to stake different tokens

that we've actually allowed them to

stake on our platform awesome work so

what do we want them to be able to do

next we want them to unstate tokens we

want to be able to issue some reward we

want to be able to get the eth value

based on that reward typically you might

want to do this unstake tokens bit first

however i know that we're actually going

to need some additional functionality in

our state tokens function for us to

actually issue tokens properly so let's

just go ahead and do this issue tokens

bit remember this issue tokens is a

reward we're giving to the users who use

our platform so we want to issue some

tokens based off the value

of the underlying tokens that they've

given us

so for example

maybe

they've deposited 100 eth and we want to

do

a ratio of one to one

for every one each

we give one depth token

that's pretty easy for us to figure out

however let's say they have 50 each and

50 die staked and we want to give a

reward of

one dap

one dapp token

per one die

well then we'd have to convert all of

our eath into die so we know that

conversion ratio for the dap token so

that's the problem that we're going to

work on now let's create this function

called issue tokens

and this

is going to be a function only callable

again by the owner

or the admin of this contract so how do

we actually go ahead and issue tokens

here well the first thought would be to

loop through a list of all the stakers

that we have but right now we don't have

a list of stakers what do we have we

have a mapping of stakers and we have a

list of allowed tokens well we're

probably going to need to have a list of

stakers so we'll do an address array

because again we can't loop through a

mapping so we'll do an address array

we'll make it public

called stakers

this is just a list of all the different

stakers on our platform now when

somebody stakes a token

we're going to have to update this

list

we want to make sure they're only added

if they're not already on the list

so in order for us to do this we should

get an idea of how many unique tokens a

user actually has

so i'm going to create a function called

update

unique

tokens staked

with message.sender

and the token

and what this function is going to do

it's going to get a good idea of how

many unique tokens a user has

and if a user has one unique token we

can add them to the list

if they have more than one we know that

they've already been added to the list

so we don't need to add them there

so let's create this

function update unique token state

we'll have it input an address

user

and an address

token

and we'll make this

an internal function

so that only this contract can call this

function and what we'll say is if

staking balance

let's even do a little underscores here

of token

of user

is less than or equal to zero

we're going to update some unique tokens

staked mapping so we'll say unique token

staked

of the user

it's going to equal

the unique token staker of the user

plus one and since we have this new

mapping called unique token staked we'll

make that as well

so we'll do a mapping

of an address

to

the un256

public called unique tokens state so

this way we know how many different

tokens each one of these addresses

actually has staked now that we have a

better idea of the unique tokens each

one of these users has staked what we

can do

is we can figure out whether or not we

want to push them onto this stakers list

if they're already on there we don't

want to push them on there if they're

not on there then we do want to push

them on there so we can just do is say

if unique token staked

of

message.sender

it's equal to one if they have one

unique token state if this is their

first unique token we're going to add

them to that stakers list so we'll say

stakers.push

message.sender and this is going to be

our completed sake tokens function here

so we had to add this little extra

functionality between the unique tokens

to figure out how to actually issue some

reward for them but now that we have

this list and it's going to get updated

here

and it will also get updated when we

unstake

what we can do now is just loop through

this list of stakers so we can say 4

unit 256

staker's index equals zero

stakers index is less than stakers dot

length

stakers index

plus plus

and now we're going to issue some of

these tokens here so we're going to say

the address

recipient

equals stickers

stakers index so one at a time we're

going to loop through grab these

recipients and then we're going to send

them

a token reward

based on their total

value locked

so we got to do a couple things here we

have to send them a token reward we have

to figure out how to actually send them

this token and then we also have to get

their total value locked

so let's do this to send them a token

reward this is going to be this dap

token that we created in the beginning

this is going to be our dap token so

right when we deploy this contract we

need to know what a reward token is

actually going to be so we can do

right at the top and then i'm actually

going to

i'm actually just going to move this

array

up here so that they're all kind of

nicely together what we need to do

is we need to create a constructor

right when we deploy this contract we

need to know what is the address of the

dap token what's the address of the

reward token that we're going to give

out

so we can say constructor it will be

passed an address of the dap token

address

this will be a public function

and

we'll store this dap token as a global

variable

so we can say

ierc20 since we're already importing it

here

public

dap token

what we can do now is set depth token

equals ierc20

underscore

dap token address so now we have this

dap token with its associated address

and what we can do now

is call functions on it for example we

can call

dap token

dot transfer

we can call transfer here because our

token farm contract is going to be the

contract that actually holds all these

dap tokens and we're going to send this

token to

the recipient of course

but how much are we going to send right

how much this of this token

are we going to send to them well we

need some function to get the total

value so we're going to say u and 256

use your total value

equals

some function

right and we can go ahead and define

that right now we'll call this function

get user total value right or get

recipient total value or whatever you

want to say

so we'll pop recipient in here and let's

go ahead and create this function so

we'll call function get user

total

value

address

user

and this is where we do a lot of looping

right we're gonna we gotta find out how

much each of these tokens actually has

now what a lot of protocols do instead

of actually them sending and them

issuing the tokens is they actually just

have some internal method that allows

people to go and claim their tokens

right you've probably seen that before

people claiming airdrops that's because

it's a lot more gas efficient to have

users claim the airdropped instead

of the application actually issuing the

tokens right it's going to be very gas

expensive to do looping through all

these addresses and checking all these

addresses right we're going to do it

though because we are a wonderful

amazing protocol and we want to give our

users the best experience but in any

case this is going to be a public view

function

that will return

a uin256 right because we want to return

this total value to our issue tokens

function up here so how do we actually

get started here well let's create

a unit 256

total value

and we'll set it off to start it to be

zero here and let's even start it off

with a quick require statement right we

want to require

that the unique

token state

of this user

going to be greater than 0

right and if it's not we'll say

they don't have any tokens state right

so the value is going to be nothing

now if this is true

if they have some token staked

we'll go ahead and find it so we're

going to loop through those allowed

tokens up here

the allowed tokens and we're going to

find how much this user has for each one

of these allowed tokens

so we're going to say 4

uint

256

allowed tokens index

equals zero allowed tokens index is less

than allowed tokens dot length

allowed tokens index plus plus

and let's go ahead and we'll add the

total value and now we'll say the total

value is going to be equal to

the total value plus

however much

value this person has in these tokens in

this single token so get user total

value is the total value across all the

different tokens we need a way to get

the total value across one token so

we're going to create a new function

called get

user single token

value

and we'll pass it our user

and we'll also pass it the single token

that we're on right now so we'll pass it

allowed tokens

allowed token index

so we got to create a new function here

function get user single token value

this is going to take an address of a

user and an address of a token

it's going to be a public function

i'm just going to put this on a new line

to make it a little easier to see it's

going to be a view function

and it's going to return

a u in 256. we want to get the value of

how much this person staked of this

single token

so for example if they've staked

one each

and the price of one eath is two

thousand dollars we wanna make sure that

this returns two thousand

or if they have two hundred die stakes

and the price of two hundred die is two

hundred dollars we want to make sure

this returns 200 right so we're getting

that conversion rate we're getting

exactly how much value this person has

staked in our application now we'll do a

quick if we'll say if

token staked

of the user

is less than or equal to zero

then we'll just go ahead and return zero

right we don't want to do a require here

right as we did up here because we want

this to actually keep going right if

this is zero we don't want the

transaction to actually revert okay we

want this to keep going so how do we

actually get

the value of a single token well we're

going to need to get the staking balance

right but we also need the price of that

token so we're going to need to get the

price of the token

and then multiply that

by the staking balance

of the token

of the user so once again we need to

create another function we'll call this

one

get token value

so in another function

we're going to call get token value

you could pass an address of a token

we'll make this a public view function

that will return

a uin256

and this of course is where we need some

pricing information and this is where

we're going to actually work with the

chain link price feeds once again and

hopefully this part is going to be a

little bit more familiar for you

so what we're going to need is a price

feed

address that's the first thing that

we're going to need so we're going to

actually have to map each token to their

associated price feed addresses so we're

going to need some mapping that does

that right so we're going to need some

mapping

that's going to map

an address

to

an address

it's going to be a public one and this

is going to be token

price feed

mapping right it's going to map the

token to their associated price feeds

and with that that means we're going to

have to have a function

called set

price feed contract

where we actually set the price feed

associated with

a token

so this will take an address of a token

and an address

of a price fee

this will be a public and this will be

only owner

we don't want anybody to be able to set

what these price feeds should be we just

want the owner to be able to do this

so we'll do token price feed mapping

of the token

is going to equal

the price fee and that's it so now we

have a way to set the price feed

contracts we have a way to map the

tokens to their price feeds right and

again

go to docs.chain.link we can go to price

feeds ethereum price feeds we can find

these different price feeds here and

this is where we're going to set those

price feeds now back down in our get

token value

we can grab that price feed address now

by saying

address

price feed address is going to equal

that token price feed mapping

of

that token parameter and now that we

have this we can use it on an aggregator

v3 interface again we can always go back

to the docs here we can grab this bit

right here

of course we're going to change it

to 0.8

and for those who would rather i just

wrote it out

we're going to import

at chain link slash contracts slash src

slash interfaces

slash agreed gate or v3 interface

dot sol

and since we're doing this import

we're gonna go to our browning config

smart contract kit

chain link

brownie contracts

and we're going to see what's the latest

version of these

now i'm going to point something out

this package recently changed to mirror

the mpm package versions so it does look

like it went backwards in versions and

there's even a little little update here

but this is the the newest version even

though it's a 0.2.1 it's literally just

to match the mpm contract tags

so this is what we're going to use so

we're going to at 0.2.1

and then in our remappings we'll also do

at chain link

equals

this bit right here

now that we've imported that we can now

grab that aggregator v3 interface

or that price feed

and say

aggregator v3 interface of price feed

address

and grab that price feed contract then

once we have this price view contract we

can call

dot latest

round data

and again you can always check back to

the documentation to see what that

function actually looks like and this is

going to return it's going to return a

whole bunch of stuff

but we only care about the price so the

first thing it returns is round id

we don't care about that so we'll just

put a comma

we do care about the n256 price so we'll

put that in there but we don't care

about the rest of these

so we'll just do

comma comma comma

because we only care about the price

here

we also care about the decimals we need

to know how many decimals the price feed

contract has that way we can match

everything up to be using the same units

so we'll say u and 256

decimals

equals price fee dot

decimals

and what we can do now is we can return

both of these so this actually needs to

return a un256 and another uint 256.

put the decimals here

and we do return

we can return both of these so we'll do

a uint

256 price we'll wrap that price into a u

and 256 and then we also need to wrap

the decimals in the u and 256 since

decimals actually returns a u uint eight

so we'll return the price and the

decimals all right now we're cooking

now

we can go ahead and start scrolling back

up and adding all this stuff in so we

can say you and 256

price you went 256 decimals

equals

this get token value that we just

created right here and then we can just

have this return

staking balance

of the token

of the user times the price

and do some interesting math here

divided by those decimals

10

raised to

decimals

and i know there's a little bit of math

here right and so you might be going

wait wait what are we doing here wrap

that up like that just so that we're

absolutely certain we're doing correct

order of operations here

so we're taking the amount

of token that the user has staked right

let's say for example

10 die

and we're taking the price of that die

maybe we have

all of our contracts all of these tokens

get converted back to the usd price so

we have die

usd actually better yet let's say we

have 10 eth

right our price feed contract is going

to be eth usd

let's say the price

is is 100 100 dollars per usd

so this first bit is we're going to do

that 10 eth

times 100 so we're going to do 10

times 100 which is going to equal to

1 000. 1000 value the only thing is we

also have to divide

by the decimals so our staking balance

is going to be in 18 decimals so it's

going to be one two three four five six

seven eight one two three four five six

seven eight nine ten

but let's say our fusd only has eight so

one two three four five six seven eight

so we need to multiply these first

and then divide by the decimals that way

we can arrive at a price that actually

makes sense is going to be a function

that we're definitely definitely

definitely going to need to test to make

sure that we're doing everything right

so that we're doing all the math

correctly but okay now that we have this

user single token value we go ahead

and come back up to our user total value

and we can literally finish this

function by just calling return

total value

and then we can pull up to our issue

tokens now that we have the total value

that this

user has actually logged we can just

transfer the amount of tokens that they

have in total value so we can say dap

token

dot transfer

this recipient we can transfer them

the total value right we'll say however

much they have in total valued staked on

our platform we'll issue them as a

reward and that is our issue tokens

function we are making great progress

all right so we have a way to stake done

we have a way to issue

done

we have a way to get

value or just get value

done

we've added a way

[Music]

to add allowed tokens and all we have to

do now is add some way to unstake the

tokens

so let's go ahead and create this

function

i'm going to make it right underneath

the state token one

we'll do function

unstake tokens

we'll do we'll pass it the token address

we'll make this a public function so

anybody can call this the first thing

we're going to want to do

is fetch the staking balance how much of

this token does this user have so we'll

see you in 256

balance equals

staking balance

of the token

from message.sender

and we're going to require

the balance

is greater than zero

otherwise we'll say staking

balance

cannot be zero

and then we're going to do a transfer

so we'll do ierc ierc20

of the token

dot transfer

message.sender

balance

once we actually transfer the token

we'll do staking balance

of this token

of message.sender

we're going to update this balance

to now be zero right because we're going

to transfer the entire balance here and

then we're going to update how many of

those unique tokens that they have

now a quick note here later on we're

going to learn about reentrancy attacks

so at some point come back here and

figure out hey is this vulnerable to

re-entrance the attacks so we'll say

unique

token staked

of message.sender

it's going to equal

unique token state

message.sender

minus 1.

now the last thing that we could do is

we probably should actually update our

stakers array

to remove this person if they no longer

have anything staked this is a little

bit sloppy but we're just going to skip

doing that for the time being however if

you want to go back and add the

functionality to remove the stakers from

the stakers list as they unstag please

go for it it's not a big deal if we

don't actually do this because our issue

tokens function is actually going to

check to see how much they actually have

staked and if they don't have anything

staked then they're not going to get

sent any tokens

but all right that's basically all of

the functionality here

let's just try a quick sanity check with

a brownie compile

whoops i forgot to add v0.8 in here

let's try again that little bit

this needs to be token

and this needs to be user whoops and

then it looks like i did the same thing

down here this is actually staking

balance

let's try it again

and perfect everything is at least

compiling correctly just because it's

compiling correctly though doesn't

necessarily mean that we're doing

everything correctly

so this is fantastic typically now we'd

want to go ahead and start doing our

tests i'm actually going to go ahead and

build one of our scripts first the

reason i'm going to build one of the

scripts first is because i'm going to

use my deploy script pretty regularly in

my test i'm going to use it as part of

my testing this way i can also test some

of my scripts as well in addition to the

contracts so let's go ahead and make our

deploy script

so let's create a new file in here

we'll call it deploy.pi

we'll also create

an init.pi for those of you on older

versions of python and let's go ahead

and do this so we're going to have a

main function in here and in our main

function we're actually just going to

call deploy

token farm

and

dap token

and then we're going to have a function

def

deploy

token farm

and

token

right and i should be able to run

running run scripts deploy.pi

and great everything's compiling right

and we're running our scripts here so

first thing that we're going to want to

do as always is get our account and i am

going to copy a couple of those helpful

scripts from our past projects so i'm

actually going to pull up our nft demo

that we did so i'm actually going to go

to our chain link mix that we did i'm

going to grab our helpful scripts

remember we can always jump onto the

chain link mix here and we can just grab

some of the scripts from here so we

could go to scripts helpful scripts and

just copy paste this whole thing or just

grab it like i did right these are going

to be those exact same scripts that we

built previously so now we have our

helpful scripts in here right we're

going to have this contract to mock for

running our tests we have get account so

we can get our accounts easily we have

encode function data which we're not

going to have to work with since we're

not doing upgradable contracts but we

have it here anyways we have upgrade

which we're also not going to use but we

have it here anyways we have get

contract which returns mocks if they're

not already deployed or it just returns

whatever contract that we're looking for

and then of course we have our deploy

mox script here so now we can do from

scripts dot helpful scripts

import

get account

and perfect we can get our account like

that no problem now and now we're going

to want to start deploying some

contracts so we're going to deploy that

dap token first so we'll do from brownie

import dap token and we'll do

dap token

equals

gap token

dot deploy

and this takes no parameters so we can

just do from

count

then we're going to want to deploy our

token farm

so we could say tokenfarm equals

tokenfarm.deploy

and this takes one parameter which is

the dap token address right because we

need that address so we can give it out

as a reward so we're going to say

dab token dot address we'll do a comma

and then we'll say from

account

and we'll need to import this

from

brownie as well and while we're here we

might as well add some publish source

bits on here so we can say publish

source equals

config we'll grab this from the config

networks

network dot show active

verify

grab network from brownie

grab config from brownie

and in our

config here

let's do networks

lad development

we'll set the verify here

to be false

and then we're going to work with the

coven chain

so we'll say coven

verify will also be false actually kovan

sorry covenant will be true

and then we'll do a persistent ganache

or verify for this will be false

and i'm even just going to put this up

here so that all these

ganache chains are kind of with each

other so we'll verify in coven but we

won't on development or ganache

now once we've deployed this token farm

contract we need a couple things right

we're going to need to send this some

dap tokens right we're going to need to

send pretty much all the dap tokens so

that i can actually give those tokens

out as a reward so we're going to want

to do a transaction it's going to equal

to

dap token

dot transfer

we'll send it to the token farm

address and then we have to choose how

much we're going to send and we'll send

the total supply

but we'll keep a little bit for

ourselves so we can do some testing and

so just in case so we'll also do minus

kept

balance some static kept balance which

we can say

at the top

we'll say the kept balance is let's keep

like 100

so this will be equal to

web 3.2 way

100

ether

so we'll do

from web 3

import web 3. so in our transfer we'll

do

dab token dot total supply minus the

kept balance and then of course we're

gonna have to do a from

[Music]

account

so now we're sending

our token farm basically 99.9

of the total supply of this dap token so

that it has this token to actually give

out as a reward we'll do a tx

dot wait we'll wait for one block

confirmation there now what do we want

to do well if we look at our token farm

we know at our state tokens function we

can only stake tokens that are allowed

in each one of these tokens also is

going to need to have some price feed

associated with it right and our token

price feed mapping

so we're going to have to add those so

what we're going to want to do is we're

going to want to create a function

called add

allowed tokens and what this is going to

do it's going to add the tokens that we

want to allow and it's going to give

them a price feed contract associated

with them so let's create this function

we'll call it def

add allowed tokens and this is going to

take a couple things we're going to want

to take that token farm because we're

going to need to call the add aloud

tokens function on it we're going to

take a dictionary

of

allowed tokens and this is going to be

the names this is going to be a

dictionary of the different token

addresses and their associated price

feeds so we're just going to price

everything in usd so so we can figure

out the value of everything in usd and

then last of course we're going to need

an account

for now i'm just going to do pass here

let's look at the different inputs that

we're going to put into this so

obviously we're going to do token farm

but then we're going to need to make

this dictionary of allowed tokens so

we're going to need the address of the

different tokens that we want to have

now how do we get the addresses of the

different tokens that we're going to use

and what are the tokens that we're even

going to use here

for simplicity we're just going to start

with three tokens we're going to allow

our platform to allow three different

tokens to be state we'll use the dap

token

as one

we use weth token or wrapped eth because

that's pretty much a standard in most

smart contract platforms and then we're

also going to use an fau token which

stands for faucet token and we're going

to pretend that this fafsa token is dye

or dai the reason we're going to use

this faucet token is because there's

this erc20 faucet.com which allows us to

get this fake faucet token we can get

unlimited amounts of this faucet token

on different test nets we're going to

pretend that this faucet token is going

to be die right so fau token slash die

so how do we actually get these

addresses well dap token we know with

token

what we can do in our config so we can

actually add those addresses here

so for coven

the weath token address is going to be

this right here which again you can go

check this out

and you can find it on etherscan you can

write your own if you want we're just

going to use this already deployed one

on coven fau token which is gonna be

this token here which i know is gonna be

this address right here

and if you want you can come here

and grab your address

paste it into this erc20faucet.com

put an amount of 10 in here

connect to metamask oh and even tells us

the token address right here which we

can just copy paste we can do mint free

tokens confirm

great says success if we don't already

have it we can take this token address

go to our meta mask

assets

add token paste it in i've already got

it

we can see right now i have 5 fau

once this confirms i'll have an

additional 10 and now you can see 15

here this is going to be this fau token

that we're going to use we have wes here

and then we know

what the depth token address is going to

be

for when we deploy it here

now we could do again we could do the

config

you know networks

etc and just always get it from our

config

or we could use our get contract method

that we grab from our helpful scripts

which will deploy a mock weath token it

doesn't exist in one of these and that's

what we want because we're going to want

to test this locally so we're going to

want to deploy our own fake weath token

so we'll say the weath token

equals get contract

with token

and then the fau token

is going to be get contract

fau token and remember what we put in

here our string that we put in here

needs to match our string in our config

now in order for this get contract to

work for weth token and the fau token

we're actually going to have to modify

our helpful scripts here so if we copied

and pasted it directly from our chain

link mix this is basically what we're

going to have here we're importing all

of our mocs which we can go ahead and

copy paste these as well from the chain

link mix our test our mock contracts

here

we have some forking implementations we

have contracts to mock which tells us

based off of the key

what token or what contract we use to

mock we have get account which we use

all the time in order for us to do this

contract to mock correctly we're going

to have to mock west and fau and

actually we don't even need all these in

here we don't even need this whole

contract to mock in fact we can get rid

of

mock oracle we can get rid of vrf

coordinator and we can even get rid of

the link token for this we do need this

sdusd price feed later on

so i'm just going to leave it in here

for now we definitely do need though fau

token which is going to be mocked to

something and we need weth token which

was going to be mocked to something else

so what are these tokens going to be

mocked to well they're each an erc20

mock but we want to give them kind of

their own identity so what we're going

to do is we're actually going to make a

mock erc20 for both fau

and for web so we're going to come in

here we're going to do new file we'll

call it mock die

dot sol

and this is going to mock that fau token

so it could be mock die it could be mock

fau whatever we want it to be and we're

just going to make this a basic erc20 so

we'll do pragma

solidity

0.8.0

we'll import at open

zeppelin

contracts token

ear c20 your c20.sol obviously this is

going to look

very familiar this should spell pragma

not whatever i just spelled this is

going to look really similar to that dap

token so now we can call contract

mock die

is erc20 and we'll do constructor

public erc20

mock die

will be the name of this

and the symbol will be die and perfect

and that's all we need we'll copy this

whole thing and then we'll do the same

thing for

mockweath.soul we'll paste this whole

thing in here

and we'll just change the name call this

mock west

crc20

mock weft

and this will be

what token right so now that we have

those mocks in here we can change fau

token to

mock die

and west token to

mock weft we can import those from

brownie and in fact we can get rid of

the mock oracle here and the vrf

coordinator

instead we'll do mock die

and mock west

now of course since we have diusd price

feed and fusd price feed we're going to

make sure we have these in our mocks

here and then we're also gonna have to

deploy these in our deploy mox script

below

so if we scroll down to deploy mocks we

can see this is what it currently has

which is pulling directly

from the chain link mix so we just go

ahead

delete the vrf coordinator mark and the

mach oracle and instead

we'll deploy

those that mock weath and that mock die

so we'll do print

deploying mock die

die token equals

mock die dot deploy

from

account

and then we'll do print

f statement

floyd to

die token.address

and then we'll do

print

deploying

mock mock web

and then we'll do

[Music]

left token

equals

mock west dot deploy

we'll say from

account

and then we'll print

this deployed

be another printf

with token.address

now additionally

we have our fusd price feed left over

from the chain link mix we also need

this die usd price feed

so we can go ahead in here

we'll add

usd price feed

and we'll set this as a mach v3

aggregator we could do is we could

parameritize this up so that the mock v3

aggregator takes maybe some different

decimals a different initial value so

that these could be different

but for the sake of testing we're just

going to leave them being the same here

so great so we have the address of the

wet token we have the addresses of the

fau token and if those don't exist on

the network we're working on we're going

to deploy a mock so now that we have all

these addresses we can do a dictionary

of allowed tokens

is going to be equal

to this dictionary that we make so we're

just going to route each one of these

contracts like the depth token

to

its equivalent price feed for the dap

token we're just going to say that the

dap is going to be equal to die

we're going to say the fau token

is also equal to die

and our weath token

of course is going to be equal to eth

so we're going to want to get a usd

price feed another di usd price feed

and an f usd price feed so in our config

we can add i usd

price feed

and since we're going to be testing

since we're going to be doing our

integration test on coven here

we'll come to the chain link docs

we'll go to ethereum price feeds

we're on coven

and we'll scroll down to

dye usd

which is this address right here

pop that in and then we'll also want the

fusd price feed

which we'll also go grab that from here

on the coven network and we'll grab that

from right here

and we'll paste it in

so now to complete this deck we can do

this get contract again and we'll deploy

mock price feeds if they don't exist

so now we can just do

get contract

die usd price feed

fau token is also going to be usd price

feed

and then our weft token is going to be

fusd price feed and awesome now we have

our dictionary of allowed tokens that we

can pass to our ad allowed tokens this

will map

the tokens and their addresses with

their associated price feeds so we can

get them all to equal the same value in

our contracts so we can go ahead and

create this function called add allowed

tokens we'll pass it this token farm

we'll pass it the dictionary of allowed

tokens and then of course we'll pass it

the account

now in our add allowed tokens function

we're going to loop through all these

different tokens and call the add allow

tokens function on it so we're gonna do

four

each token in the dictionary of allowed

tokens we're gonna do tokenfarm.add

allowed tokens

and we'll do the token.address and we'll

do from

account

we'll say

add tx equals that

we'll do add tx dot weight

1

then we're going to call this set price

feed contract so we're actually going to

set the price feed associated with that

token

so we'll do

set tx

equals token farm

dot set price feed contract

and we'll do token.address

the dictionary of allowed tokens

of

that token that we're for looping

and then of course

from

account

and we'll do

set text.wait one

and then we'll just return

the token farm but we probably don't

have to return anything and great that

deploy script looks pretty good and in

fact we're going to end our deploy

script here with returning token farm

and

adapt token this way we can actually use

this deploy script in our tests so i'm

just going to do a quick little zoom out

and we can see

our wonderful deploy script right here

and awesome it looks like we have just

about everything here

let's give this an initial test

on a local ganache chain see if our

mocks all work see if everything at

least makes sense we can call our

functions awesome it looks like we can

call all of our functions

and we can deploy our mocks and the

mocking is working at least somewhat

correctly here this is great we'll zoom

out a little bit here we've got our

deploy scripts we've got our ad allowed

token scripts we've got all of our mock

contracts added under tests things are

looking good now what do we want to do

here

well of course we want to run some tests

we want to make sure our contract is

actually going to do

what we say it's going to do you guys

ready let's jump into it so in our tests

let's make a new folder called unit

we'll add a new file we'll call it test

token farm dot pi let's do some tests

now ideally we would also write some

tests for our dap token however we're

going to skip over those because we're

basically just doing open zeppelin's

implementation

but in a full-scale production here you

probably would want to write some tests

on your tokens as well so let's get into

this let's look at our token farm and

see what we need to test remember

ideally every piece of code in our smart

contract here should be tested in some

form or another so with that in mind

let's get started so one of the first

functions that we see is set price feed

contract so let's make a test for that

so we'll do def

test

set

price

feed contract

and we're literally gonna test just this

one function so how do we test that well

first let's make sure we're on a local

network right because we only want to be

doing this

on our local network since this is one

of our unit tests

so in our arrange stage

we're going to do if

network dot show active

is not in

local

blockchain

environments

then we're going to run pi test.skip

and say only

for

local testing of course we've got a

number of pieces here that we need to

import we're going to do from browning

import network

we're going to do from

scripts.helpfulscripts

import local blockchain environments and

then

we're going to import

pi test all right so now we're going to

get an account

to make these transactions we'll say

account equals get count and let's grab

that for my helpful scripts as well so

now we have an account we can use let's

even grab a non-owner account so we'll

say non-owner

equals get account

and we'll do index equals one this will

give us a different account rather than

this account and we'll use this to check

some only owner functions and then what

we're going to do is we're going to get

the token farm

and the dap token

based off of

our deploy script so we're going to use

this deploy token farm and dap token

we're going to import that by saying

from

scripts.deploy

import

deploy token farm and dap token and

we're just going to call this function

in our test right here so we're going to

say token farm dap token equals deploy

token farm and dap token awesome this is

how we're going to do this a lot this

arrange step for a lot of these tests

here because this is how we're going to

set them up we could even hypothetically

turn this into a conf test or into a

wrapper if we wanted to but we're just

going to leave it in here like this for

now now we can move on to our act phase

so we're going to want to do

token farm

dot

set price feed contract

because remember

this is what we're testing right now and

we're going to use

a token and a price feed address so we

use the dap token dot address we'll use

get contract to actually get an fusd

price feed address

which we can also grab

for my helpful scripts get contract an

important note here if you try to set a

contract as an address parameter like

this ronnie will know okay that you're

looking for an address instead of the

actual contract in any case then we'll

do from

account

save it and it re-shifts over here now

this should work perfectly so we're

going to assert this

we're going to move into our assert

stage right

if we check our price feed mapping

this should now be updated

so we can do

assert

token farm

dot token price feed

mapping

and remember

token price feed mapping is an address

to an address so we'll say dap token

dot address this should be equal to

get contract

of fusd

price feed

this should be updated with exactly what

get contract of fuc price feed returns

in fact we can even make this a little

bit better

copy this we'll say

price feed address

equals get contract and then we'll

pop this in here and we'll pop this here

that way now we're just using this

single variable for both

all right that's our first test let's

run it brownie

test this will run the whole test suite

and we're passing awesome now let's also

do a test

to make sure that

non-owners can't call this function we

want to make sure that somebody other

than the owner who deployed this right

because deploy token farm and dap token

is going to be run by get account we

want to make sure that

somebody else can't call this function

so we'll do with pi test dot raises

exceptions dot virtual machine error

excuse me for that

getting in the way and then we'll try to

call this exact same function here right

we can even just copy paste it

but instead we'll

call it from non-owner

right

and then we do also have to import

exceptions from browning so this should

also pass

it's expecting this contract call to

actually revert so let's try this

perfect it passes

right we can double check to make sure

that this pi test.raises is working

because what if we did a count here

right

this now should fail because this isn't

going to revert and that's exactly what

happens perfect so we can leave this as

non-owner and our first test is looking

great let's even zoom out just a hairier

we can sleep easy that this function is

going to work as we intended isn't that

a wonderful feeling yes it is great

let's move on so let's look at our token

farm what's the next function aha

issue tokens all right great let's write

some tests for issue tokens so what are

we going to do

def

test

issue

tokens so how are we actually going to

do this well in order to test issuing

tokens

we actually need to

stake some tokens first

so for now i'm actually just going to do

pass here and before we test issuing the

staking tokens we need to write a test

for staking those tokens right because

in order to issue tokens you need to

have some tokens state so let's write a

test

stake tokens first and then we'll write

this test issue tokens so we'll do def

test

stake

tokens

now let's set this up

so we're going to copy this bit here

because we are going to be working on a

local network with this we'll do account

equals get account and then

we'll go ahead

and deploy the token farm and the dap

token so

this initial bit is going to be exactly

the same making sure we're on a local

network getting the account deploying

the token farm and the dap token

so now let's move into the act phase

let's go ahead and act let's go ahead

and actually send some tokens to our

token farm so first we obviously need to

call approve on the dap token contract

so we'll do dap token

dot approve

to the token farm dot address

and again you can see and again we can

go to the open zeppelin docs to figure

out what the parameters of this are but

it's going to be an address and it's

going to be some amount and then

obviously from

account

now i put a couple question marks here

because we're going to constantly be

using an amount right we're going to be

using an amount staked for a lot of our

tests here

so what we're going to do is we're

actually going to turn that into a

fixture

we're going to call it

amount

state and we're going to define this in

our conf test folder so we're going to

make our conf test file so in here we're

going to do new file

conf test dot pi

and whoops it's in the wrong directory

so we're going to go cd tests

units

i'm gonna do move

confidence.pi

down one directory and it should be in

here now if that didn't work you should

be able to drag and drop it

uh into test you just wanna pull it out

of unit is what we're doing here right

just want to get it so that's just in

this test directory here in the case in

our conf test.pi we're going to create

our first fixture

so we're going to do at pi test.fixture

we'll do def amount staked

and then we're just going to return

web3

dot 2 way

one

ether now of course we need to import pi

test here

then we're going to need to import we're

going to do from web3

import web3 and now

it saves

perfectly so now we can use this amount

staked fixture as basically a static

variable right we could have done at the

top we could do something like amount

staked equals you know that exact same

thing but

we're going to get into the habit of

working with these fixtures so we have

our def test stake tokens and we're

going to pass it this amount staked

fixture pi test and brownie will

grab all this stuff from the conf test

folder and put it into here

so now we can just use amount staked as

a parameter in our test here so once we

approve we can then do token farm

we now call

our stake tokens

function right here

and it takes an amount

and then a token address

so of course we're going to do amount

staked

as the amount and then we'll do depth

token

address

as the address and of course from

account

and perfect this is going to be our

basic action of testing the staking

functionality so we can go ahead and

down here and move into our assert phase

and we can just assert a number of

things

right

and do a little

bracket here

we're gonna do a couple of things here

we're gonna assert the token farm

that's staking balance

of dap token

that address

of account dot address

equals amount

state

so let's talk about this really quickly

what is this actually doing so if we go

to our token farm we know that we have

this mapping called staking balance and

this is a mapping of a mapping

right so we need to actually pass

two variables the first address and then

the second address to get this amount

this is how you do that syntactically

with brownie you just pass it as

additional parameters in here so we pass

the dap token address

which is going to be the token address

here

and then the account address

which is going to be the address here

and perfect

so we can even run this by doing brownie

test

dash k

test stake tokens

and great looks like that passed

perfectly

but we have a couple of other assertions

to make right because if we look at our

stake tokens function it does a lot of

things so let's check all of these and

make sure that they all are working

correctly so we'll also assert

that the

dot tokenfarm.unique

token staked

of account that address

is going to be equal to one right this

is going to be the first token so

it should have a unique token state we

should also assert that the token farm

dot stakers

at the zeroth index is going to be

this account that we're using we update

our unique token staked

we update our staking balance

and then we add

stakers.push right so we're going to be

the first

address in this array now and then i'm

going to do one other thing here too i'm

going to do return

token farm

and dap token

the reason i'm doing this is because now

we can actually use this

test in some of our other tests now

we're getting a little bit integration

here we're kind of mixing and matching

some stuff we could even probably put

this whole thing in a function in our

regular scripts directory but for

simplicity's sake this is how we're

going to architect it but great let's

test the rest of those we'll just hit up

ground to test k test stake tokens we'll

hit enter and perfect

this is passing correctly as well

awesome let's keep going now we're

moving into this test issue tokens phase

here and we're going to use our test

stake tokens test here

so the way that we're going to use this

is we're going to grab this amount

staked parameter

place it in here

and we're going to set this up exactly

the same way we're going to set this up

almost exactly the same way so we can

even just copy these few lines here

paste it

we're going to do an arrange

we're going to check to make sure we're

on a local network we're going to get

our account but instead

of doing deploy token farm and dap token

we're going to do

token farm

comma dap token

equals test stake tokens and we're going

to pass it that amount state so this is

why we're returning the token farm in

the dap token in our test stake tokens

that way we can use that function now

in our test issue tokens and perfect now

we can test issuing these tokens so to

test issuing tokens to issue this reward

we want to first take some inventory of

the current starting balances of our

address we'll say starting balance

equals

depth token dot balance of

account dot address and great this is

how we're going to start off in our

range phase now let's move to acting

open our act phase and we'll just do

tokenfarm.issue tokens

we'll save from

account

and this is really the only thing that

we're testing here so now we can move

into the arrange

stage

and we'll do assert

i'm going to do a little

parentheses here because this is going

to be a long thing and we're going to

assert that the dap token

dot balance of

the account dot address

should equal

the starting balance

plus

some new amount

what's that new amount going to be well

if we look at our issue tokens function

if we're staking in our conf test if

we're staking one

ether right

or one

die right because we're staking the dap

token we're just taking one our marks

are going to be this

fusd price feed right our mock v3

aggregator when we deploy it the initial

value is going to be this 2000 right

here and we're saying

in our mock in our sample here we're

saying

we are staking

one

depth token

which is equal

in price

to one each

so we should get 2 000 depth tokens in

reward since we're saying

since the price

of eth is

2000 usd

so there's a little bit of math here

but the initial value is going to be

2000 right you can almost think of it

like this

with 18 decimals and our application

pays us reward based off of the total

usd value that we have locked so we

actually can know that this is going to

be that 2000 price so what i'm even

going to do is i and if this isn't

already in the chain link mix shame on

me i should add this in here

because we're going to add a new

variable called initial

price feed value

it's going to be equal to 2 000. one two

three four five six seven eight nine ten

one two three four five six seven eight

that super big number and we're gonna

take that and we're gonna set that here

to our initial value is going to be now

this initial price food value

and what we can do in our test

is we can then import that

from our helpful scripts

and we can just assume that our starting

balance is going to be now we are

starting balance plus that initial price

feed balance and if we've done our math

correctly and if we've done our issue

tokens and if we've done all of our get

value correctly this should work we

should have done our testing already

on the things like get

user total value right because get user

total value is a subset of issue tokens

but we're jumping the gun a little bit

here and we're going to test this later

on anyways so

with that being said let's run this test

brownie

test dash k

test issue tokens and lovely so our math

is correct

awesome we are doing wonderfully with

her tests here we've even gotten some of

the harder ones out of the way early

which isn't too bad either now as far as

this video goes we're actually going to

stop writing the test because we're

literally just going to keep going down

that solidity file and grabbing

functions and adding tests to them we've

got all the tests located in the github

repository associated with this lesson

there is both a unit test file and an

integration test file in the github

repository if you want to just go ahead

and check that feel free to do so we're

going to move on to the next section to

keep things moving forward but i highly

highly recommend you trying to write all

these tests yourself so good luck we're

gonna have all right now we're going to

umv

private

and our website

make sure your integration projects work

well make sure that you get started if

you run your deployment on copy paste

network directly

we're going to be testing everything

works we'll save dots of course you're

going to want to get out.env file you're

going to want to add that to your

browning config address privacy and add

your web3 inferior project id and make

sure you have plenty of test dent coven

so that you can actually run these

deploy scripts we can always find the

latest faucets from the link token

contracts page under our coven or rink b

networks here we're also going to need

our wallets section we'll do from key

and this is where we'll put the dollar

sign

private

key

now

now that we've got the contract now that

we've done all the contract work we're

going to learn something totally new

that we haven't covered yet we're going

to learn to do some front end

development now like i said this isn't a

front end course and the focus isn't

going to be on front end and i want to

point out right away that this is

considered a bonus section there are a

ton of pieces in this section that we're

not going to have the time to go over

thoroughly because we're not going to be

going into what's going on on the front

end side the editing is a little bit

choppier and i highly recommend having

the documentation having the github

associated with this front end with you

while you're going through this free

code camp has an awesome video on doing

front-end work and if you want to learn

more about react and typescript and some

of the technology that we're going to go

over definitely check out those videos

after this we're going to make this

though so that you should be able to

follow along with everything that we're

doing if you're not interested in front

end feel free to go ahead and skip this

part

however understanding how these front

end applications work is really helpful

and it'll give you a

massive massive incredible skill to

actually build front ends for your smart

contracts having a really solid user

interface is really important in the

web3 in the blockchain world if people

can't use your contracts then what good

is your application so with that being

said let's jump on and let's build our

front end

and i know we said we didn't like

javascript we're gonna be working with

typescript here which is a improved

version of javascript and catches a ton

of the different bugs and allows us to

be much more explicit with how we're

working with our front end we're also

going to be working with react we're

going to be working with create react

app this is a front-end framework that

allows us to quickly spin up a front end

to build for our applications here we're

also going to be working with this tool

called used app it's a framework for

rapid dap development

and works great with react here so let's

get started building this front end the

first thing that we're going to want to

do to build a front end for our full

stack application create react app

boilerplate so you should have mpx

installed if you run mpx-version

it should show up this should be

installed from when we installed npm if

you don't have mpx installed you can run

mpm install

g npx additionally we're going to want

to install

yarn here to install yarn again you just

run mpm install dash dash global or dash

g yarn you'll know you have yarn

installed correctly if you can run yarn

dash dash version you see a version of

yarn and i have a link to install both

npx and yarn in our github repo great

once you have those we can actually

create a folder with all of our

boilerplate code in it we're going to

run mpx

create

react app we're going to call it front

end and this is going to create a new

folder called frontend

and we're going to do dash dash template

type script

because we're going to want to work like

i said with typescript instead of

javascript for those of you who've never

worked with typescript before and who

have worked with javascript don't worry

the syntax is nearly identical for those

of you who have never worked with either

don't worry we're going to walk through

everything that we do and then we'll hit

enter here what's going to happen is

you'll see we're going to create this

new react app in this new front end

folder in our project here

awesome now that we've downloaded our

create react app we have this new folder

called frontend and it's got a whole

bunch of stuff in it now typically what

different applications will actually do

is they'll have one repository for all

their python and for all their contracts

but they'll additionally have a

different folder

or different repository for their

front-end application and their

front-end work this is really good

practice we're just going to bundle

everything up into the same repo here

just to get started and just to make it

easier for us getting started here

however what you will see across

different projects is they'll have a

totally separate repo for their front

end so let's take some inventory on

what's actually going on inside this

folder so the first folder you'll see is

node modules these are basically the pip

installs these are the different

packages pulled in from javascript and

typescript we can pretty much ignore

this folder for the majority of what

we're working with here next we have our

public folder we're also not really

going to go in here but it's got some

nice little images it's got our basic

index.html which has the html that we're

going to be running with it has a couple

logo images and it has a manifest the

manifest is something that we want to

change this tells our browsers a little

bit about what our app is and what our

app actually does so this is something

that we we would change but everything

in here is pretty self-explanatory the

short name of our application the long

name of our application some icons start

url this is something that if you want

to fiddle with it later absolutely

please go for it and then robots.txt

we're not going to talk about this at

all this helps web searchers and

indexers learn a little bit more about

your site we can ignore this one as well

so for the most part we're not really

going to do anything in the public

folder or the node modules folder our

source folder however we are going to be

spending a lot of time in it has our

app.css which includes a whole bunch of

formatting for html we have app.test.tsx

this is going to be testing our front

end

yes you can even test your front end

we're going to totally skip over testing

the front end which yes i know we've

spent a lot of time testing our

contracts if you want to learn more

about testing your front ends there's

some fantastic links in the github and

in the description to go over this

app.tsx which we are going to be

spending some time in and it's one of

our the main places for us to write some

code index.css

again a formatting and styling file

anything that ends in css

is some type of formatting and styling

all these tsx are going to be type

scripts index.tsx we're going to pretty

much ignore we are going to change the

logo and we can ignore all these last

bits here a package.json this file tells

our project what dependencies it needs

and node.js packages it actually needs

to get started we have a readme which of

course is a readme we have a typescript

config which gives us some options on

how to work with typescript we're going

to ignore this and then we have our

yarn.lock which is an auto-generated

file we're not going to touch it at all

because yarn is going to automatically

create this if you're not if you're

unfamiliar with yarn.lock and unfamiliar

with a lot of this stuff don't worry too

much about it this isn't going to be a

file you're really going to need to pay

attention to but okay

now that we've created the basic create

react app we can actually go ahead and

right now we can see what a front end

will look like so we'll cd to the front

end

we'll run yarn just to make sure we have

everything installed what yarn does is

it actually installs all of our

dependencies anything in this

package.json

yarn is going to go out and download

these dependencies and store them into

node modules

and then yarn.lock is going to tell us

exactly what it downloaded once running

yarn now it just checks to see it says

ah it looks like you already have

everything installed because when we run

create react app it already goes ahead

and downloads everything but now we can

just run yarn start

if you want to know where this is coming

from if you go in your package.json

and you look under scripts

these are the four different scripts

that we actually run

running yard start runs this mpx react

scripts start which will actually start

our front end so we'll do yarn start

you'll see react script start you'll see

it says starting the development server

and after a little bit of time

we'll get something that looks like this

edit source

slash app.tsx and save and reload and

this is a super simple front end

obviously this isn't at all what we're

looking for but we've now started a

front end which is fantastic it'll say

compiled successfully it'll say you can

now view frontend in the browser

it'll tell you exactly where it's

located on our local host on the network

and it'll give you any outputs from the

front end down below

so we're just going to stop the front

end for now by hitting command c or

control c and closing it down

of course if we reload now on the front

end it's going to be blank but great so

we have a really basic setup for working

with a front end awesome if we look at

an application like app.avi.com you'll

see they have like this really fun

connect button that pops up

and they've got some nice user interface

tools for actually working with the

blockchain we don't want to have to

reinvent the wheel and build all these

custom tools for doing this so we're

going to use this application called

used app or this framework called used

app which has a whole lot of these

already built in to get started

installing all we have to do is run this

command right here yarn add use dap

slash core so here in our front end

we'll do yarn

add at use dap slash core and this will

go ahead and install all the used app

pieces into our front end so we can

actually work with used app and not

reinvent the wheel with working with

wallets and working with ethereum and

other smart contract applications

awesome now we have that installed we

can actually go ahead and start building

our front end now what we're going to do

is we're going to go to

app.tsx folder and we're going to start

in here we're going to start adjusting

some bits in here so what we can do is

we can do the yarn start and we'll get

our a little react front end here now

what we could do is we go ahead and do

something like change anything in here

right see how this line says edit source

that app source slash app and saved

reload we could do we change this whole

line

being something just like

hello

we'll save it

it'll recompile

we can go back and now it just says

hello right so this is how we can

actually upload and update our front end

we have these these wonderful return

pieces here these return sections here

which will return the html to actually

render the front end and this is also

our starting point for allowing our

application to be web 3 compatible

so if we go to this use dap

documentation right we go to our getting

started section we have a little example

here that shows kind of what what

something should look like right but

it's not exactly clear where we put all

this code

so they do have this wonderful

step-by-step bit and this is probably

the most helpful bit here it says the

first thing you need to do is set up dap

provider with optional config and wrap

your whole app in it so we're going to

use these depth provider tags right this

is the open tag and this is the closing

tag we just wrap it around our app so we

can see here this this whole thing right

now

is our app so we could take this whole

thing

delete it right and if we save right now

we can go and see

our friend is going to have nothing it's

going to be blank this function app here

that's getting exported export default

app

and this is getting rendered in this

index.tsx we have this cool little

app.html tag thing right but any case we

want to wrap this whole thing with this

tag here right

so we can even just copy this paste it

in i can do dap provider and then my vs

code even auto adds a second dap

provider here we can delete this div

class name equals app

i'll just put put a little divider in

here and just say hi and at the top

we'll just import this dap provider

thing like what is this weird tag we're

going to import it so we'll do import

depth provider

from

and use dap

core

now if we hit save we'll get this weird

error saying hey property config is

missing in our dap provider and that's

because

this dat provider needs a config

associated with it so we need to add

this config bit into this dat provider

so we're going to do

config

equals at this first bracket says we're

going to type in typescript and the

second bracket is saying we're an object

here so in this config we're going to

tell our application

a couple of different things so we're

going to tell it what supported chains

there are what are the networks that our

application can actually work with the

default value for supported change in

used app is going to be mainnet

reli

coven wrinkby robsten and xdi since

we're going to be testing only on coven

and ring b we could just do chain id dot

coven

and chain id dot chain id

is another term that we can pull right

from our used app slash core right and

now if we wanted some other chain id we

could just go ahead and put it in here

right like if we wanted to work with our

ganache we could just do one three three

seven if we wanted some other random

chain we could just put the other number

in there right but chain id coven is

going to be 42 and chain id that ring b

is going to be what is it three yeah

three or what or whatever it is and this

is all we need to get started working

with in a web 3 a blockchain compatible

application so let's go back let's save

and we'll refresh and now it just says

hi

how's it going so we're going to spend a

lot of time in this source folder and

since we're going to be here a lot let's

let's do some cleanup just to cut down

on the amount of fat that we have with

that create react app

so app.css we're going to toss this

app.test yes tests are great but we're

going to toss it we're going to leave

index.css we do need index.tsx

we don't need this logo bit anymore

because we're going to use our own logo

we do need this

we also need this

and since we're not running tests

anymore we don't need this but i'm going

to leave it in here just in case you

guys want to later on go back and add

some tests great so now we're looking a

little bit lighter and in our app let's

just remove

amp.css let's remove logo.svb

logo.svg goodbye

now okay so we're going to create what's

called a component we're going to create

a header component now in react

components are basically where you you

put modular parts of your front end and

we're going to create one of these

components is going to be our header

component to do this we're going to

create a new folder called components

and in here

we're going to create a new file called

header.ts

and this is where we're going to put our

header stuff and we're looking to to

make a little button up here right we're

looking to make a little button in this

header so what we're going to do is

we're going to import some stuff so

we're going to import use ethers

at usdap

core again if we look at the

documentation real quick this use ethers

thing has got some cool stuff it's got

this activate browser wallet thing got

this account thing

it's got some it's got some cool stuff

so what do those actually do we're going

to start by exporting a constant

variable

called header this is going to be a

function and this is some really this is

some really fancy typescript syntax what

this is meaning is that we're saying

header is a function

and here's what the function is going to

do we're going to use this use easter's

thing to get a couple variables so we're

going to say constant variable

account

activate

browser wallet

deactivate

equals use ethers

in order for us to actually use these

though we need to figure out first if

the user is connected

so we're going to create another

constant variable we'll call it is

connected

and this is going to equal

an account it's going to equal an

account it's going to equal account does

not equal

on d find

so we're saying

if the account

is undefined we're not connected if it's

not undefined then great we're connected

so we're literally just looking to see

if there's an account here and whether

or not we're connected we'll decide if

we show a connect button or not so to do

that we're going to return

a div this is where we're going to

return

some html stuff and we've got to check

to see if we're connected so we'll do is

connected i'm going to use this question

mark which is known as a tertiary

operator

which means

if this is true we're gonna do something

and if it's false we're gonna do

something else so we're saying okay if

we are connected right what do we do if

we're connected here well

we're gonna create a button

we'll have the color

equal

primary

create this button here

and then my vs code auto makes these

closing tags we'd even leave this button

blank if we want or we're actually going

to put some fancy stuff in here and then

we'll put a little function in it we'll

say on click

equals

deactivate this is this deactivate

function pulled in from our use ethers

thing i should spell it right though and

we're going to call this button

oops there's a little

parenthesis next to this so this is what

this is connect thing does so we're

saying if if we are connected

right do this

now we're going to do a little

colon here

and this is going to represent what

we're going to do if we're not connected

okay if we're not connected what we're

going to show is a different button

color can still be

primary

and we're going to do on click

we're going to do

a function

activate browser wallet

then we close up the button tag with

another backslash button

and we'll call this one though

so if we are connected we're going to

show a disconnect button and then if

we're not connected we're going to show

a connect button and that's it right

just make sure all of your divs all your

tags are matched up and we can go ahead

and save this and if we look at our ui

you'll see nothing's changed right okay

well why isn't anything changed well

this component that we just made it's

living inside of this components folder

and we've exported this this header

variable this header function right

however it's actually not in our app

here right so if we look at our

index.tsx this is what's actually

getting rendered so we're just rendering

this app variable which is pulled in

from you know dot slash app right this

app.tsx so index.tsx is really our true

ground zero this is where everything

really comes from this is kind of our

entry point right this is our main

function you kind of think of it that

way that pulls from this app file that

we have here you can see in here we

don't have any reference to this header

right we have our dat provider we have

our div tag saying hi but we don't have

the header in here so what we need to do

is we need to import this component we

just made into our app.tsx so we're

going to do is we're going to import

header

from

dot slash

components

slash

header

and now we can take this header bit we

can place it

inside our header tags here we can just

do header

and we'll close the tag

by adding it right here we'll save

and we'll head back and now we can see a

little connect button here which is

great obviously it doesn't look great

but we have the functionality here which

is what we want if we hit the connect

button our meta mask will actually pop

up and say hey would you like to connect

which account would you like to connect

i'm going to go ahead

select my first one

next connect it's connecting

and now i'm actually going to be

connected let's go to

one of the supported networks like coven

and now we can see here we have this on

click equals disconnect if i click this

now oops i need to actually sorry i need

to put this

inside the tag here so we just moved on

click to be inside of this little button

here now we can see it actually says

disconnect and if i click it i get

disconnected and if i connect i get

automatically connected right so if we

look at our metamask we can see we're

connected right here right that little

little green thing we can also manually

disconnect by going right into our

metamasks click this connected thing

here

click the account and hit disconnect the

account and you'll see our front end

does indeed update awesome this is how

we can take our meta masks and actually

inject it into our front ends so we can

actually use the front ends great job

this is absolutely massive where we are

so far now you might be saying to

yourself hey patrick this is cool uh but

it doesn't look very good that's kind of

a gross button in the top right corner

can we can we style this up can we make

this look a lot nicer and the answer is

absolutely yes so there's a lot of

different styling packages out there you

can 100 write your own custom ones we're

going to be using one called material ui

it's a popular react framework for

creating components and just doing a lot

of styling and doing a lot of really

nice work so we're going to be adding

this to our project as well so to add it

we're just going to use this this line

and i'm just going to go ahead and do it

myself and come in here we're going to

cancel this with control c

we do yarn

add at material hyphen ui

core and this will give us access to

some really nice libraries

for styling all these buttons installing

a lot of the things that we're going to

be working with back in our header we

can add this styling here so we're gonna

do import

button

make styles

from

app material

hyphen ui

core

and we're gonna use their button and

their make styles if we look in the

documentation here you can find there

but this is double narration kind of

like what their default buttons look

like and this looks pretty good looks a

lot better than what we currently have

we're also going to be taking advantage

of their make styles bit here so make

styles is a way to actually do styles

for based off of different themes that

you can actually use with materials ui

we're not going to be working with css

files because we're going to be working

with this make styles instead if you

prefer css you can absolutely easily

translate these to css files so we are

going to add some used styles first of

all using make styles so in here we're

going to do

const

use styles

equals make styles and this is where we

put a theme in here we're just going to

set it to be a default theme um there's

some documentation if you want to go

ahead and add your old themes though so

this make styles function it's going to

have a container and in this container

we're going to add some

padding of theme.spacing

for we're going to add display

flex

we're going to add justify content

flex end

and then we're going to add gap

theme.spacing 1.

so this is really just some typical css

stuff now we're going to take this use

styles constant that we just made

and down here we're going to do const

classes

equals

use styles so now we have this classes

object that we can start working with

we're going to take this classes object

in our little is connected thing we're

going to do div

class name

equals a little javascript in here

classes.container

we're going to wrap this whole thing in

this div right and this is going to

style

this whole button div here so now if we

go ahead and do yarn start again because

we shut it off

if we come back here we're going to see

it's going to look a little bit

different now it's been moved over here

we have this like fun little disconnect

connect button

where there's some padding and it looks

a little bit nicer and we're going to

change all of our buttons to being kind

of this built-in button

from the materials ui

so we're going to swap out all those

buttons with this with our new button

here if we go back we can see it's

it looks even nicer now now that we've

swapped it out with that with that new

type of button right it's got a nice

little clicky feel to it and then we can

also do another line called variant

equals contained

for each of our buttons

so right next to the color primary we'll

do

variant contained and then now we go

back and we have

a really nice button now

so awesome now we have like a really

nice button let's create a component

that will contain the meat of our

application now though from materials ui

we're going to use what's called

containers right and these are nice

little containers that are going to

allow us to style and make these

different sections well we can use we

can import

this container bit from this materials

ui

by doing import

container

from at material

hyphen ui

core

in our app.tsx

and what we'll do to our header we'll

make a little container here

container

give it a closing tag container

and then maybe in here we'll put this

little div high right so we'll remove

that div we'll paste it in here and now

we can see that it's been formatted a

little bit right it's been pushed over

from the side it still says hi we're

going to want to do one more thing we're

going to give it a max width of being md

oops

max width equals md

and this max width now if we look in the

docs again on materials ui these are the

different sizes we have large medium

small extra large extra small and then

false right these are the different

options we can have for max with we're

just going to do medium so if we save

this now go to wrap we can see it's been

pushed over a little bit more it's time

to add our main pieces right we're going

to need that top piece for staking and

the bottom piece for unstaking so we're

actually going to create a new component

called main and this is going to be our

main component so we're going to create

a new file in components called

main.tsx so let's start by just showing

some information about our wallet right

showing what we have in our wallet

associated with what we have in their

smart contracts so we'll say export

a constant variable called main and this

will be a function here's that syntax

for

functions in typescript and javascript

in order for us to show what amounts

that we have in our current wallet we're

going to need to know what chain that

we're even on because the network that

we're on is going to determine where the

addresses are right because it's going

to be different if you're on coven or

mainnet etc now this is where it gets a

little bit interesting because obviously

with brownie we know where these

addresses are right and brownie keeps

track of this for us right it does it in

our builds folder in our deployments

folder if we look there now if you

actually deployed something to coven

you'll see this 42 you'll see some stuff

in here you'll see this map.json which

has the most recent deployments

of our tokens our tokens and our token

farm if you actually deployed it to

coven if you haven't deployed it to

coven i highly recommend you doing that

now as well this way we can test our

front ends against a real test net so in

order to get these addresses we're going

to have to ask brownie hey brownie what

are these addresses where are these

coming from so we're going to need to

grab some information from this brownie

config we're basically going to need to

get all the information all the

information that's in this brownie

config right because this has

has these addresses already and this is

what we want however it's really hard

for node.js to work outside of this

source folder so what we're going to

want to do is we're going to want to

send that brownie config to our front

end the way we're going to do that is

we're going to actually modify

by adding a new function

called

def

update

front end now the only reason that this

works is because we have both our

contracts and our frontend in the same

repository in the real world once you

deploy your contracts those addresses

are pretty much set so you can just copy

paste them over to your front end

repository but for us we don't have set

contracts yet so we need a way to update

our front end so what we're going to do

is we're going to send that brownie

config

over to the front end right that way our

main

can know where those addresses are

we're also going to need to send

so we need to send the brownie config

to our

source

folder we're also going to send

the build folder

why because this will have access to the

dap token address or any other mock

addresses that we're using we're going

to open up our brownie config and we're

going to paste and we're going to dump

the config into that source folder now

typescript doesn't work with the ammo so

well it works with json really well so

we're actually going to convert it from

yaml to json and dump it to the front

end so we're going to open up our

brownie config we're going to say with

open

brownie

config

yaml

we're going to open it in

read format

we're going to say as

brownie config

we're going to say config

dictionary

equals

yaml dot load

brownie config

loader equals yaml dot

full loader

so we're gonna have to import this yaml

from the top we're gonna do

import yaml

and what this yaml is gonna do

is it's going to allow us to

load our yaml into a dictionary that's

really it so you probably don't have it

right now you're going to want to run

pip install

pi yaml

to actually get it now we'll be able to

have that now that we've got this in a

dictionary we're going to want to send

this to the front right we're going to

want to write this dictionary as a json

object to our front end so we're going

to say with

open we're going to open that front end

source folder

and that's just where we're going to

dump this file we're going to call it

brownie

config

dot json

we're going to open this new file

in write mode we'll say it's as

brownie

config json

what we're going to do is just do what's

called a json dump we're just going to

take this dictionary and dump it as json

into this file so we're going to say

json.dump

config dick

brownie

config

json

of course we're gonna have to import

json and then at the end we'll even

print

front and updated so now we have this

update front end script what we can do

when we run our deploy token in-depth

token we can just add this update front

end bit now we don't want to always

update the front end right we only want

to do when we're working with the front

end so in our deploy token farm in depth

token we're going to set update front

end

equals false so by default this is false

this way when we run our tests

the front end won't get updated right

and down here we'll just say

if update front end

and we'll update the front end otherwise

we won't

and in our main function here we'll just

say update

frontend equals true now if we deploy

this to coven or rink b we'll

automatically update and send this

browning config and then let's actually

change this to front and update instead

of update front end so that we don't

have the same method name as our boolean

here so we'll do front

and

update instead so now

when that we deploy

we'll actually go ahead and update our

front end here but we're not always

going to redeploy so let's also

create an up

date front end dot pi script

and this we'll just call that function

that we just made so we'll do def main

update

front end and then we'll do from

scripts

dot deploy

import update

front end semicolon there great

let's open up a new shell

by hitting a little plus button here now

we have two shells and we can just do

brownie

run scripts

update front end doesn't matter the

network

and what this is just going to do

it's just going to run that copy script

right it's going to run our

our update front-end script which we

made right here so if we did this right

we should now have a brownie config.json

in our end

source directory so if we go in here we

go into our source directory we can

indeed see it's right in here do we need

anything else well so that's going to

give us those addresses right it's going

to give us it's going to give us some of

the addresses but it's not going to give

us everything what about dap token right

the app token isn't going to be

something in our brownie config last

token and fau token sure they'll be in

our config but dap token is going to be

something that only is going to be

deployed by us so we need to send that

to the front end too we need to send

basically our whole build folder so

we're going to need to update this

update frontend script to also send

send the build folder i know that we're

actually going to be copying a number of

different folders so i'm just going to

go ahead and make a new function called

copy folders

to front

end

and in here so we're going to make this

copy folders to front end function here

we're going to do a couple of clever

python things this is going to take a

source and a destination so we want a

source folder and then a destination

folder so we're going to copy this build

folder and move it to you know some

folder in the front end first we're

going to check that that destination

exists and if it exists we're gonna kill

it we're gonna we're just gonna remove

it so we're gonna say if os.path dot

exists destination we're gonna do this

shuttle dot rm tree

dest

and this is gonna kill everything so we

need to import both of those we're going

to import os

we're going to import

shuttle or shutil i actually have no

idea how to pronounce that but we're

going to remove that whole bit and we're

just going to copy everything over from

our build folder so we're going to do

shuttle dot copy tree src

dest so we're going to say hey if that

build folder exists in the front end

just delete it and we're just going to

copy everything over from the build

folder and we're going to do this copy

folders to frontend a few times

the first thing of course like i said is

going to be with this build folder so

we're going to do this copy folders to

frontend the source

is going to be dot slash build so we're

going to take this whole build thing and

we're going to move it to

dot slash

front end

src and we're gonna create a new folder

in here called chain

info right and this is just gonna have

all of the build information

and all right

cool so now we can run that

brownie run scripts update frontend

we'll go ahead and run that

and great front end is now updated so if

we look at our front end we're looking

source

we now have this chain info folder which

is literally just the build folder which

is awesome now we can actually start

working with these pieces in our front

end so let's figure out how to get the

depth token address

well to get this dap token address we're

going to need

that map that we just got from chain

info in our deployments but we're also

going to need to know what chain that

we're currently on like what we saw

before we have this chain id

from used app core which will tell us

what chain id of the current network

that we're on

so we can go ahead and import that in

here as well so we're going to do is

we're going to import

use ethers again

from

at use dap

core what we're going to do here

is use ethers

allows us to get the chain id that we're

working on so we can say cons

chain id

equals

use ethers now that we have the chain id

we're going to have to map it to the

name of the network right because our

browning config has this network section

but it's mapped by the name of the

network not by the id

so what we're actually going to do

is we're going to create a helper config

in our src

so we're just going to create a new file

helper config

dot json and it's literally

just going to be a json object that maps

numbers to their associated chain names

so 42 for example is going to be kovan

four is going to be rank b one three

three seven gonna be dev

or it could also be ganache right one is

gonna be mainnet etc now that we have

this helper config we can do import

helper config

from

dot dot slash

helpworkconfig.json

and before we even get the dab token

address we can do const network

name is going to equal that helper

config

at the chain id now typescript is

actually going to get a little bit mad

at us here so we need to add a little

bit more to this line actually so we

need to say okay only grab from this

helper config if chain id exists right

because there might be a chance that

train chain id is nothing or it's

something really weird so we're going to

say chain id i'm going to use this

tertiary tertiary operator again we're

gonna say if this chain id exists

then go ahead and use the helper config

however if it doesn't exist

just use dev i should spell

chain id right so it doesn't get really

confused to me and whenever we return

one of these components or try to use

one of these components we're always

going to have to return some type of

html or div tag like this we head over

to our app

we add our little main bit here

of course we're going to want to import

this say import

main

from

dot slash components

slash main we save it we'll add our

main tag

syntax we're basically saying in it now

depending on your setup you might

actually run into this error here saying

element implicitly has an any type

because expression blah blah blah you

might be saying okay well what's going

on here now to make our lives easier

we're going to tone down typescripts

strictness here so what we're going to

do

is in our typescript config.json we're

actually going to add suppress

implicit

any index errors

so we're basically suppressing when we

get this type of error because it's not

ever actually going to affect anything i

should probably i should probably spell

this correctly we'll save it

now if we save this file here

we're going to actually get this saying

everything's compiled everything looks

good

and if we refresh our front end we're

gonna get back to exactly where we are

before

now what we can also do is we can also

console.log these out we can also see in

the console

exactly what these are gonna look like

so if we do console.log chain id and

console.log network name

we save and we go back we can go hit

inspect

go to the console

and we'll see 42 and coven gets printed

out in the console over here so that's

42 is the chain id and coven is the

is the network name so we know that

we're doing this right okay great

so we have

our network name and we have a chain id

we've got a way for us to update our

front end with a new script let's

finally get those different addresses

that we need say the constant variable

gap token address

is going to equal

something from that build folder or that

chain info folder that we created inside

here inside deployments we have this

map.json

and since i've already deployed this to

coven

we have dap token and token farm on the

cova network so we can then use that and

say

if

if we are connected to a chain id and

that's again that's what this question

mark is doing

saying if this chain id exists

then

look into that mapping else we're just

going to use a zero address right so how

do we actually get this mapping in here

though so i'm going to say import

network

mapping

from

this is going to be in that chain info

folder

inside the deployments

deployments

and it's just going to be map.json

so we're going to take this network

mapping object

and we're going to say if the chain id

exists

then inside this network mapping json

object we're going to

cast

that chain id

as a string

and then we're going to grab

the name of the dab token which is going

to be dap token and we're going to grab

whatever address is at the top right so

this is going to be a big list the more

times we deploy

the more times brown is going to keep

track of it and there's going to be all

these different addresses and we just

want this one right at the top right we

want the most recent one here so we're

just going to say at position zero

otherwise if we're not on a chain id

we're just going to use a zero address

and ether's js actually has a really

nice package to give us what's called

constants so we're going to do

constants

dot

address zero

and we can import that from ethers

so we'll do import

cons

dance

from

ethers

if you don't already have ethers

installed here

we're going to do

cd front end we're going to do yarn add

ethers

and now we have the ethers package in

here now we're not going to do the same

thing for the weft token or the fau

token

because those tokens are defined in the

brownie config as opposed to being

defined in our map.json here so to get

those ones we're going to say const

with token address

it's going to equal let's check first if

the chain id exists and if it does

we're going to grab it from

the brownie config so to grab that

we're going to do

import

brownie config

from

again now that we've imported it

brownie config.json

now we can work with this brownie config

inside of our front end so we'll say

browning config

of networks

of that network name of the

left token and if chain id oops chain id

does not exist then once again

we're gonna do constants dot address

zero so we're just gonna leave it blank

and then we're going to do the exact

same thing for the fau slash the die

token so we'll do const fau

token address

equals chain id question mark

so if the chain id does exist it'll be

the brownie

config

networks

network name

fau token

and if chain id doesn't exist it'll be

constants

dot

address

zero

okay awesome

and if we save it

oops looks like i put in an extra

comment there by accident i'm just gonna

get rid of that and resave

and then refresh here so i'm getting an

issue

uh because i'm on the rink beat chain

right now and it's saying hey there's no

there's nothing for rink there's no dap

token for rink b you gotta be on coven

so if i go back to coven here

and i refresh now it works out fine

right this might still break for you if

you're on coven and you haven't deployed

anything to coven we can fix this in our

config for the dap provider by changing

the supported chains for this now

typically a lot of the times you're

going to want to test using a ganache

chain or some type of local chain so

that your front end testing can be a lot

faster for this we're just going to do

everything on coven but a nice little

challenge for you would be to refactor

this so that it also works with

something like ganache and we're going

to not use ganache so i'm just going to

go back to app.tsx

we're going to remove ganache

even we're going to even remove rink b

for now we're just going to work with

coven just to make it simple if i go to

our react page now

refresh i can connect

awesome

if i go to

ring b it's not going to freak out

because it says hey ring b is not even

supported so i don't care what you're

doing

however covent is supported

so we're connected and we're looking

good and the thing is we really don't

want to couple our front end with our

contracts right we really want to code

the contracts independently and the

front end independently anyways so let's

get back into our

main.tsx because we're going to be in

here for a while but we've already done

some great things we've gotten what

network we're on what chain id we're on

and we've gotten the different addresses

for these different tokens so as you can

probably see

the place that we're actually going to

put stuff on the front end is in this

little return statement here right right

now we're just returning i'm main and we

just see my main right here to do this

we're actually going to make another

component we're going to make a

component called your wallet this

component is going to be a part of this

main component here it's a component

inside of a component that is literally

only going to address our wallet needs

so in our little components tab here

we're going to go ahead and create a new

folder

and we're going to call it your

wallet and this is just going to have

everything to do with our wallet in here

so let's get in here we'll create a new

file because we're going to actually

make a couple files and our first one is

going to be your wallet.tsx

this is going to be our component that

is just going to deal with getting our

wallet getting the token balances of the

different tokens that we have since we

know we're going to put this component

in main and main is in our

our home base our app.tsx you know that

we're going to do an export

const

your wallet

in here and we'll make this a function

now in order to actually show these

tokens we do need to

get some information from our other

component we need to get some

information on what the supported tokens

even are

so we're going to have our main

actually pass a variable

to our wallet here

we're going to call it the supported

tokens

and this is going to be of type

your wallet props

and this is going to be a your wallet

props here just to tell typescript what

this is what this supported tokens is

going to look like we're going to say

interface your wallet props it's going

to look like this

supported tokens

and it's going to be an array

of tokens and array of some token

we're going to grab that token type

from main as well so actually we're

going to do import

token

from

main

and in our main we're going to pass this

token and we're going to pass some

supported tokens to our wallet

so right underneath those three token

addresses

back in main we're going to do const

supported tokens

is going to be an array

of token this token type

so above here

we do export

type token

equals

and we're going to say a token type is

going to involve an image which is going

to be a string

an address which is also going to be a

string

and a name which will also be a string

so we're creating a new type called

token here in our main function

we're creating this supported tokens

object which is an array of tokens and

this is excuse me and this is going to

equal

that array syntax

so our first token

is going to be

have an image

that we haven't defined yet

the address

is going to be

this dap token address

and the

name the name of course is going to be

gap for dap token

now we're going to need a couple images

so at this point you should see where

we're going with this we create this

array of supported tokens

first is our dap token and we need an

image for this dap token so if you're

following along you can just grab this

image right off of the github

and we're going to grab that dab token

and we're going to pop it into src

we're going to change this to

dap.png

now we can import this by doing import

dap from dot dot slash dap dot png

now i can take this dap image

and under image i'll put

now let's do the other tokens so we'll

do a comma we'll do image

we'll be f

oops

f

address will be

weath token

with token address name will be

wef

and again we can either oh and let's

close this off

and again we can either grab right from

my github or pop it into my src here

we'll change this to f dot png we'll

scroll up and we'll import this as well

import f from dot dot slash at that png

and boom that looks good

one more comma image

it's going to be

fau

or

it's going to be our die token

address is going to be fau

token address

name

it's going to be fau

or die

this will be our die token

we'll pop it into our src

change the name to

die dot png no import

die from dot dot slash die dot png

grab die and it looks like we're going

to name it die actually instead and if

your vs code starts yelling at you about

this can't find module it's really

confused what we're going to do at the

top here so we're just going to add a

little comment backslash star eslint

disable

spaced

comment

star backslash

dash dash dash

ref

errant

types

equals react

scripts

and we'll save and that issue will go

away

all right well now that we have

our supported tokens token array we can

actually pass this to

that your wallet bit

right so now we're going to

go to this return bit we're going to

remove that div on main and we're going

to actually start getting to some meat

here so we're going to pass this to our

your wallet component that we're going

to import in just a second

and we're going to send it our

supported tokens let's say supported

tokens equals

supported tokens

backslash like this

and of course we're gonna have to import

your wallet here

so we'll scroll to the top we'll do

import

your wallet

from

dot slash

your

wallet

we're actually going to make a new file

in our your wallet folder called

index.ts

and we're just going to export

your wallet

from dot slash your

wallet

save that

i'm getting an issue

[Music]

saying you wallet it's not defined

it's because this should be your wallet

okay cool so we're getting another issue

but i'm going to fix that in a second

great so now we have some supported

tokens

we have a wallet here

we're exporting our wallet with our

index.ts and our your wallet

folder now let's finish our your wallet

implementation

and this needs a little equal sign here

whoops

and we're going to get this little error

basically because we don't have a return

here

so we could just do return

just to make it happy div

hi

and we'll even change this to i'm your

wallet and we'll save and now

everything's happy we'll go to our front

end we'll do a quick refresh and now we

see i'm your wallet so let's keep diving

into your wallet here right because this

is going to be

where we're doing all of this stuff

about what's in your wallet now we're

going to use a couple of these

components from the materials ui here to

get started

to start we're just going to use this

box the box component it serves just as

a wrapper component for most of the css

utility needs it's

just a box right it's a box that we can

put on our front end so we're going to

come over in into our your wallet and

we'll start working with this box we're

going to put everything

inside

of this little

this little box here

i'm going to import this box

import

box

from

[Music]

at material

ui core

we'll give this a little header

h1 we'll say

your wallet

h1

get a little header your wallet on your

wallet great

now we'll get rid of this little i'm

your wallet and we'll create another box

and in here we're going to add

all of our functionality for

what is in our wallet now we're going to

use some tabs here

from the materials ui

to swap between the tokens right we're

going to have one tab for

fau token another tab for zap token and

for wrapped ether we're going to use

this this this tabs thing here so to

work with tabs we're going to need to

import some

tab stuff so we're going to import

tab context tab list

and tab panel

from

material ui

lab

so material ui

material i slash lab these are some

components that they're not quite ready

to move to the core so we do have to add

these as well so we'll go to our front

end and our other shell and we'll do

yarn add

and material ui

lab these are kind of their testy ones

but they have some really nice features

that we're going to use but let's get

into this box and let's make

our first tab context

value

equal to

now in our box here the first tab

that we're going to have to use is going

to be whatever token that we have

selected

to select tokens we're going to use

what's called a state hook

so we're going to create a state hook

here inside of this

we're going to do

const

selected token index

set selected token index

equals

use

state

number

zero

so use state we're going to grab from

react it looks like i've already

imported here

import react

comma

brackets use state

from react

and what this is going to do it's going

to create one variable select the token

index this is going to be whatever token

that we're on and then set selected

token index is going to update this

selected token index this u state state

components thing is a way of saving

state

between renders of components so in our

little box here

we're going to start with a tab context

we'll start basically with our own tab

and the value is going to be equal to

whatever

token we currently have selected dot to

string

and we're gonna have to make a list of

these tokens in our tab context

we're gonna have to add some way to

change

between the tabs right when we change

between the tabs we want a different

token to be selected and we're going to

make a

tab list that's going to change whenever

we

click the different tab so

we're going to add we're going to add

some functionality to this but for now

we're just going to give it an aria

label

call this our

stake form tabs and based off the

supported

tokens

in a mapping

of token to index

we're going to call a function in here

where we return

a tab

which will have a label equal to the

token.name the value would be equal to

the index

dot string or excuse me dot 2 string

and the key

is going to be equal to

the index

tab is something that is just from the

material ui core so we're going to

import

tab

from

that material

ui core

i should probably spell supported tokens

correctly

supported tokens now

if we look at our ui we can now see

we've got a couple different buttons

here which great we have dap west and

die right these are the different

supported tokens that we're mapping here

now of course if we click the different

buttons

nothing actually happens so we do need

to to handle a change we do need to code

some functionality to handle a change

whenever we do something different so in

our tab list we're going to add on

change

on

change

equals

handle

change

i'm going to code a little functionality

at the top to actually handle a change

so we'll say const

handle change

equal to

an event

a react dot

change event

we'll do a new value

it's gonna be a string

and this is a function

so we're gonna do this little function

syntax again

and all we're going to do is we're going

to use our little state hook here so

we're going to do set

selected

token index

and we're going to parse

the int

of the new value that we get

so what's happening here we've added

this new functionality where whenever we

change

one of those tabs we're going to change

this the selected token right this

selected token number is going to be

different and what we do is we map the

indexes to a token right so each one of

these tokens is going to represent a

certain number so now when we save let

me go check out our front end you can

now see that we do indeed swap between

tabs here which is really nice all right

let's keep going so that's cool we have

a way to swap between the different

tokens visually here but we need a big

stake button right the reason that we

need to swap between the tokens is

because we need a way to stake

between them

so when we're on one of these tabs we're

going to add a stake form here we're

going to add a big button that allows us

to stake so we're going to do some

typescript we're going to do supported

tokens.map

i'm going to map that token and index

again

function use that and then here we're

going to return

a different tab panel

the value in here is going to be the

index

dot to string

key is gonna be

the index

we'll make a little div in here

and we're gonna need to put two pieces

in here we're gonna need to be putting

our wallet balance in here and then also

a big

stake button right

of course we're looking at right now

it's just going to say our wallet

balance and a big stake button but how

do we actually do this how do we

actually get our wallet balance and one

of these big stake buttons

well we're probably going to need some

type of component to get our actual

wallet balance that we're going to stick

in here

so yup you already know we're going to

go in here into our your wallet

component we're going to create a new

file and this is where we're going to

define

that wallet balance component and we're

going to import our wallet balance

into our wallet here so that we can

actually see

the balance of our wallet right in the

front end and right and this is where

we're going to actually be reading off

chain finally after a lot of typescript

and react setup since we're going to be

importing this into our your wallet

component here of course we're going to

start with export const

wallet balance

we're going to make this a function so

we'll do this

really weird

function syntax and we're probably going

to want to pass this

the token right the token that we want

to get the balance of

so we're even going to set that up like

this a token in here

and we'll define

what this looks like uh with the

interface called wallet balance props so

we'll say export interface

wallet balance props

and this will be

a token right

this will be that same

token type that we defined before so

we're gonna have to import that so we'll

say import

token

from

[Music]

main

all right great that's our initial setup

here we'll grab

from the token that we passed to this

we'll pass we'll get the image

address

and the name

from that token

address and name

we'll grab the account right because

we're going to need the account with

along with the token

so we'll say const

account

equals use ethers

and of course

we're gonna have to import

account

from

excuse me imports not account use

ethers

from at use dap

slash core

we're gonna need the account we're gonna

need the address and use dab core has a

nice little hook

called

use token balance that we're going to

use you look check it out in the

documentation provides a way to fetch

the balance of erc20 tokens specified by

a token address it makes our lives a lot

easier so we'll just import that as well

use

token balance and all we have to do

really is do const

token balance

equals

use

token balance

of the address of the token

and our count here we can even do a

quick console.log

token balance

see if we're doing it correctly and we

take this wallet balance and import it

into our wallet here

we should be able to see

something so we'll import it into our

wallet now let's go into the top we'll

do

import wallet

balance from

dot slash

wallet balance and down inside our very

large return function here we'll add

this new

tab

or this new uh component we'll say

wallet balance

we still remember we need to send it the

token

so we'll send it

tokens

at the index of the selected

token index

i should spell supported tokens right

i should spell wallet balance right

capital b we do need to do a return

so that it's actually a jsx component

we'll do a div

we'll just have to say i'm the wallet

balance if we go to our front end we do

a quick refresh

we do indeed see this little print line

here uh this is javascript's big number

so if we really want to see this token

balance we'll do dot to string

and we have to put this question mark

here to tell typescript hey

turn it to a string if it's not

undefined and now if we save we go to

our front end

we do a refresh

since we are connected

to coven here we can see

we get an amount printed out here and if

we switch tabs

you'll see

the different amounts being printed here

which is fantastic cool so let's remove

this little console.log we want to show

this token balance obviously in our ui

right we don't want to have people to

have to go to the console.log right to

actually see it we want it to represent

we want to show up where it says i'm the

wallet balance so what we're gonna do

first we should probably format it

right because this is in units of way

so we're gonna do const

formatted

token balance

this will be a number which will equal

to

token balance

if token balance does exist

again we're using this tertiary operator

we're going to parse

float

format

units

balance

18

otherwise we're just going to use zero

format units is a nice little import

that we're going to grab from

the ethers project so we'll do import

format units

from at ether's project

slash

units

and of course

yarn add at ethers project and of course

we're going to do a yarn add on this

here we'll do yarn add

at ether's project units and now this

formatted token balance is going to be

this token balance that we just got but

formatted formatted much nicer in our

little div here what we could just do so

we could just add this formatted token

balance

we'll save and we'll look at the front

end now

and aha

we now see we have 100 dapp zero weft

and 15 die right these numbers might be

a little bit different depending on how

much you actually got but this is

perfect this is exactly what we're

looking for so let's close out the

console and

let's let's flesh this out a little bit

let's make this look a little bit nicer

here so instead of just returning a

little div like this let's actually make

a new component called

balance message

and we'll use this instead

create a new component called balance

message and it'll format up the way we

actually show these formatted tokens and

here we'll pass

we'll pass it

a couple variables we'll pass this

component an amount we'll pass it a

label

we'll say the label is going to be

your unstaked

name

balance

right we're grabbing name from the token

and we'll pass it a token image src

which is going to be that image so we're

going to pass it a label

or excuse me not img it's going to be

image we're going to pass it a label

token image and an amount right and this

component is just going to make us

have this balance look a little bit

nicer so in our our your wallet section

i'm going to do a new file

called balance message.tsx oops not tsx

tsx and we can kind of rip through this

pretty quickly so per usual we're going

to export

const

balance message is gonna equal

a function where it's gonna take those

parameters a label

and a mount

and a token image

src and this will be

an interface of balance message props

this will be a function of course so

we'll do this weird

function syntax of course we need to

tell typescript

what this looks like so we'll say

interface

balance message props

what are those inputs

we'll say the label

is going to be a string

the amount

it's going to be a number

and the token image src

is going to be a string and in here

we're going to use

and in here we're going to once again do

that use styles bit for materials ui

because we want to style this up a

little bit so we're going to import make

styles

from

[Music]

at material

slash ui core

we'll do a const use styles

it's going to equal make styles

theme which we're going to skip doing a

theme but let's make some styles for the

different pieces let's give it balance

message be surrounded mainly by a

container

which will have a couple of styles in

here we'll say the display

it's going to be an inline grid the grid

template columns

are going to be

auto auto auto again you can check out

all these parameters in the

documentation

there's going to be a gap which will be

theme dot spacing

one again we're skipping theme but this

will just be a way to add some spacing

and then align items

in the center we'll also give

token image

its own

styling we give it a width

of 32px

32 pixels and then

the amount

just do

we go to font weight

of 700. so we'll make that a a little

thick

so now that we have our use styles we

have our styling here we can go into our

export below

we'll do const classes

equals

use styles

and we're going to return we're going to

return a div

class name is going to be equal to that

main container

classes.container

we'll do another div just for that label

that we're looking for we'll do another

div

for class name

equals

classes dot amount

so have that that nice font weight and

then here we'll just have the

amount

and then we'll grab that image of the

token

class name is going to equal to

classes dot token image

we'll grab the source of that image is

just going to be that token image src

that we get passed

and we'll give it an alt

called token logo

and we'll close that tab out

great so we're going to want to do is in

our wallet balance here it's balance

message that we just created we'll do

import

balance message

from dot

dot com

mints slash

your wallet

capital w and actually i know we're

going to use this balance message a

little bit later so i'm actually going

to grab it

and drag it into components move it into

components and move it out of your

wallet

because i know that we're actually going

to use it a little bit later so that

means in our wallet balance

we're just going to pull it right from

components

slash

balance message

and whoops we actually need to make this

look like

this

close it out here

remove this part

like this boom right like that

and now let's try out the front end okay

we're looking a little bit nicer

right we have a really thick number here

explaining how much of the token we have

we have the images popping up this looks

starting to look great let's add this

stake button right so that when they see

this they can actually stake and

interact with our contract here so to do

this we do need to create another

component called our stake form so in

your wallet we're going to create a new

file

called stake form dot ts x and this is

where we're going to add

a little button

and an amount for the users to actually

stake on our contract so you already

know we're going to start with export

const

state form

equals

and we're going to have

our wallet pass

the token just like we passed the token

to wallet balance

so we'll say token and we'll have this

be stake form props

which is an interface we're going to

define in a second this is a function so

we'll do this fun function

syntax here

and then stake form props as you know is

just going to be a token so do inter

export

interface

stake form

[Music]

props

this is just going to be a token of type

token which again

we're going to import token

from

maine

great and that is our starting point for

this so we're going to create a stake

form

with a big button that says stake and

the user can actually choose how much

they want to stake on our smart contract

so we're going to do some similar stuff

as we did before we're going to grab

some variables we're going to say the

address is going to be that token

address

that we get from the pass token

we're also going to get a name

of the token

from that token

we're going to get our account

from use ethers again

so we can import that we'll say from or

oops

import

use ethers

from

at use

dap slash core we're going to want to

grab the token balance so we'll do const

token balance

once again we can grab that with the use

token balance with the token address

and the account

so we're going to use use token balance

this will also grab from used app slash

core we're going to want to format this

token balance so we'll do const

format it token

balance it's going to be a number

again this is going to be the exact same

as we did before say token balance

do parse float

format units

token balance

18

or

zero

in format units once again we're going

to import that import

format units from

at ether's project slash units

perfect

importing here we've gotten some some

starter boilerplate let's just go ahead

and grab those buttons right because

those are really the things that we're

going to care about here let's just

return some stuff here so something can

show up on our front end right so let's

do return

i'll start returning something here and

whenever we return something it's all

gonna be in one

tag right so i'm gonna i know i'm gonna

be doing a whole bunch of different tags

so i'm just gonna go ahead and make an

open and close tag here

and this is where i'm going to put all

my stuff now we know we're going to want

to have a big stake button right so

let's go ahead and just do

let's get a let's get a button tag in

here and of course since we're going to

have a button

we're going to pull this in

from that materials eye material ui

right so we'll do import

button

from

material

ui core just so we can get get started

with something here and then back in our

your wallet.tsx let's add this button in

here inside of our tab panel

right below our wallet balance we'll add

this

stake form thing we'll open and close of

course we've got to import it

so we'll say import

stake form from

dot slash

stake form and

we need to pass this that token object

so back in our your wallet we're gonna

say okay token

equals

supported tokens

of that

selected token

index

selected

token

index and let's not have this

let's just do a little backslash here to

close that out let's be sure to close

this bracket here we'll give this button

some stuff right we'll do color equals

primary say size equals large then we'll

give it some text called

stake

double exclamation point or however many

you want to put in there and now if we

look at the front we got this big stake

button

nice okay we're looking a little bit

better currently doesn't do anything but

we have a stake button great

now we can start adding some

implementation right we can have it do

some stuff now

when we hit this stake button what do we

want it to do we want to do two things

we want to approve

whatever token that we have and then we

want it to stake that amount we also

need to have some type of form here we

need to know how much we want to stake

right so we're going to need some little

input box that we can add a certain

amount in well we can do that too with a

little input box from materials ui so

there's another package we're going to

grab which is called input

from materials ui core

and then we're going to use this little

input box before

the button so we're gonna do input

little slash here now if we save

refresh the front end

awesome now we can do some typing in

here we can click this stake button now

to do this though we're gonna need to

keep track of how much amount is in here

right we're going to need to keep track

of how much amount's in here

so we're going to inspect on the front

end and we're going to go to console and

see if we can follow along

with how much is in here or what amount

is in here and to do this we're going to

make another one of those state hooks

and we're going to track that amount in

there

so we're going to say const

amount

set amount

for one of these stakeholders equals use

state which is going to be a number

or a string or an array number or string

zero

and we're going to import this use state

here

from react so we're going to do import

import

react

use state

from react

and now we have this state hook that we

can use to keep track of the amount

that's going to be put in there with our

input tag here we're going to say on

change

whenever this changes we're going to

have to

have some handle function right we're

going to call it

handle

input change and this is going to handle

the input change so we're going to

create that function we're going to do

const

handle input change equals and we're

going to use some event stuff in here

we're going to say this is going to take

an event

a react

dot change

event

of html input element

this is going to be a function

that's going to

set amount

it's going to say

const

new amount

equals

event.target.value

whenever we change that value in that

field if if it's equal to nothing

then we're just going to say okay we're

going to do nothing

otherwise

we're going to cast it as a number

event.target.value

we're going to cast whatever is in there

as a number

and then

we're going to do set amount

to this new amount what we could do is

we can even do a console.log

new amount

and now and we can start using it right

so if i go back here and do one two

three right you can see it's

console.logging every time i change

something in here so now we have a way

to actually get that amount with this

input now we're going to need to weigh

to send that amount as part of our stake

right so we're going to first have to

call that approve function with this

amount and then we're going to have to

call

from our token farm then we're going to

have to call the stake method so how do

we get

it to call this approve function here

well to do these we're actually going to

make some new state hooks that we're

going to use in our staking form here

we're going to make state hooks for

approving and for staking and even for

unstaking so

back in our folder here we're going to

create a new folder

called hooks

and this is where we're going to add

some different hooks

first hook that we're going to make is

going to be called use

use stake

tokens dot type script and this is

something that we're going to import

into our our stake form here so we can

actually stake some tokens and the way

we want to do it too

is that once we hit stake once we hit

our stake button

it kicks off the approve and then and

actually right afterwards it kicks off

ascend it kicks off a stake token we

want to run these two

functions sequentially and we're going

to make this use stake token hook clever

enough to do it in that order so let's

do it hooks are basically just like

components except for they're more

functionality wise so since we know

we're just like components we're going

to do export const

use stake tokens and this is going to be

a function

just like our other components and as

input we're going to take a token

address

that's going to be a string and inside

of this we're going to have some

intelligent scripts to know if it's

already been approved if it's not

already been approved and what we need

to do right we know we're going to need

some approved thing and we know we're

going to need some stake tokens thing so

let's let's at least try to approach

this approved thing first before we get

too creative right how do we approve

this transaction to get an approve we're

going to need a couple things we're

going to need the address

as you guys know

we're probably going to need the abi

we're probably going to need

the chain id so we know which chain it's

on

so let's go ahead and let's grab those

so we'll do const chain id

equals use ethers

and since we're using use ethers here

we're going to import this so we'll do

import

use ethers

from at use dep

slash core

we're also going to want the abi of the

token farm so we'll do const

abi

equals well where do we get this api

from ha that's right we've imported it

in our little chain info piece and

should be right in here we could should

be able to do

import

token farm

from down to directory it'll be in

chain info slash contracts

slash

tokenfarm.json and now we can say

avi is going to be equal to this this

token farm right because in token farm

we have an abi key so we can just

abstract that away and just pull out the

api perfect we're going to need the

token address of course we're also going

to need our token farm address and we

can find that the exact same way we

found it before

with const token farm

address

it's going to be equal to

depending on if the chain id exists

once again we're going to want to use

that network mapping so we can even go

back to main.tsx

let's see how we did it here for the

depth token address

you can copy this as like a frame of

reference

we'll say if this chain id exists we'll

pull

right from that network mapping

right we'll pull right from the network

mapping so we got to import that too

which we can grab from

import

network mapping

from

chain

info chain info slash

deployments

slash

map.json so once again we're going to

say if that chain id exists

in the network mapping

we're going to use

that string chain id

so we'll do string

chain id

of

the token farm

at position 0 right because we obviously

want the most recent one otherwise again

we'll do constants dot

address

zero

and since we're going to do that of

course we're gonna have to do import

constants

from

[Music]

ethers

and this hooks folder should be in

source so let's just make sure that

we have hooks in source here now we're

going to want to interact with this

token farm address contract right we're

going to want to run that proof function

first we want to create like an

interface so we can do const

token farm interface we'll say this

equals new

utils.interface with the abi

this utils we can again grab from the

ethers project or excuse me from uh from

ethers so we'll do comma utils

now we can create a token form interface

here and now that we have interface

we'll create a contract so we'll do

const token farm contract

equals new

contract

and this will be a combination of this

token farm interface and the token farm

address actually it's address first and

contract is something we can grab from

import

contract from at ether's project

slash

contracts

all right

you're probably starting to follow along

and figure out okay cool i have a token

farm contract

now that we have a contract we can

actually call some functions which we

totally can but right we need to call

the approve first so let's get

the token contract before we even work

with the stake token right so to work

with the token we're going to want to do

the same thing so we'll do const

erc20

interface

equals new utils dot interface

interface

and this will be from ear c20

abi which we should probably make first

so we'll do const erc20 avi

equals

we'll do it the same way we did up here

except for instead of token farm we'll

do something else we'll do

look in our contracts here

we'll do mock erc20 instead

and then we'll just call this erc20

or yeah we'll just call this erc20

but we'll grab it from our mock erc20

dot json

so now that we have the crc20 we do

const erc20 api equals

erc20.avi

and we can just pop this api

to create our interface we'll now do

const erc20

contract

equals new contract of

the token address

comma the erc20 interface

boom okay

now we have both of these contracts we

have the erc20 contract we have the

token farm contract now we should be

able to go ahead and call some functions

right now to actually send one of these

we're going to use this thing called use

contract function it's a hook in use dap

that returns an object with two

variables a state and a send this state

bit is used to represent the status of

the transaction and that's how we're

actually going to automatically kick off

the stake after we approve to send a

transaction we have to actually have to

we actually have to use this send

function here

so we're going to use this use contract

function to get to get a state and

ascend so that's what we're going to

first need to do so we're going to const

send

and then we're going to call this

approve erc

20 send

and state because this is what it's

returning it's returning send an estate

i'm going to say state is going to be

approved

erc20 state

equals

use contract function

we pass the token contract the erc20

contract

comma the name of the function which is

going to be approve

then we do a comma and then we'll do a

little object here we'll call this

transaction name

and this will just be approve

erc20

transfer

then of course i have to import this

from used app this use contract function

now oddly enough

oops i got rid of the

closing tag here but great so now in a

weird way we actually have these two

new pieces here we have this send

function this approve vrc20 send

and this approve erc20 state this is

going to be

the status of our transaction and this

is going to be the actual function that

we use and if we want to call this

approve function what we can do

is now we can return calling this proof

function so we'll do const approve

we'll have this be

a function we'll say it'll take a string

amount as an input parameter

and we'll just have it return

this approve erc20 send and we'll give

it the token

farm

contract address

as a first input parameter excuse me

token farm address and we'll use this

input amount as the second parameter and

then we'll just have this

this use stake tokens return this

approve function

and then also

this state here so it's going to return

approve

and it's going to return state we could

also just have it return this if we

wanted

but we're going to wrap it just all up

in this approved thing here we also

probably want to return this state right

so we're going to turn this into

hook as well

so we're gonna do const

state

set state

equals

oops

use state and we'll have this be the

approved

or the approved erc 20

state

as the input and of course since we're

using use state we're going to grab this

from react as well we also want to

return the state so we'll return this

approve erc20 state here so now we have

a way

to actually do all this

so in our stake form

what we're going to have

is we're going to create const that's

going to grab those two variables so

we'll do const approve

and approve erc20 state is going to be

equal to use

stake tokens

with that token

address

pulled down from the token as the input

parameter

and this is our new hook so we're going

to import

use stake tokens

from

dot dot slash dot dot slash hooks now

that we have these two functions we have

the approve function and then we have

the state of that function

now we can add a handle submit

functionality for our button here

so now we can say okay on click

when we click this button

we're gonna do

a handle

stake

submit

right because this is that our big well

it's not gonna show up now because i

broke everything but this is our big

button right this is our this is our

stake button so we're going to create

this function called handle stake submit

let's go ahead and do const

handle stake submit

this will be a function

and what it's going to do

is we'll get this amount here so we'll

do const

amount

which we're going to actually have to

convert it from

string to way so we'll call it amount as

way

we'll do equals utils.parse

ether we'll grab parse ether

we'll grab utils

again from ethers

utils from

ethers

and we'll do the amount dot 2 string

so we're going to grab this amount this

statehook amount here we'll turn it into

a string

and then what we can do is we can return

this approve function

with this amount as way

okay oh and then we're getting a fail to

compile so in our hooks section we're

just gonna do an index.typescript

and we're gonna export this use stake

so we'll do export

use

stake tokens

from dot slash use stake

tokens

close that

we'll restart the server

and then i should import this from the

right place

and i should import this from the right

place as well

and let's get rid of the brackets here

whoops sorry

and let's do this

as a dot to string oops because you

can't do a big number

now let's save it'll recompile we'll pop

into our front end here we'll do a

refresh

our stuff is up that's cool our stuff is

getting

logged out now if we hit stake

we should call the approve function here

metamask pops up we do get allow

localhost to spend your dap this is

amazing we're gonna reject this for now

though because

or don't want to bother testing it so

amazing job getting this far we're

hitting a button

metamask is popping up and

we're doing it we're actually sending a

transaction this is incredibly exciting

great work so far let's keep going uh

the approve function is working

perfectly it's working as intended or

we're just we're kind of assuming it's

working as intended but that's great

this is perfect so now we've got to go

one step further we need to have this

call stake after it's been approved this

is where we're going to do a little

something called use effect we can

import in here

just to use effect

comma what use effect does it allows us

to do something if some variable has

changed

so the way that we're going to do that

is we're going to say okay

use effect

and it takes one of these functions as

an input and then we'll do a little

comma here and similar to those state

hooks we'll do an array

of different things we want to track and

if anything in this array changes we'll

kick off this use effect and we'll do

something in here

so one of these things that we

definitely want to

track is this approved erc20 state

if approved erc20 state if this

transaction comes back successful

then we want to do some stuff

so we'll say we'll track this

this state and we'll go ahead and say if

approve erc20 state dot status

equals

success

then

we're going to go ahead and do like a

stake function

and to do a state function we're going

to follow this exact same methodology

that we did for the approve

so first

we're going to use this use contract

function thing

so we'll do const

send is going to be

stake

send

and then state

will be

stake state

this is going to be equal to

again we're going to use use contract

function

this is going to be on our

token farm

contract this is going to be our stake

tokens

function

and this will be trans action name it's

just going to be stake tokens

and that's it

so let's make this look a little bit

more readable here lovely

so we have our little used contract bit

here and now this stake send we can just

call this right in this approve erc20

dot state does status we need to do

stake send

and if we look back in our token farm if

we do stake

tokens we have an amount and a token

address so that's what we're going to

have to put in here

we have to put some amount

and then token address will just be

token address

where do we actually get this amount

from

well when we originally called

this approved function this is when we

should actually do it and you might be

asking hey

how come we wrapped this approve your

c20 into a function here but we're not

going to do that here i'll tell you why

in just a second so what we're going to

have is we're going to have a state hook

for how much we want to actually

stake so we'll do const

amount to stake

and set amount to stake

it's going to be equal to use state

and we're going to start with zero we're

just going to get this defaulted right

to zero

and what we're going to do actually

is once we call this approve function

the first time

we're going to set amount to stake

to be

this amount and what we should do

instead of calling this approve is we

should call this approve

and stake

since it's this function that's going to

kick off yes it's going to kick off our

approve erc20

but it's also going to change

the amount that we're going to stake

and later on

once the transaction succeeds it will

also then kick off our steak send

or our staking function so we're going

to change this to a proven stake that

means below we have to actually return a

proven stake and not just approve

and for stake send the amount is going

to be this

amount to stake which we got from our

original proven stake and then we just

have to change this to approve

and stake

and we'll change this from improve to

approve and stake and realistically

that's all we really need to do here so

if we save we go back to our front end

let's go to one of these that i actually

have some of i'll type in one

for in here i'll hit the stake button

and what should happen is approve will

come up i'll confirm

and once this actually confirms then

i'll be able to another transaction

should pop up

telling us

to actually stake and that's exactly

what happens here so we've approved now

we can stake we'll even watch metamask

really really quick here i'm doing this

on coven

right i just called this state tokens

function

for those of you doing this on ganache

will be a lot quicker but perfect that

was fantastic our balance even got

deducted by one now we have

one

of these tokens actually staked and this

is fantastic however

there's obviously a couple issues here

right

what was happening during that that

whole section right there is there was

no indication for us of what was really

going on got no notifications we're

totally left in the dark here

additionally

this page still looks disgusting so we

want to clean this up we want to make

this look a lot nicer so how can we

actually do this

so for switching between these we want

to actually just change our use effect

here

so we do want to check let's approve

erc20 state but we also want to see if

we switch the token address

we want to just check to see if approve

vrc20 is done if we switch our token

address

and we also want to just check to see

this if amount to stake actually changes

so if we do amount to

stake

we want to check kind of during all

these these three if any of these three

changes we'll just do a quick check hey

is the prove vrc20 done if yes great

then we'll we'll stake some tokens so

this is great but we're going to want to

get some notifications that these

transactions are going through these

transactions are pending

and these transactions finish so why do

we actually add those pieces to this

well used app has this thing called use

notifications this notifications bit

will help us actually get notified on

whether or not our transactions are

completing so to use these notifications

we're going to do a couple of different

things in here first all the way back in

our app.tsx we're actually going to

change our config here

we're going to add some notifications

in here

to check periodically if our things are

done

and there's a couple of different

parameters there's a

x

variation period and then we'll set it

to be 1000 this is in milliseconds so

we'll set it to be a thousand which is

just one second

and we'll do a check interval

also of one thousand so basically we're

saying hey every second check the

blockchain on our transactions that we

send please thank you and now that we

have this notifications bit identified

in our staking form

we can add this bit so from used up

decor we'll do comma use notifications

and now we can actually start using some

of these notifications so right here at

the top

we'll do const

notifications

equals use notifications

we can actually start working

with some of these notifications now

we're going to want to see if anything

in any of these notifications actually

change and if these notifications change

we're going to want to do something so

since we're going to want to check to

see if this if notification changes

those who have been following along with

what i've been explaining for use effect

you know that means we're going to want

to use a use effect we're going to say

use effect

it's going to be this function

and if we don't have it imported let's

go ahead and import this from react

let's use effect

we're going to be looking to see if

these notifications change we're going

to be looking to see if our transaction

has completed so in our little watching

array here

we're going to say let's watch the

notifications here let's make sure

if any of those notifications changes if

anything in our meta mask changes we're

going to want to do something right so

we're going to say

if

there are any notifications that are

approved erc20 or transaction succeeded

we want to show hey you know good job

it's been approved

so to do this we're going to say if

notifications

dot

filter

all right this is going to be a function

based off the notification

on this notification we're going to say

notification.type

it's going to be

transaction dot succeeded

succeed

and

that

notification dot transaction name then

this is why we need to give them names

before

in our use state

it's going to be approve

erc20 transfer

dot length

is greater than zero

then we're going to do some stuff

our transaction succeed

so we're saying if

in these notifications we're going to

filter on a notification

if the type is transaction succeeded and

the name is approved erc20 transfer then

we're going to do some stuff and for now

we're just going to do console.log

approved

we can also then do the same thing for

if

notifications dot filter

author on the notification

notification dot type

if that notification to type is going to

be again that transaction

succeed

and

notification

dot transaction name

equals stake

tokens capital t

stake tokens

there are more than one dot length

is greater than zero

then

we'll do console.log

tokens staked

okay so we've got some notifications put

in

we're gonna do a little console logging

let's see if our use effect stuff is

actually gonna work so let's go to our

front end we'll do a quick refresh

we'll go to where we have some tokens

i'm gonna type one in here i'm gonna hit

stake

i'm gonna hit

confirm and we're gonna wait a little

bit and if this confirms correctly

then we're gonna see a little

console.log printout that says approved

and we do indeed and that's perfect

metamask pops up again for our stake

tokens

we hit approve there as well

and we should see a little console.log

out here for state token staked and we

do perfect so now we have a way to

actually track some of these

notifications and track what actually

happens on the blockchain

console.logging stuff is great but we

want to actually see it in our ui here

what we're going to want to do is show a

little waiting thing here

while we're waiting for it to be

approved and then she'll pop up when it

actually does get approved we can add a

little

constant called is mining

which will be based off of whether or

not the transactions are approved so

we'll do const

is mining

and this will be equal to

the state of these transactions so this

should actually instead be approved

erc20 there should be approve

and stake erc20 state now we'll say oops

now we'll say is mining will be equal

to approve and stake erc20 state dot

status

equals equals equals

mining should probably have it look like

this

then back in our

use stake instead of

approve your c20 i'm going to change

this to approve and stake your c20 state

and then we're also going to return

prove and stake erc20 stake

let's make this make a little bit more

sense here get that little red line to

go away and now what we can do with this

is mining thing is we can add this to

our button now we have this is mining

thing it's gonna be based off of whether

or not approve and stake are done so we

can scroll down to our button

and we can add a little disabled flag so

we'll say disabled

equals

it'll be equal to dependent on whether

or not it's done we'll just add is

mining

and if this is true then disabled will

be true and if this isn't mining then

this will be false

we can also add

this to be kind of like a little loading

thing so instead of just saying stake

all the time

we'll do a tertiary operator we'll say

if it is mining

then we'll do like a little loading

thing material ui has this thing called

circular progress that we can use it's

like a little loading thing

so we can do if it is mining we'll do a

circular progress

we'll say the size is 26 or whatever we

want it to be

we'll close the tag out

and if it's not mining again we'll do

this stake with a bunch of exclamation

marks here so now if we save that go to

our front end

it looks like i need to fix something

can't find name approve your c20 state

that's because we changed it this is now

a proven stake er20 state

so let's change it to that

now let's save go back to the front end

and okay cool

let's go to one of these that we have

some stuff with we have a little dial

we'll do one here

we'll hit stake and if we did this right

this should show a little loading thing

while the transaction is going through

so we're gonna hit approve

and perfect we do see a little loading

thing and it should stay like this

until the transaction finishes

this is a good way to indicate to the

user that we've actually

approved

now i'll hit confirm for staking so we

didn't actually see the loading thing go

back up again so this probably means

that we didn't actually reload this is

mining correctly

and the reason we don't see the little

spinny thing is because this a proven

stake erc20 state is really only

tracking the approve right we have our

cost a proven stake which does all this

good stuff here but our staking part

this stake state we actually never use

right and we need to pass this back to

our our stake form so it can actually

know you know what's going on so what we

can do is we can add a new state hook

we'll do const we'll just call this one

state

and then we'll do set state it's going

to be equal

to

use state

and this will be that

approve in stake ear c20 state

we'll start it off there and this will

represent kind of the overall state

right for this will be the true proven

stake ear c20 state

what we're going to do now is we're

going to have to track those both of

those states we're going to track both

the proving and the staking so we're

going to do use effect and we're going

to track both of those

with our little

our little wonderful

use effect stuff so we're going to track

them with by doing of course

proven stake erc20 state and then

stake state so if either one of these

change now we're going to want to change

this overall state function and that is

going to get pushed back to our our

stake form here so what we're going to

say is we're going to say if proven

stake erc20 state dot status

equals equals equals

success

then

we're going to set state to be the stake

state

otherwise we're going to set this

overall state we're going to do set

state

to be this approve and stake bit

or just or really just kind of approve

here now we're going to pass this just

kind of overall state variable here

to our front end like this

excuse me to our stake form and in our

stake form we're just going to say we're

just going to map this state variable to

the proven stake erc20 state we'll save

here that should work perfectly great

now if we go back to our front end we'll

go to die or whatever we'll do one we'll

hit stake

metamask will pop up we'll confirm we do

indeed get this little loading thing

which is perfect once it's done once

it's approved we'll confirm again and we

get loading again and this is perfect

this is exactly what we want because now

the user has a good idea ah okay i need

to wait right the transaction is going

through the transaction is being built

and once it's done

it's all set so this is fantastic we now

have basically all the functionality for

staking right we have a proof we have it

doing some waiting we have it actually

staking

let's clean this up a little bit right

let's make this look a little bit nicer

so first we're gonna go to index.css

we're gonna we're gonna add some bits in

here for a body we're just going to do

background

color we're going to set this to

set a background color

to

[Music]

hsl we'll do 227 comma 61 percent

26 there's a whole bunch of tools the

background color doesn't really matter

but we'll save we'll refresh our front

end and we'll get a nice little uh

background color here which is cool but

let's actually be even more creative

than just this let's do a nice little

linear gradient in here we'll just get

rid of this actually we'll do background

do lin ear

gradient

we'll do 135

right here do hsl 227

61 percent

comma 13 percent

then we'll do hsl 227 61

26

we'll do one more we'll do hsl again

this will be 227

61

39

for some colors in here semicolon there

let's look at our front and k we're

getting somewhere we got some cool

double gradients going on in here we'll

go to our main section here and we'll do

that use styles bits again so right in

our looks like we don't have any

material ui in here so we'll do a little

import

make styles

from

at material

dash ui dash core

and right at the top

we'll do const use styles

equals make

styles

some theme which we're ignoring

nice little function thing here let's

then for our titles in here we'll do a

little

make the color be theme dot

palette dot common dot white which again

we're ignoring theme but if we did

everything we would do like that we'll

do text align

center do some padding

[Music]

theme.spacing4

and then our main of course we'll just

add this in here const

classes equals use

styles

and then we'll just put like a little

little section in here

do an h2

or class name it's going to be equal

to classes.title

and we'll just call this dap

token

app

we'll go back to the front end we got

like a nice little deck token dap token

app nice white right at the top that

looks good we'll go to our your wallet

component we'll add some styles in here

looks like we don't have any styles in

here so we'll do the same thing we'll

grab

make styles in here

do a little const

use styles equals make styles

a theme that we're going to ignore

some fun little function syntax stuff

here

we'll say tab content

give this some styling we'll say all the

tab content stuff we'll have

display of flex

flex direct

sean will be

column

[Music]

align items in the center

and then we'll do a gap for this which

will be

theme.spacing04

give our boxes some stuff so we'll say

box

we'll say

background color is going to be white

we'll say border

radius it's going to be 25 px

to give it some roundness here

then we'll also do a header

which we'll just do color of white

we're going to grab tab content

scroll down

this is going to be inside this little

tab panel bit here

this div

it's gonna have class name

equals

classes dot

tab content

oops we gotta add classes in here right

before the return

so do const

classes equals that use styles

we'll say this box

well it's not we're not going to do the

overarching box this could actually just

be this if we wanted to we'll just say

it's this first box so this will be

class name

equals

classes dot box

and then our h1 is going to be class

name

equals

classes.header

let's save it and let's take a look

whoa

this is already starting to look a lot

better now as you guys can kind of see

the functionality is really the

important part behind the application

and doing a lot of this use style stuff

is what's really going to make it look a

lot prettier right so if you're like hey

how do i do this pretty stuff now i know

i didn't really explain what any of this

pretty

prettiness was doing

there's a ton of tutorials on doing css

that's basically what this is that you

guys can learn a little bit more to make

your stuff look pretty now it looks like

for the most part we have everything

that we need to stay i know we have the

spinning wheel which is great but let's

also add a little bit of an alert at the

bottom to say hey your transaction has

gone through successfully

so what we're going to do

is we're going to pop back over to our

stake form we're going to wrap

our input and our button into their own

little div here right and that is going

to

put a little bit of space actually

between

our little component here and some other

stuff which is kind of nice

but what we're going to do is the reason

that we're doing this is so that we can

add some alerts this section down here

is where we're going to add some

alerting

to do that we're going to use what's

called a snack bar

and alerts from material ui

you can look at both of these

in the documentation

provides a brief message about app

processes and something like this like

we're just going to say hey you did it

transactions has come through

so what we're going to do is we're going

to import snack bar from material ui

so we're going to do comma

snack bar we're also going to import

alerting

like a little alert box import

alert from

at material

ui lab slash alert and what this is

going to do is it's also going to make

these alerts basically down below our

button and our input we're going to do a

little

little snack bar in here

snack bar and we're going to say this is

going to open when we want to show that

the erc20 is done which we're not

exactly sure how to do that quite yet

we'll have it auto hide

auto hide

duration it's gonna be equal to

about five seconds or five thousand

milliseconds and then on close

we're also going to do some stuff

inside this little snack bar

yes i know we haven't filled this out

yet

actually let's just do this for now

having blanks for now

inside the snack bar

we're going to have some alerts

where we say on close

we're also going to do some stuff

severity is going to be

success

and this alert

is what's going to have our text in here

so we'll say erc

20

token

transfer approved

now approve

the second

transaction

and we're going to have two of these

little snack bars one is gonna be for

the erc20

and one is going to be for staking token

so we're going to call this one

token staked

or excuse me tokens staked

now we need to define when these open

and also

when they close and what to do when they

close

so

this erc20 thing should pop up when

erc20 has been approved so we're going

to want to create

some variable that's going to track

whether or not it's actually been

approved so we'll create another state

hook here

we'll do const

show

erc20

approval

success comma set show

erc20 approval success this is going to

be equal to

use state and we're going to start with

false right we don't want to show this

thing right away

and then we're going to want to do the

same thing for staking tokens so we'll

do const

show

stake

token success

and then set

stake token

success

and this will be also used

and we will start this out with false

and what we're going to do

is right now we're doing this

console.login here right and this is

cute

but we want to actually turn this into

changing show erc20 approval success

right so when this actually goes through

when notification says hey it's been

approved we want to say okay great show

that approval status

so instead of doing console.log here

we're going to say set show

your c

20 approval

success to true

and then we're also going to set show

stake

token success

tokens success

to false

i hopefully i'm spelling this right

set

show

stake token success and let's

make sure that's spelled right

great

and then we're going to do the same

thing but the opposite for staking token

so get rid of console.log

we'll do set show erc 20 approval

success to false and set show stake

erc20 to true

now we'll say the erc21 is going to open

and now we can also have this

notifications thing

track

these two

if these ever change

we'll also run through this

so we'll grab both of these in here so

this use effect will now track these as

well and we'll say show erc20 approval

status will open up

the erc20 alert

and then the show state token success

will open up

the state tokens alert and then for both

of these we'll add a new function called

handle close snack

which will just close it out

and turn those

variables that we just made to false so

we'll do

const

handle close snack

this will be a function

and we'll just say

set show erc20 approval status to false

and then set

show stake

token

i'm just going to copy paste it

this one also to false awesome now if we

go back we refresh our front ends here

looks like i forgot to do an on close

ah okay yep

we'll do handle on closed snack here

for the alerts as well

and there are no

tags there there are no brackets there

so i've got to change that

but now if we go to our front end we'll

do a quick refresh we see everything in

here looking great

let's add one in here we'll hit stake

this will pop up we'll confirm we'll get

the little progress bar which is exactly

what we want and you see here now we get

this little pop-up it says erc20 token

transfer approved now approve the second

transaction this should

uh go away after a few seconds or not

let's just approve this second one oh

looks like it now went away so maybe it

was a little bit longer than five

seconds

and now we can see the token stake

popped up perfect

so we have some pop-ups we have a little

bit of ways to show the user how to do

everything

now you'll notice this doesn't look

exactly like what we see in the github

repo right and this github repo looks a

little bit different it's got this

little slidey bar it's got this second

token farm contract for unstaking

however a lot of what we're going to

keep doing is just going to be a lot of

more front-end stuff and at this point

you pretty much should have everything

that you need to build the rest of the

contract

so what we're going to do

is we're going to have the rest of this

be a challenge if you want if you would

like to complete it you can absolutely

add this second tokenfarb contract with

this unstake all weth bit or unstay golf

fau dap etc

we're going to have two versions

of this front end in here we're going to

have kind of this more cleaned up

version and then we're going to have a

little bit more raw version this one's

the the more raw version all the code is

going to be there so if you want to say

i don't really want to code and follow

this along you can just copy paste the

code or you can say you know what i'm

going to do

this unstaking part all myself and that

will be awesome also fantastic you

should be incredibly proud of yourself

because at the end of the day at this

point you have a way to stake

tokens into a smart contract and build a

front end which is absolutely massive

absolutely fantastic you should be

patting yourself in the back excellent

job excellent job let's go ahead and

wrap this course up welcome back friends

how do you feel good

smarter empowered ready to take on the

world

excellent well you absolutely 100 should

be and you deserve a massive round of

applause because you have just done

something fantastic you have started

your journey and equipped yourself with

the tools to become an incredibly

powerful intelligent smart contract

engineer in the space now i would be

remiss if i didn't comment on security

and audits when it comes to doing your

smart contracts as you know all these

smart contracts are available on chain

for anybody to see and anybody to work

with this means that having a security

mindset is incredibly incredibly

important and i highly recommend if

you're going to go maintenanc